001/*
002 * Java Genetic Algorithm Library (jenetics-7.2.0).
003 * Copyright (c) 2007-2023 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.util;
021
022import static java.util.Objects.requireNonNull;
023
024import java.util.ArrayList;
025import java.util.List;
026import java.util.function.Function;
027import java.util.function.Supplier;
028import java.util.stream.Collector;
029
030import io.jenetics.internal.collection.Empty;
031import io.jenetics.internal.collection.Empty.EmptyISeq;
032import io.jenetics.internal.util.Requires;
033
034/**
035 * Immutable, ordered, fixed sized sequence.
036 *
037 * @see MSeq
038 *
039 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040 * @since 1.0
041 * @version 5.2
042 */
043public interface ISeq<T>
044        extends
045                Seq<T>,
046                Copyable<MSeq<T>>
047{
048
049        @Override
050        ISeq<T> subSeq(final int start, final int end);
051
052        @Override
053        ISeq<T> subSeq(final int start);
054
055        @Override
056        <B> ISeq<B> map(final Function<? super T, ? extends B> mapper);
057
058        @SuppressWarnings("unchecked")
059        @Override
060        default ISeq<T> append(final T... values) {
061                return append(ISeq.of(values));
062        }
063
064        @Override
065        ISeq<T> append(final Iterable<? extends T> values);
066
067        @SuppressWarnings("unchecked")
068        @Override
069        default ISeq<T> prepend(final T... values) {
070                return prepend(ISeq.of(values));
071        }
072
073        @Override
074        ISeq<T> prepend(final Iterable<? extends T> values);
075
076        /**
077         * Return a shallow copy of this sequence. The sequence elements are not
078         * cloned.
079         *
080         * @return a shallow copy of this sequence.
081         */
082        @Override
083        MSeq<T> copy();
084
085
086        /* *************************************************************************
087         *  Some static helper methods.
088         * ************************************************************************/
089
090        /**
091         * Return a sequence whose elements are all the elements of the first
092         * element followed by all the elements of the sequence.
093         *
094         * @since 5.0
095         *
096         * @param a the first element
097         * @param b the appending sequence
098         * @param <T> the type of the sequence elements
099         * @return the concatenation of the two inputs
100         * @throws NullPointerException if one of the second arguments is
101         *         {@code null}
102         */
103        @SuppressWarnings("unchecked")
104        static <T> ISeq<T> concat(
105                final T a,
106                final ISeq<? extends T> b
107        ) {
108                return ((ISeq<T>)b).prepend(a);
109        }
110
111        /**
112         * Return a sequence whose elements are all the elements of the first
113         * sequence followed by all the elements of the vararg array.
114         *
115         * @since 5.0
116         *
117         * @param a the first sequence
118         * @param b the vararg elements
119         * @param <T> the type of the sequence elements
120         * @return the concatenation of the two inputs
121         * @throws NullPointerException if one of the arguments is {@code null}
122         */
123        @SuppressWarnings("unchecked")
124        static <T> ISeq<T> concat(
125                final ISeq<? extends T> a,
126                final T... b
127        ) {
128                return ((ISeq<T>)a).append(b);
129        }
130
131        /**
132         * Return a sequence whose elements are all the elements of the first
133         * sequence followed by all the elements of the second sequence.
134         *
135         * @since 5.0
136         *
137         * @param a the first sequence
138         * @param b the second sequence
139         * @param <T> the type of the sequence elements
140         * @return the concatenation of the two input sequences
141         * @throws NullPointerException if one of the arguments is {@code null}
142         */
143        @SuppressWarnings("unchecked")
144        static <T> ISeq<T> concat(
145                final ISeq<? extends T> a,
146                final ISeq<? extends T> b
147        ) {
148                return ((ISeq<T>)a).append(b);
149        }
150
151        /* *************************************************************************
152         *  Some static factory methods.
153         * ************************************************************************/
154
155        /**
156         * Single instance of an empty {@code ISeq}.
157         *
158         * @since 3.3
159         */
160        ISeq<?> EMPTY = EmptyISeq.INSTANCE;
161
162        /**
163         * Return an empty {@code ISeq}.
164         *
165         * @since 3.3
166         *
167         * @param <T> the element type of the returned {@code ISeq}.
168         * @return an empty {@code ISeq}.
169         */
170        static <T> ISeq<T> empty() {
171                return Empty.iseq();
172        }
173
174        /**
175         * Returns a {@code Collector} that accumulates the input elements into a
176         * new {@code ISeq}.
177         *
178         * @param <T> the type of the input elements
179         * @return a {@code Collector} which collects all the input elements into an
180         *         {@code ISeq}, in encounter order
181         */
182        static <T> Collector<T, ?, ISeq<T>> toISeq() {
183                return Collector.of(
184                        (Supplier<List<T>>)ArrayList::new,
185                        List::add,
186                        (left, right) -> { left.addAll(right); return left; },
187                        ISeq::of
188                );
189        }
190
191        /**
192         * Returns a {@code Collector} that accumulates the last {@code n} input
193         * elements into a new {@code ISeq}.
194         *
195         * @since 5.0
196         *
197         * @param maxSize the maximal size of the collected sequence
198         * @param <T> the type of the input elements
199         * @return a {@code Collector} which collects maximal {@code maxSize} of the
200         *         input elements into an {@code ISeq}, in encounter order
201         * @throws IllegalArgumentException if the {@code maxSize} is negative
202         */
203        static <T> Collector<T, ?, ISeq<T>> toISeq(final int maxSize) {
204                return Seqs.toSeq(maxSize, Buffer::toSeq);
205        }
206
207        /**
208         * Create a new {@code ISeq} from the given values.
209         *
210         * @param <T> the element type
211         * @param values the array values.
212         * @return a new {@code ISeq} with the given values.
213         * @throws NullPointerException if the {@code values} array is {@code null}.
214         */
215        @SafeVarargs
216        static <T> ISeq<T> of(final T... values) {
217                return values.length == 0
218                        ? empty()
219                        : MSeq.of(values).toISeq();
220        }
221
222        /**
223         * Create a new {@code ISeq} from the given values.
224         *
225         * @param <T> the element type
226         * @param values the array values.
227         * @return a new {@code ISeq} with the given values.
228         * @throws NullPointerException if the {@code values} array is {@code null}.
229         */
230        static <T> ISeq<T> of(final Iterable<? extends T> values) {
231                requireNonNull(values);
232
233                @SuppressWarnings("unchecked")
234                final Iterable<T> vals = (Iterable<T>)values;
235
236                return vals instanceof ISeq<T> seq
237                        ? seq
238                        : vals instanceof MSeq<T> mseq
239                                ? mseq.toISeq()
240                                : MSeq.<T>of(values).toISeq();
241        }
242
243        /**
244         * Creates a new sequence, which is filled with objects created be the given
245         * {@code supplier}.
246         *
247         * @since 3.2
248         *
249         * @param <T> the element type of the sequence
250         * @param supplier the {@code Supplier} which creates the elements, the
251         *        returned sequence is filled with
252         * @param length the length of the returned sequence
253         * @return a new sequence filled with elements given by the {@code supplier}
254         * @throws NegativeArraySizeException if the given {@code length} is
255         *         negative
256         * @throws NullPointerException if the given {@code supplier} is
257         *         {@code null}
258         */
259        static <T> ISeq<T> of(
260                final Supplier<? extends T> supplier,
261                final int length
262        ) {
263                requireNonNull(supplier);
264                Requires.nonNegative(length);
265
266                return length == 0
267                        ? empty()
268                        : MSeq.<T>ofLength(length).fill(supplier).toISeq();
269        }
270
271        /**
272         * Allows a safe (without compiler warning) upcast from {@code B} to
273         * {@code A}. Since {@code ISeq} instances are immutable, an <i>upcast</i>
274         * will be always safe.
275         *
276         * <pre>{@code
277         * // The sequence which we want to case.
278         * final ISeq<? extends Number> ints = ISeq.of(1, 2, 3, 4, 5);
279         *
280         * // This casts are possible without warning.
281         * final ISeq<Object> objects = ISeq.upcast(ints);
282         * final ISeq<Number> numbers = ISeq.upcast(ints);
283         *
284         * // This cast will, of course, still fail.
285         * final ISeq<String> strings = ISeq.upcast(ints);
286         * final ISeq<Integer> integers = ISeq.upcast(ints);
287         * }</pre>
288         *
289         * @since 3.6
290         *
291         * @param seq the sequence to cast safely
292         * @param <A> the <i>super</i>-object type
293         * @param <B> the <i>sub</i>-object type
294         * @return the cast instance of the given {@code seq}
295         */
296        @SuppressWarnings("unchecked")
297        static <A, B extends A> ISeq<A> upcast(final ISeq<B> seq) {
298                return (ISeq<A>)seq;
299        }
300
301}