on master help sign in
Split the List library into Elm and JS code. Do profiling for many functions (map, foldr, filter, length, zipWith, scanl, last, take, reverse) and get some nice speedups.
commite05e9c5acacacb308760f3750f9be06e24d9f9d1 authorevancz <info@elm-lang.org> dateSun 10 Feb 2013, 01:45 (14 years ago) parent784ada6
2 files changed+232−494
core/List.elm+20−14 core/Native/List.js+212−480
core/List.elm+20−14
@@ -9,6 +9,9 @@ head = Native.head
99tail : [a] -> [a]
1010tail = Native.tail
1111
12+last : [a] -> a
13+last = Native.last
14+
1215map : (a -> b) -> [a] -> [b]
1316map = Native.map
1417
@@ -19,16 +22,16 @@ foldr : (a -> b -> b) -> b -> [a] -> b
1922foldr = Native.foldr
2023
2124foldl1 : (a -> a -> a) -> [a] -> a
22−foldl1 f (x::xs) = foldl f x xs
25+foldl1 = Native.foldl1
2326
2427foldr1 : (a -> a -> a) -> [a] -> a
25−foldr1 f (x::xs) = foldr f x xs
28+foldr1 = Native.foldr1
2629
2730scanl : (a -> b -> b) -> b -> [a] -> [b]
28−scanl f b xs = b :: (case xs of { x::xs -> scanl f (f x b) xs; [] -> [] })
31+scanl = Native.scanl
2932
3033scanl1 : (a -> a -> a) -> [a] -> [a]
31−scanl1 f lst = case lst of { x::xs -> scanl f x xs; [] -> [] }
34+scanl1 = Native.scanl1
3235
3336filter : (a -> Bool) -> [a] -> [a]
3437filter = Native.filter
@@ -37,22 +40,25 @@ length : [a] -> Int
3740length = Native.length
3841
3942reverse : [a] -> [a]
40−reverse = foldl (::) []
43+reverse = Native.reverse
4144
42−concat = foldr (++) []
43−concatMap f = concat . map f
45+concat : [[a]] -> [a]
46+concat = Native.foldr (++) []
4447
45−and : [Bool] -> Bool
46−and = foldl (&&) True
48+concatMap : (a -> [b]) -> [a] -> [b]
49+concatMap f = concat . Native.map f
4750
48−or : [Bool] -> Bool
49−or = foldl (||) False
51+all : (a -> Bool) -> [a] -> Bool
52+all pred = Native.all
5053
5154any : (a -> Bool) -> [a] -> Bool
52−any pred = foldl (\x acc -> acc && pred x) True
55+any = Native.any
5356
54−all : (a -> Bool) -> [a] -> Bool
55−all pred = foldl (\x acc -> acc || pred x) False
57+and : [Bool] -> Bool
58+and = Native.all id
59+
60+or : [Bool] -> Bool
61+or = Native.any id
5662
5763sum = foldl (+) 0
5864product = foldl (*) 1
core/Native/List.js+212−480
@@ -1,482 +1,214 @@
1−Elm.List = function() {
1+function nativeList(elm) {
22
3− var throwError = function(f) {
4− throw new Error("Function '" + f + "' expecting a list!");
5− }
3+ function throwError(f) {
4+ throw new Error("Function '" + f + "' expects a non-empty list!");
5+ }
66
7− function length(xs) {
8− var out = 0;
9− while (xs[0] === "Cons") {
10− out += 1;
11− xs = xs[2];
12− }
13− return out;
14− };
15− var reverse = foldl(function(x_72) {
16− return function(y_73) {
17− return["Cons", x_72, y_73]
18− }
19− })(["Nil"]);
20− var concat = foldr(function(x_74) {
21− return function(y_75) {
22− return Value.append(x_74, y_75)
23− }
24− })(["Nil"]);
25− var and = foldl(function(x_77) {
26− return function(y_78) {
27− return x_77 && y_78
28− }
29− })(true);
30− var or = foldl(function(x_79) {
31− return function(y_80) {
32− return x_79 || y_80
33− }
34− })(false);
35− var sum = foldl(function(x_89) {
36− return function(y_90) {
37− return x_89 + y_90
38− }
39− })(0);
40− var product = foldl(function(x_91) {
41− return function(y_92) {
42− return x_91 * y_92
43− }
44− })(1);
45− var maximum = foldl1(function(x) { return function(y) { return Math.max(x,y) } });
46− var minimum = foldl1(function(x) { return function(y) { return Math.min(x,y) } });
47− function head(v) {
48− if (v[0] !== "Cons") {
49− throw new Error("Error: 'head' only accepts lists of length greater than one.");
50− }
51− return v[1];
52− }
53− function tail(v) {
54− if (v[0] !== "Cons") {
55− throw new Error("Error: 'tail' only accepts lists of length greater than one.");
56− }
57− return v[2];
58− }
59− function last(v) {
60− if (v[0] !== "Cons") {
61− throw new Error("Error: 'last' only accepts lists of length greater than one.");
62− }
63− var out = v[1];
64− while (v[0] === "Cons") {
65− out = v[1];
66− v = v[2];
67− }
68− return out;
69− }
70− function map(f) {
71− return function(xs) {
72− if (xs[0] === "Nil") { return xs; }
73− if (xs[0] !== "Cons") { throwError('map'); }
74− var root = ["Cons", f(xs[1]), ["Nil"]];
75− var curr = root;
76− xs = xs[2];
77− while (xs[0]==="Cons") {
78− curr[2] = ["Cons", f(xs[1]), ["Nil"]];
79− xs = xs[2];
80− curr = curr[2];
81− }
82− return root;
83− }
84− }
85− function foldl(f) {
86− return function(b) {
87− return function(xs) {
88− var acc = b;
89− if (xs[0] === "Nil") { return acc; }
90− if (xs[0] !== "Cons") { throwError('foldl'); }
91− while (xs[0] === "Cons") {
92− acc = f(xs[1])(acc);
93− xs = xs[2];
94− }
95− return acc;
96− }
97− }
98− }
99− function foldr(f) {
100− return function(b) {
101− return function(xs) {
102− var acc = b;
103− if (xs[0] === "Nil") { return acc; }
104− if (xs[0] !== "Cons") { throwError('foldr'); }
105− var arr = [];
106− while (xs[0] === "Cons") {
107− arr.push(xs[1]);
108− xs = xs[2];
109− }
110− for (var i = arr.length; i--; ) {
111− acc = f(arr[i])(acc);
112− }
113− return acc;
114− }
115− }
116− }
117− function foldl1(f_49) {
118− return function(_temp_50) {
119− return function(v) {
120− if("Cons" !== v[0]) {
121− return undefined
122− }else {
123− var x_51 = v[1];
124− var xs_52 = v[2];
125− return foldl(f_49)(x_51)(xs_52)
126− }
127− }(_temp_50)
128− }
129− }
130− function foldr1(f) {
131− return function(xs) {
132− if (xs[0] === "Nil") { throw new Error("'foldr1' requires an non-empty list.") }
133− if (xs[0] !== "Cons") { throwError('foldr1'); }
134− var arr = [];
135− while (xs[0] === "Cons") {
136− arr.push(xs[1]);
137− xs = xs[2];
138− }
139− var acc = arr.pop();
140− for (var i = arr.length; i--; ) {
141− acc = f(arr[i])(acc);
142− }
143− return acc;
144− }
145− }
146− function scanl(f) {
147− return function(b) {
148− return function(xs) {
149− if (xs[0] === "Nil") { return ["Cons",b,["Nil"]]; }
150− if (xs[0] !== "Cons") { throwError('scanl'); }
151− var arr = [b];
152− while (xs[0] === "Cons") {
153− b = f(xs[1])(b);
154− arr.push(b);
155− xs = xs[2];
156− }
157− var out = ["Nil"];
158− for (var i = arr.length; i--; ) {
159− out = ["Cons", arr[i], out];
160− }
161− return out;
162− }
163− }
164− }
165− function scanl1(f) {
166− return function(xs) {
167− if (xs[0] !== "Cons") {
168− throw new Error("Error: 'scanl1' requires a list of at least length 1.");
169− }
170− return scanl(f)(xs[1])(xs[2]);
171− }
172− }
173− function filter(pred) {
174− return function(xs) {
175− if (xs[0] === "Nil") { return xs; }
176− if (xs[0] !== "Cons") { throwError('filter'); }
177− var arr = [];
178− while (xs[0] === "Cons") {
179− if (pred(xs[1])) { arr.push(xs[1]); }
180− xs = xs[2];
181− }
182− var out = ["Nil"];
183− for (var i = arr.length; i--; ) {
184− out = ["Cons", arr[i], out];
185− }
186− return out;
187− }
188− }
189− function concatMap(f_76) {
190− return function(x) {
191− return concat(map(f_76)(x))
192− }
193− }
194− function all(pred) {
195− return foldl(function(x) { return function(acc) {
196− return acc && pred(x);
197− };})(true);
198− }
199− function any(pred) {
200− return foldl(function(x) { return function(acc) {
201− return acc || pred(x);
202− };})(false);
203− }
204− function partition(pred_93) {
205− return function(lst_94) {
206− return function() {
207− var v = lst_94;
208− var c = [function(v) {
209− if("Nil" !== v[0]) {
210− return undefined
211− }else {
212− return["Tuple2", ["Nil"], ["Nil"]]
213− }
214− }, function(v) {
215− if("Cons" !== v[0]) {
216− return undefined
217− }else {
218− var x_95 = v[1];
219− var xs_96 = v[2];
220− return function(v) {
221− if("Tuple2" !== v[0]) {
222− return undefined
223− }else {
224− var as_97 = v[1];
225− var bs_98 = v[2];
226− return pred_93(x_95) ? ["Tuple2", ["Cons", x_95, as_97], bs_98] : ["Tuple2", as_97, ["Cons", x_95, bs_98]]
227− }
228− }(partition(pred_93)(xs_96))
229− }
230− }];
231− for(var i = c.length;i--;) {
232− var r = c[i](v);
233− if(r !== undefined) {
234− return r
235− }
236− }
237− }()
238− }
239− }
240− function zipWith(f) {
241− return function(listA) {
242− return function(listB) {
243− if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
244− if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zipWith'); }
245− var arr = [];
246− while (listA[0] === "Cons" && listB[0] === "Cons") {
247− arr.push(f(listA[1])(listB[1]));
248− listA = listA[2];
249− listB = listB[2];
250− }
251− var out = ["Nil"];
252− for (var i = arr.length; i--; ) {
253− out = ["Cons", arr[i], out];
254− }
255− return out;
256− }
257− }
258− }
259− function zip(listA) {
260− return function(listB) {
261− if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
262− if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zip'); }
263− var arr = [];
264− while (listA[0] === "Cons" && listB[0] === "Cons") {
265− arr.push(["Tuple2", listA[1], listB[1]]);
266− listA = listA[2];
267− listB = listB[2];
268− }
269− var out = ["Nil"];
270− for (var i = arr.length; i--; ) {
271− out = ["Cons", arr[i], out];
272− }
273− return out;
274− }
275− }
276− function unzip(pairs_112) {
277− return function() {
278− var v = pairs_112;
279− var c = [function(v) {
280− if("Nil" !== v[0]) {
281− return undefined
282− }else {
283− return["Tuple2", ["Nil"], ["Nil"]]
284− }
285− }, function(v) {
286− if("Cons" !== v[0]) {
287− return undefined
288− }else {
289− var p_113 = v[1];
290− var ps_114 = v[2];
291− return function(v) {
292− if("Tuple2" !== v[0]) {
293− return undefined
294− }else {
295− if("Tuple2" !== v[1][0]) {
296− return undefined
297− }else {
298− var x_115 = v[1][1];
299− var y_116 = v[1][2];
300− if("Tuple2" !== v[2][0]) {
301− return undefined
302− }else {
303− var xs_117 = v[2][1];
304− var ys_118 = v[2][2];
305− return["Tuple2", ["Cons", x_115, xs_117], ["Cons", y_116, ys_118]]
306− }
307− }
308− }
309− }(["Tuple2", p_113, unzip(ps_114)])
310− }
311− }];
312− for(var i = c.length;i--;) {
313− var r = c[i](v);
314− if(r !== undefined) {
315− return r
316− }
317− }
318− }()
319− }
320− function intersperse(sep_119) {
321− return function(xs_120) {
322− return function() {
323− var v = xs_120;
324− var c = [function(v) {
325− if("Nil" !== v[0]) {
326− return undefined
327− }else {
328− return["Nil"]
329− }
330− }, function(v) {
331− if("Cons" !== v[0]) {
332− return undefined
333− }else {
334− var a_124 = v[1];
335− if("Nil" !== v[2][0]) {
336− return undefined
337− }else {
338− return["Cons", a_124, ["Nil"]]
339− }
340− }
341− }, function(v) {
342− if("Cons" !== v[0]) {
343− return undefined
344− }else {
345− var a_121 = v[1];
346− if("Cons" !== v[2][0]) {
347− return undefined
348− }else {
349− var b_122 = v[2][1];
350− var cs_123 = v[2][2];
351− return["Cons", a_121, ["Cons", sep_119, intersperse(sep_119)(["Cons", b_122, cs_123])]]
352− }
353− }
354− }];
355− for(var i = c.length;i--;) {
356− var r = c[i](v);
357− if(r !== undefined) {
358− return r
359− }
360− }
361− }()
362− }
363− }
364− function intercalate(sep_125) {
365− return function(xs_126) {
366− return function() {
367− var v = xs_126;
368− var c = [function(v) {
369− if("Nil" !== v[0]) {
370− return undefined
371− }else {
372− return["Nil"]
373− }
374− }, function(v) {
375− if("Cons" !== v[0]) {
376− return undefined
377− }else {
378− var a_130 = v[1];
379− if("Nil" !== v[2][0]) {
380− return undefined
381− }else {
382− return a_130
383− }
384− }
385− }, function(v) {
386− if("Cons" !== v[0]) {
387− return undefined
388− }else {
389− var a_127 = v[1];
390− if("Cons" !== v[2][0]) {
391− return undefined
392− }else {
393− var b_128 = v[2][1];
394− var cs_129 = v[2][2];
395− return Value.append(a_127, Value.append(sep_125, intercalate(sep_125)(["Cons", b_128, cs_129])))
396− }
397− }
398− }];
399− for(var i = c.length;i--;) {
400− var r = c[i](v);
401− if(r !== undefined) {
402− return r
403− }
404− }
405− }()
406− }
407− }
408− function sort(xs) {
409− if (xs[0] === "Nil") { return xs; }
410− if (xs[0] !== "Cons") { throwError('sort'); }
411− var arr = [];
412− while (xs[0] === "Cons") {
413− arr.push(xs[1]);
414− xs = xs[2];
415− }
416− arr.sort(function(a,b) { return a - b});
417− var out = ["Nil"];
418− for (var i = arr.length; i--; ) {
419− out = [ "Cons", arr[i], out ];
420− }
421− return out;
422− }
423− function take(n) { return function(xs) {
424− if (n <= 0) { return ["Nil"]; }
425− if (xs[0] === "Nil") { return xs; }
426− if (xs[0] !== "Cons") { throwError('take'); }
427− var out = [ "Cons", xs[1], ["Nil"] ];
428− var temp = out;
429− xs = xs[2];
430− --n;
431− while (xs[0] === "Cons" && n > 0) {
432− temp[2] = [ "Cons", xs[1], ["Nil"] ];
433− temp = temp[2];
434− xs = xs[2];
435− --n;
436− }
437− return out;
438− };
439− }
440− function drop(n) { return function(xs) {
441− if (xs[0] === "Nil") { return xs; }
442− if (xs[0] !== "Cons") { throwError('drop'); }
443− while (xs[0] === "Cons" && n > 0) {
444− xs = xs[2];
445− --n;
446− }
447− return xs;
448− };
449− }
450− return {head:head,
451− tail:tail,
452− last:last,
453− map:map,
454− foldl:foldl,
455− foldr:foldr,
456− foldl1:foldl1,
457− foldr1:foldr1,
458− scanl:scanl,
459− scanl1:scanl1,
460− filter:filter,
461− length:length,
462− reverse:reverse,
463− concat:concat,
464− concatMap:concatMap,
465− and:and,
466− or:or,
467− all:all,
468− any:any,
469− sum:sum,
470− product:product,
471− maximum:maximum,
472− minimum:minimum,
473− partition:partition,
474− zipWith:zipWith,
475− zip:zip,
476− unzip:unzip,
477− intersperse:intersperse,
478− intercalate:intercalate,
479− sort:sort,
480− take:take,
481− drop:drop};
482−}();
7+ function toArray(xs) {
8+ var out = [];
9+ while (xs[0] === "Cons") {
10+ out.push(xs[1]);
11+ xs = xs[2];
12+ }
13+ return out;
14+ }
15+
16+ function fromArray(arr) {
17+ var out = ["Nil"];
18+ for (var i = arr.length; i--; ) {
19+ out = ["Cons", arr[i], out];
20+ }
21+ return out;
22+ }
23+
24+ function head(v) { v[0] === "Nil" ? throwError('head') : return v[1]; }
25+ function tail(v) { v[0] === "Nil" ? throwError('tail') : return v[2]; }
26+
27+ function last(xs) {
28+ if (xs[0] === "Nil") { throwError('last'); }
29+ var out = xs[1];
30+ while (xs[0] === "Cons") {
31+ out = xs[1];
32+ xs = xs[2];
33+ }
34+ return out;
35+ }
36+
37+ function map(f) { return function(xs) {
38+ var arr = [];
39+ while (xs[0] === "Cons") {
40+ arr.push(f(xs[1]));
41+ xs = xs[2];
42+ }
43+ return fromArray(arr);
44+ }
45+ }
46+
47+ function foldl(f) { return function(b) { return function(xs) {
48+ var acc = b;
49+ while (xs[0] === "Cons") {
50+ acc = f(xs[1])(acc);
51+ xs = xs[2];
52+ }
53+ return acc;
54+ }
55+ }
56+ }
57+
58+ function foldr(f) { return function(b) { return function(xs) {
59+ var arr = toArray(xs);
60+ var acc = b;
61+ for (var i = arr.length; i--; ) {
62+ acc = f(arr[i])(acc);
63+ }
64+ return acc;
65+ }
66+ }
67+ }
68+
69+ function foldl1(f) { return function(xs) {
70+ xs[0] === "Nil" ? throwError('foldl1') : return foldl(f)(xs[1])(xs[2]);
71+ }
72+ }
73+
74+ function foldr1(f) { return function(xs) {
75+ if (xs[0] === "Nil") { throwError('foldr1'); }
76+ var arr = toArray(xs);
77+ var acc = arr.pop();
78+ for (var i = arr.length; i--; ) {
79+ acc = f(arr[i])(acc);
80+ }
81+ return acc;
82+ }
83+ }
84+
85+ function scanl(f) { return function(b) { return function(xs) {
86+ var arr = toArray(xs);
87+ arr.unshift(b);
88+ var len = arr.length;
89+ for (var i = 1; i < len; ++i) {
90+ arr[i] = f(arr[i])(arr[i-1]);
91+ }
92+ return fromArray(arr);
93+ }
94+ }
95+ }
96+
97+ function scanl1(f) { return function(xs) {
98+ xs[0] === "Nil" ? throwError('scanl1') : return scanl(f)(xs[1])(xs[2]);
99+ }
100+ }
101+
102+ function filter(pred) { return function(xs) {
103+ var arr = [];
104+ while (xs[0] === "Cons") {
105+ if (pred(xs[1])) { arr.push(xs[1]); }
106+ xs = xs[2];
107+ }
108+ return fromArray(arr);
109+ }
110+ }
111+
112+ function length(xs) {
113+ var out = 0;
114+ while (xs[0] === "Cons") {
115+ out += 1;
116+ xs = xs[2];
117+ }
118+ return out;
119+ }
120+
121+ function reverse(xs) { return fromArray(toArray(xs).reverse()); }
122+
123+ function all(pred) { return function(xs) {
124+ while (xs[0] === "Cons") {
125+ if (!pred(xs[1])) return false;
126+ xs = xs[2];
127+ }
128+ return true;
129+ }
130+ }
131+
132+ function any(pred) { return function(xs) {
133+ while (xs[0] === "Cons") {
134+ if (pred(xs[1])) return true;
135+ xs = xs[2];
136+ }
137+ return false;
138+ }
139+ }
140+
141+ function zipWith(f) { return function(xs) { return function(ys) {
142+ var arr = [];
143+ while (xs[0] === "Cons" && ys[0] === "Cons") {
144+ arr.push(f(xs[1])(ys[1]));
145+ xs = xs[2];
146+ ys = ys[2];
147+ }
148+ return fromArray(arr);
149+ }
150+ }
151+ }
152+
153+ function zip(xs) { return function(ys) {
154+ var arr = [];
155+ while (xs[0] === "Cons" && ys[0] === "Cons") {
156+ arr.push(["Tuple2",xs[1],ys[1]]);
157+ xs = xs[2];
158+ ys = ys[2];
159+ }
160+ return fromArray(arr);
161+ }
162+ }
163+
164+ function sort(xs) {
165+ return fromArray(toArray(xs).sort(function(a,b) { return a - b}));
166+ }
167+
168+ function take(n) { return function(xs) {
169+ var arr = [];
170+ while (xs[0] === "Cons" && n > 0) {
171+ arr.push(xs[1]);
172+ xs = xs[2];
173+ --n;
174+ }
175+ return fromArray(arr);
176+ }
177+ }
178+
179+ function drop(n) { return function(xs) {
180+ while (xs[0] === "Cons" && n > 0) {
181+ xs = xs[2];
182+ --n;
183+ }
184+ return xs;
185+ }
186+ }
187+
188+ function concatA(
189+
190+ elm.Native.List = {
191+ head:head,
192+ tail:tail,
193+ last:last,
194+
195+ map:map,
196+ foldl:foldl,
197+ foldr:foldr,
198+
199+ foldl1:foldl1,
200+ foldr1:foldr1,
201+ scanl:scanl,
202+ scanl1:scanl1,
203+ filter:filter,
204+ length:length,
205+ reverse:reverse,
206+
207+ all:all,
208+ any:any,
209+ zipWith:zipWith,
210+ zip:zip,
211+ sort:sort,
212+ take:take,
213+ drop:drop};
214+}