| 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 |