OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart._internal; | 5 part of dart._internal; |
6 | 6 |
7 /** | 7 /** |
8 * Marker interface for [Iterable] subclasses that have an efficient | 8 * Marker interface for [Iterable] subclasses that have an efficient |
9 * [length] implementation. | 9 * [length] implementation. |
10 */ | 10 */ |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 if (length != this.length) { | 165 if (length != this.length) { |
166 throw new ConcurrentModificationError(this); | 166 throw new ConcurrentModificationError(this); |
167 } | 167 } |
168 } | 168 } |
169 return buffer.toString(); | 169 return buffer.toString(); |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 Iterable<E> where(bool test(E element)) => super.where(test); | 173 Iterable<E> where(bool test(E element)) => super.where(test); |
174 | 174 |
175 Iterable map(f(E element)) => new MappedListIterable(this, f); | 175 Iterable/*<T>*/ map/*<T>*/(/*=T*/f(E element)) => new MappedListIterable<E, dy
namic/*=T*/>(this, f); |
176 | 176 |
177 E reduce(E combine(var value, E element)) { | 177 E reduce(E combine(var value, E element)) { |
178 int length = this.length; | 178 int length = this.length; |
179 if (length == 0) throw IterableElementError.noElement(); | 179 if (length == 0) throw IterableElementError.noElement(); |
180 E value = elementAt(0); | 180 E value = elementAt(0); |
181 for (int i = 1; i < length; i++) { | 181 for (int i = 1; i < length; i++) { |
182 value = combine(value, elementAt(i)); | 182 value = combine(value, elementAt(i)); |
183 if (length != this.length) { | 183 if (length != this.length) { |
184 throw new ConcurrentModificationError(this); | 184 throw new ConcurrentModificationError(this); |
185 } | 185 } |
186 | 186 |
187 } | 187 } |
188 return value; | 188 return value; |
189 } | 189 } |
190 | 190 |
191 fold(var initialValue, combine(var previousValue, E element)) { | 191 /*=T*/ fold/*<T>*/(var/*=T*/ initialValue, /*=T*/combine(var/*=T*/ previousVal
ue, E element)) { |
192 var value = initialValue; | 192 var value = initialValue; |
193 int length = this.length; | 193 int length = this.length; |
194 for (int i = 0; i < length; i++) { | 194 for (int i = 0; i < length; i++) { |
195 value = combine(value, elementAt(i)); | 195 value = combine(value, elementAt(i)); |
196 if (length != this.length) { | 196 if (length != this.length) { |
197 throw new ConcurrentModificationError(this); | 197 throw new ConcurrentModificationError(this); |
198 } | 198 } |
199 } | 199 } |
200 return value; | 200 return value; |
201 } | 201 } |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 | 709 |
710 E singleWhere(bool test(E element), { E orElse() }) { | 710 E singleWhere(bool test(E element), { E orElse() }) { |
711 if (orElse != null) return orElse(); | 711 if (orElse != null) return orElse(); |
712 throw IterableElementError.noElement(); | 712 throw IterableElementError.noElement(); |
713 } | 713 } |
714 | 714 |
715 String join([String separator = ""]) => ""; | 715 String join([String separator = ""]) => ""; |
716 | 716 |
717 Iterable<E> where(bool test(E element)) => this; | 717 Iterable<E> where(bool test(E element)) => this; |
718 | 718 |
719 Iterable map(f(E element)) => const EmptyIterable(); | 719 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => const EmptyIterable(); |
720 | 720 |
721 E reduce(E combine(E value, E element)) { | 721 E reduce(E combine(E value, E element)) { |
722 throw IterableElementError.noElement(); | 722 throw IterableElementError.noElement(); |
723 } | 723 } |
724 | 724 |
725 fold(var initialValue, combine(var previousValue, E element)) { | 725 /*=T*/ fold/*<T>*/(var/*=T*/ initialValue, /*=T*/ combine(var/*=T*/ previousVa
lue, E element)) { |
726 return initialValue; | 726 return initialValue; |
727 } | 727 } |
728 | 728 |
729 Iterable<E> skip(int count) { | 729 Iterable<E> skip(int count) { |
730 RangeError.checkNotNegative(count, "count"); | 730 RangeError.checkNotNegative(count, "count"); |
731 return this; | 731 return this; |
732 } | 732 } |
733 | 733 |
734 Iterable<E> skipWhile(bool test(E element)) => this; | 734 Iterable<E> skipWhile(bool test(E element)) => this; |
735 | 735 |
(...skipping 20 matching lines...) Expand all Loading... |
756 abstract class BidirectionalIterator<T> implements Iterator<T> { | 756 abstract class BidirectionalIterator<T> implements Iterator<T> { |
757 bool movePrevious(); | 757 bool movePrevious(); |
758 } | 758 } |
759 | 759 |
760 /** | 760 /** |
761 * This class provides default implementations for Iterables (including Lists). | 761 * This class provides default implementations for Iterables (including Lists). |
762 * | 762 * |
763 * The uses of this class will be replaced by mixins. | 763 * The uses of this class will be replaced by mixins. |
764 */ | 764 */ |
765 class IterableMixinWorkaround<T> { | 765 class IterableMixinWorkaround<T> { |
766 static bool contains(Iterable iterable, var element) { | 766 static bool contains/*<E>*/(Iterable/*<E>*/ iterable, var element) { |
767 for (final e in iterable) { | 767 for (final e in iterable) { |
768 if (e == element) return true; | 768 if (e == element) return true; |
769 } | 769 } |
770 return false; | 770 return false; |
771 } | 771 } |
772 | 772 |
773 static void forEach(Iterable iterable, void f(o)) { | 773 static void forEach/*<E>*/(Iterable/*<E>*/ iterable, void f(/*=E*/ o)) { |
774 for (final e in iterable) { | 774 for (final e in iterable) { |
775 f(e); | 775 f(e); |
776 } | 776 } |
777 } | 777 } |
778 | 778 |
779 static bool any(Iterable iterable, bool f(o)) { | 779 static bool any/*<E>*/(Iterable/*<E>*/ iterable, bool f(/*=E*/ o)) { |
780 for (final e in iterable) { | 780 for (final e in iterable) { |
781 if (f(e)) return true; | 781 if (f(e)) return true; |
782 } | 782 } |
783 return false; | 783 return false; |
784 } | 784 } |
785 | 785 |
786 static bool every(Iterable iterable, bool f(o)) { | 786 static bool every/*<E>*/(Iterable/*<E>*/ iterable, bool f(/*=E*/ o)) { |
787 for (final e in iterable) { | 787 for (final e in iterable) { |
788 if (!f(e)) return false; | 788 if (!f(e)) return false; |
789 } | 789 } |
790 return true; | 790 return true; |
791 } | 791 } |
792 | 792 |
793 static dynamic reduce(Iterable iterable, | 793 static dynamic/*=E*/ reduce/*<E>*/(Iterable/*<E>*/ iterable, |
794 dynamic combine(previousValue, element)) { | 794 dynamic/*=E*/ combine(/*=E*/previousValue, /*=
E*/element)) { |
795 Iterator iterator = iterable.iterator; | 795 Iterator/*<E>*/ iterator = iterable.iterator; |
796 if (!iterator.moveNext()) throw IterableElementError.noElement(); | 796 if (!iterator.moveNext()) throw IterableElementError.noElement(); |
797 var value = iterator.current; | 797 var value = iterator.current; |
798 while (iterator.moveNext()) { | 798 while (iterator.moveNext()) { |
799 value = combine(value, iterator.current); | 799 value = combine(value, iterator.current); |
800 } | 800 } |
801 return value; | 801 return value; |
802 } | 802 } |
803 | 803 |
804 static dynamic fold(Iterable iterable, | 804 static /*=V*/ fold/*<E, V>*/(Iterable/*<E>*/ iterable, |
805 dynamic initialValue, | 805 dynamic/*=V*/ initialValue, |
806 dynamic combine(dynamic previousValue, element)) { | 806 dynamic/*=V*/ combine(dynamic/*=V*/ previousValue
, /*=E*/element)) { |
807 for (final element in iterable) { | 807 for (final element in iterable) { |
808 initialValue = combine(initialValue, element); | 808 initialValue = combine(initialValue, element); |
809 } | 809 } |
810 return initialValue; | 810 return initialValue; |
811 } | 811 } |
812 | 812 |
813 /** | 813 /** |
814 * Removes elements matching [test] from [list]. | 814 * Removes elements matching [test] from [list]. |
815 * | 815 * |
816 * This is performed in two steps, to avoid exposing an inconsistent state | 816 * This is performed in two steps, to avoid exposing an inconsistent state |
817 * to the [test] function. First the elements to retain are found, and then | 817 * to the [test] function. First the elements to retain are found, and then |
818 * the original list is updated to contain those elements. | 818 * the original list is updated to contain those elements. |
819 */ | 819 */ |
820 static void removeWhereList(List list, bool test(var element)) { | 820 static void removeWhereList/*<E>*/(List/*<E>*/ list, bool test(var/*=E*/ eleme
nt)) { |
821 List retained = []; | 821 List/*<E>*/ retained = []; |
822 int length = list.length; | 822 int length = list.length; |
823 for (int i = 0; i < length; i++) { | 823 for (int i = 0; i < length; i++) { |
824 var element = list[i]; | 824 var element = list[i]; |
825 if (!test(element)) { | 825 if (!test(element)) { |
826 retained.add(element); | 826 retained.add(element); |
827 } | 827 } |
828 if (length != list.length) { | 828 if (length != list.length) { |
829 throw new ConcurrentModificationError(list); | 829 throw new ConcurrentModificationError(list); |
830 } | 830 } |
831 } | 831 } |
832 if (retained.length == length) return; | 832 if (retained.length == length) return; |
833 list.length = retained.length; | 833 list.length = retained.length; |
834 for (int i = 0; i < retained.length; i++) { | 834 for (int i = 0; i < retained.length; i++) { |
835 list[i] = retained[i]; | 835 list[i] = retained[i]; |
836 } | 836 } |
837 } | 837 } |
838 | 838 |
839 static bool isEmpty(Iterable iterable) { | 839 static bool isEmpty/*<E>*/(Iterable/*<E>*/ iterable) { |
840 return !iterable.iterator.moveNext(); | 840 return !iterable.iterator.moveNext(); |
841 } | 841 } |
842 | 842 |
843 static dynamic first(Iterable iterable) { | 843 static dynamic/*=E*/ first/*<E>*/(Iterable/*<E>*/ iterable) { |
844 Iterator it = iterable.iterator; | 844 Iterator/*<E>*/ it = iterable.iterator; |
845 if (!it.moveNext()) { | 845 if (!it.moveNext()) { |
846 throw IterableElementError.noElement(); | 846 throw IterableElementError.noElement(); |
847 } | 847 } |
848 return it.current; | 848 return it.current; |
849 } | 849 } |
850 | 850 |
851 static dynamic last(Iterable iterable) { | 851 static dynamic/*=E*/ last/*<E>*/(Iterable/*<E>*/ iterable) { |
852 Iterator it = iterable.iterator; | 852 Iterator/*<E>*/ it = iterable.iterator; |
853 if (!it.moveNext()) { | 853 if (!it.moveNext()) { |
854 throw IterableElementError.noElement(); | 854 throw IterableElementError.noElement(); |
855 } | 855 } |
856 dynamic result; | 856 var/*=E*/ result; |
857 do { | 857 do { |
858 result = it.current; | 858 result = it.current; |
859 } while(it.moveNext()); | 859 } while(it.moveNext()); |
860 return result; | 860 return result; |
861 } | 861 } |
862 | 862 |
863 static dynamic single(Iterable iterable) { | 863 static dynamic/*=E*/ single/*<E>*/(Iterable/*<E>*/ iterable) { |
864 Iterator it = iterable.iterator; | 864 Iterator/*<E>*/ it = iterable.iterator; |
865 if (!it.moveNext()) throw IterableElementError.noElement(); | 865 if (!it.moveNext()) throw IterableElementError.noElement(); |
866 dynamic result = it.current; | 866 var result = it.current; |
867 if (it.moveNext()) throw IterableElementError.tooMany(); | 867 if (it.moveNext()) throw IterableElementError.tooMany(); |
868 return result; | 868 return result; |
869 } | 869 } |
870 | 870 |
871 static dynamic firstWhere(Iterable iterable, | 871 static dynamic/*=E*/ firstWhere/*<E>*/(Iterable/*<E>*/ iterable, |
872 bool test(dynamic value), | 872 bool test(dynamic/*=E*/ value), |
873 dynamic orElse()) { | 873 dynamic/*=E*/ orElse()) { |
874 for (dynamic element in iterable) { | 874 for (var element in iterable) { |
875 if (test(element)) return element; | 875 if (test(element)) return element; |
876 } | 876 } |
877 if (orElse != null) return orElse(); | 877 if (orElse != null) return orElse(); |
878 throw IterableElementError.noElement(); | 878 throw IterableElementError.noElement(); |
879 } | 879 } |
880 | 880 |
881 static dynamic lastWhere(Iterable iterable, | 881 static dynamic/*=E*/ lastWhere/*<E>*/(Iterable/*<E>*/ iterable, |
882 bool test(dynamic value), | 882 bool test(dynamic/*=E*/ value), |
883 dynamic orElse()) { | 883 dynamic/*=E*/ orElse()) { |
884 dynamic result = null; | 884 dynamic/*=E*/ result = null; |
885 bool foundMatching = false; | 885 bool foundMatching = false; |
886 for (dynamic element in iterable) { | 886 for (var element in iterable) { |
887 if (test(element)) { | 887 if (test(element)) { |
888 result = element; | 888 result = element; |
889 foundMatching = true; | 889 foundMatching = true; |
890 } | 890 } |
891 } | 891 } |
892 if (foundMatching) return result; | 892 if (foundMatching) return result; |
893 if (orElse != null) return orElse(); | 893 if (orElse != null) return orElse(); |
894 throw IterableElementError.noElement(); | 894 throw IterableElementError.noElement(); |
895 } | 895 } |
896 | 896 |
897 static dynamic lastWhereList(List list, | 897 static dynamic/*=E*/ lastWhereList/*<E>*/(List/*<E>*/ list, |
898 bool test(dynamic value), | 898 bool test(dynamic/*=E*/ value), |
899 dynamic orElse()) { | 899 dynamic/*=E*/ orElse()) { |
900 // TODO(floitsch): check that arguments are of correct type? | 900 // TODO(floitsch): check that arguments are of correct type? |
901 for (int i = list.length - 1; i >= 0; i--) { | 901 for (int i = list.length - 1; i >= 0; i--) { |
902 dynamic element = list[i]; | 902 var element = list[i]; |
903 if (test(element)) return element; | 903 if (test(element)) return element; |
904 } | 904 } |
905 if (orElse != null) return orElse(); | 905 if (orElse != null) return orElse(); |
906 throw IterableElementError.noElement(); | 906 throw IterableElementError.noElement(); |
907 } | 907 } |
908 | 908 |
909 static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) { | 909 static dynamic/*=E*/ singleWhere/*<E>*/(Iterable/*<E>*/ iterable, bool test(dy
namic/*=E*/ value)) { |
910 dynamic result = null; | 910 dynamic/*=E*/ result = null; |
911 bool foundMatching = false; | 911 bool foundMatching = false; |
912 for (dynamic element in iterable) { | 912 for (var element in iterable) { |
913 if (test(element)) { | 913 if (test(element)) { |
914 if (foundMatching) { | 914 if (foundMatching) { |
915 throw IterableElementError.tooMany(); | 915 throw IterableElementError.tooMany(); |
916 } | 916 } |
917 result = element; | 917 result = element; |
918 foundMatching = true; | 918 foundMatching = true; |
919 } | 919 } |
920 } | 920 } |
921 if (foundMatching) return result; | 921 if (foundMatching) return result; |
922 throw IterableElementError.noElement(); | 922 throw IterableElementError.noElement(); |
923 } | 923 } |
924 | 924 |
925 static elementAt(Iterable iterable, int index) { | 925 static dynamic/*=E*/ elementAt/*<E>*/(Iterable/*<E>*/ iterable, int index) { |
926 if (index is! int) throw new ArgumentError.notNull("index"); | 926 if (index is! int) throw new ArgumentError.notNull("index"); |
927 RangeError.checkNotNegative(index, "index"); | 927 RangeError.checkNotNegative(index, "index"); |
928 int elementIndex = 0; | 928 int elementIndex = 0; |
929 for (var element in iterable) { | 929 for (var element in iterable) { |
930 if (index == elementIndex) return element; | 930 if (index == elementIndex) return element; |
931 elementIndex++; | 931 elementIndex++; |
932 } | 932 } |
933 throw new RangeError.index(index, iterable, "index", null, elementIndex); | 933 throw new RangeError.index(index, iterable, "index", null, elementIndex); |
934 } | 934 } |
935 | 935 |
936 static String join(Iterable iterable, [String separator]) { | 936 static String join/*<E>*/(Iterable/*<E>*/ iterable, [String separator]) { |
937 StringBuffer buffer = new StringBuffer(); | 937 StringBuffer buffer = new StringBuffer(); |
938 buffer.writeAll(iterable, separator); | 938 buffer.writeAll(iterable, separator); |
939 return buffer.toString(); | 939 return buffer.toString(); |
940 } | 940 } |
941 | 941 |
942 static String joinList(List list, [String separator]) { | 942 static String joinList/*<E>*/(List/*<E>*/ list, [String separator]) { |
943 if (list.isEmpty) return ""; | 943 if (list.isEmpty) return ""; |
944 if (list.length == 1) return "${list[0]}"; | 944 if (list.length == 1) return "${list[0]}"; |
945 StringBuffer buffer = new StringBuffer(); | 945 StringBuffer buffer = new StringBuffer(); |
946 if (separator.isEmpty) { | 946 if (separator.isEmpty) { |
947 for (int i = 0; i < list.length; i++) { | 947 for (int i = 0; i < list.length; i++) { |
948 buffer.write(list[i]); | 948 buffer.write(list[i]); |
949 } | 949 } |
950 } else { | 950 } else { |
951 buffer.write(list[0]); | 951 buffer.write(list[0]); |
952 for (int i = 1; i < list.length; i++) { | 952 for (int i = 1; i < list.length; i++) { |
953 buffer.write(separator); | 953 buffer.write(separator); |
954 buffer.write(list[i]); | 954 buffer.write(list[i]); |
955 } | 955 } |
956 } | 956 } |
957 return buffer.toString(); | 957 return buffer.toString(); |
958 } | 958 } |
959 | 959 |
960 Iterable<T> where(Iterable iterable, bool f(var element)) { | 960 Iterable<T> where(Iterable<T> iterable, bool f(T element)) { |
961 return new WhereIterable<T>(iterable, f); | 961 return new WhereIterable<T>(iterable, f); |
962 } | 962 } |
963 | 963 |
964 static Iterable map(Iterable iterable, f(var element)) { | 964 static Iterable/*<V>*/ map/*<E, V>*/(Iterable/*<E>*/ iterable, /*=V*/ f(var/*=
E*/ element)) { |
965 return new MappedIterable(iterable, f); | 965 return new MappedIterable/*<E, V>*/(iterable, f); |
966 } | 966 } |
967 | 967 |
968 static Iterable mapList(List list, f(var element)) { | 968 static Iterable/*<V>*/ mapList/*<E, V>*/(List/*<E>*/ list, /*=V*/ f(var/*=E*/
element)) { |
969 return new MappedListIterable(list, f); | 969 return new MappedListIterable/*<E, V>*/(list, f); |
970 } | 970 } |
971 | 971 |
972 static Iterable expand(Iterable iterable, Iterable f(var element)) { | 972 static Iterable/*<V>*/ expand/*<E, V>*/(Iterable/*<E>*/ iterable, Iterable/*<V
>*/ f(var/*=E*/ element)) { |
973 return new ExpandIterable(iterable, f); | 973 return new ExpandIterable/*<E, V>*/(iterable, f); |
974 } | 974 } |
975 | 975 |
976 Iterable<T> takeList(List list, int n) { | 976 Iterable<T> takeList(List list, int n) { |
977 // The generic type is currently lost. It will be fixed with mixins. | 977 // The generic type is currently lost. It will be fixed with mixins. |
978 return new SubListIterable<T>(list, 0, n); | 978 return new SubListIterable<T>(list, 0, n); |
979 } | 979 } |
980 | 980 |
981 Iterable<T> takeWhile(Iterable iterable, bool test(var value)) { | 981 Iterable<T> takeWhile(Iterable iterable, bool test(var value)) { |
982 // The generic type is currently lost. It will be fixed with mixins. | 982 // The generic type is currently lost. It will be fixed with mixins. |
983 return new TakeWhileIterable<T>(iterable, test); | 983 return new TakeWhileIterable<T>(iterable, test); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 * Creates errors throw by [Iterable] when the element count is wrong. | 1160 * Creates errors throw by [Iterable] when the element count is wrong. |
1161 */ | 1161 */ |
1162 abstract class IterableElementError { | 1162 abstract class IterableElementError { |
1163 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ | 1163 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ |
1164 static StateError noElement() => new StateError("No element"); | 1164 static StateError noElement() => new StateError("No element"); |
1165 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ | 1165 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ |
1166 static StateError tooMany() => new StateError("Too many elements"); | 1166 static StateError tooMany() => new StateError("Too many elements"); |
1167 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ | 1167 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ |
1168 static StateError tooFew() => new StateError("Too few elements"); | 1168 static StateError tooFew() => new StateError("Too few elements"); |
1169 } | 1169 } |
OLD | NEW |