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.
e05e9c5evancz
core/List.elm+20−14
@@ -9,6 +9,9 @@ head = Native.head
9tail : [a] -> [a]
9tail : [a] -> [a]
10tail = Native.tail
10tail = Native.tail
11
11
12+last : [a] -> a
13+last = Native.last
14+
12map : (a -> b) -> [a] -> [b]
15map : (a -> b) -> [a] -> [b]
13map = Native.map
16map = Native.map
14
17
@@ -19,16 +22,16 @@ foldr : (a -> b -> b) -> b -> [a] -> b
19foldr = Native.foldr
22foldr = Native.foldr
20
23
21foldl1 : (a -> a -> a) -> [a] -> a
24foldl1 : (a -> a -> a) -> [a] -> a
22−foldl1 f (x::xs) = foldl f x xs
25+foldl1 = Native.foldl1
23
26
24foldr1 : (a -> a -> a) -> [a] -> a
27foldr1 : (a -> a -> a) -> [a] -> a
25−foldr1 f (x::xs) = foldr f x xs
28+foldr1 = Native.foldr1
26
29
27scanl : (a -> b -> b) -> b -> [a] -> [b]
30scanl : (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
29
32
30scanl1 : (a -> a -> a) -> [a] -> [a]
33scanl1 : (a -> a -> a) -> [a] -> [a]
31−scanl1 f lst = case lst of { x::xs -> scanl f x xs; [] -> [] }
34+scanl1 = Native.scanl1
32
35
33filter : (a -> Bool) -> [a] -> [a]
36filter : (a -> Bool) -> [a] -> [a]
34filter = Native.filter
37filter = Native.filter
@@ -37,22 +40,25 @@ length : [a] -> Int
37length = Native.length
40length = Native.length
38
41
39reverse : [a] -> [a]
42reverse : [a] -> [a]
40−reverse = foldl (::) []
43+reverse = Native.reverse
41
44
42−concat = foldr (++) []
45+concat : [[a]] -> [a]
43−concatMap f = concat . map f
46+concat = Native.foldr (++) []
44
47
45−and : [Bool] -> Bool
48+concatMap : (a -> [b]) -> [a] -> [b]
46−and = foldl (&&) True
49+concatMap f = concat . Native.map f
47
50
48−or : [Bool] -> Bool
51+all : (a -> Bool) -> [a] -> Bool
49−or = foldl (||) False
52+all pred = Native.all
50
53
51any : (a -> Bool) -> [a] -> Bool
54any : (a -> Bool) -> [a] -> Bool
52−any pred = foldl (\x acc -> acc && pred x) True
55+any = Native.any
53
56
54−all : (a -> Bool) -> [a] -> Bool
57+and : [Bool] -> Bool
55−all pred = foldl (\x acc -> acc || pred x) False
58+and = Native.all id
59+
60+or : [Bool] -> Bool
61+or = Native.any id
56
62
57sum = foldl (+) 0
63sum = foldl (+) 0
58product = foldl (*) 1
64product = foldl (*) 1
core/Native/List.js+212−480
@@ -1,482 +1,214 @@
1−Elm.List = function() {
1+function nativeList(elm) {
2
2
3− var throwError = function(f) {
3+ function throwError(f) {
4− throw new Error("Function '" + f + "' expecting a list!");
4+ throw new Error("Function '" + f + "' expects a non-empty list!");
5− }
5+ }
6
6
7− function length(xs) {
7+ function toArray(xs) {
8− var out = 0;
8+ var out = [];
9− while (xs[0] === "Cons") {
9+ while (xs[0] === "Cons") {
10− out += 1;
10+ out.push(xs[1]);
11− xs = xs[2];
11+ xs = xs[2];
12− }
12+ }
13− return out;
13+ return out;
14− };
14+ }
15− var reverse = foldl(function(x_72) {
15+
16− return function(y_73) {
16+ function fromArray(arr) {
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"]);
17+ var out = ["Nil"];
25− var and = foldl(function(x_77) {
18+ for (var i = arr.length; i--; ) {
26− return function(y_78) {
19+ out = ["Cons", arr[i], out];
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− }
20+ }
82− return root;
21+ return out;
83− }
22+ }
84− }
23+
85− function foldl(f) {
24+ function head(v) { v[0] === "Nil" ? throwError('head') : return v[1]; }
86− return function(b) {
25+ function tail(v) { v[0] === "Nil" ? throwError('tail') : return v[2]; }
87− return function(xs) {
26+
88− var acc = b;
27+ function last(xs) {
89− if (xs[0] === "Nil") { return acc; }
90− if (xs[0] !== "Cons") { throwError('foldl'); }
28+ if (xs[0] === "Nil") { throwError('last'); }
29+ var out = xs[1];
91− while (xs[0] === "Cons") {
30+ while (xs[0] === "Cons") {
92− acc = f(xs[1])(acc);
31+ out = xs[1];
93− xs = xs[2];
32+ xs = xs[2];
94− }
33+ }
95− return acc;
34+ return out;
96− }
97− }
35+ }
98− }
36+
99− function foldr(f) {
100− return function(b) {
101− return function(xs) {
37+ function map(f) { return function(xs) {
102− var acc = b;
38+ var arr = [];
103− if (xs[0] === "Nil") { return acc; }
39+ while (xs[0] === "Cons") {
104− if (xs[0] !== "Cons") { throwError('foldr'); }
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) {
105− var arr = [];
48+ var acc = b;
106− while (xs[0] === "Cons") {
49+ while (xs[0] === "Cons") {
107− arr.push(xs[1]);
50+ acc = f(xs[1])(acc);
108− xs = xs[2];
51+ xs = xs[2];
52+ }
53+ return acc;
54+ }
55+ }
109− }
56+ }
57+
58+ function foldr(f) { return function(b) { return function(xs) {
59+ var arr = toArray(xs);
60+ var acc = b;
110− for (var i = arr.length; i--; ) {
61+ for (var i = arr.length; i--; ) {
111− acc = f(arr[i])(acc);
62+ acc = f(arr[i])(acc);
112− }
63+ }
113− return acc;
64+ return acc;
114− }
65+ }
115− }
66+ }
116− }
67+ }
117− function foldl1(f_49) {
68+
118− return function(_temp_50) {
119− return function(v) {
69+ function foldl1(f) { return function(xs) {
120− if("Cons" !== v[0]) {
70+ xs[0] === "Nil" ? throwError('foldl1') : return foldl(f)(xs[1])(xs[2]);
121− return undefined
71+ }
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− }
72+ }
129− }
73+
130− function foldr1(f) {
131− return function(xs) {
74+ function foldr1(f) { return function(xs) {
132− if (xs[0] === "Nil") { throw new Error("'foldr1' requires an non-empty list.") }
133− if (xs[0] !== "Cons") { throwError('foldr1'); }
75+ if (xs[0] === "Nil") { throwError('foldr1'); }
134− var arr = [];
76+ var arr = toArray(xs);
135− while (xs[0] === "Cons") {
136− arr.push(xs[1]);
137− xs = xs[2];
138− }
139− var acc = arr.pop();
77+ var acc = arr.pop();
140− for (var i = arr.length; i--; ) {
78+ for (var i = arr.length; i--; ) {
141− acc = f(arr[i])(acc);
79+ acc = f(arr[i])(acc);
142− }
80+ }
143− return acc;
81+ return acc;
144− }
82+ }
145− }
83+ }
146− function scanl(f) {
84+
147− return function(b) {
148− return function(xs) {
85+ function scanl(f) { return function(b) { return function(xs) {
149− if (xs[0] === "Nil") { return ["Cons",b,["Nil"]]; }
150− if (xs[0] !== "Cons") { throwError('scanl'); }
151− var arr = [b];
86+ var arr = toArray(xs);
152− while (xs[0] === "Cons") {
153− b = f(xs[1])(b);
154− arr.push(b);
87+ arr.unshift(b);
155− xs = xs[2];
88+ var len = arr.length;
156− }
157− var out = ["Nil"];
158− for (var i = arr.length; i--; ) {
89+ for (var i = 1; i < len; ++i) {
159− out = ["Cons", arr[i], out];
90+ arr[i] = f(arr[i])(arr[i-1]);
160− }
91+ }
161− return out;
92+ return fromArray(arr);
162− }
93+ }
163− }
94+ }
164− }
95+ }
165− function scanl1(f) {
96+
166− return function(xs) {
97+ function scanl1(f) { 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]);
98+ xs[0] === "Nil" ? throwError('scanl1') : return scanl(f)(xs[1])(xs[2]);
171− }
99+ }
172− }
100+ }
101+
173− function filter(pred) {
102+ function filter(pred) { return function(xs) {
174− return function(xs) {
175− if (xs[0] === "Nil") { return xs; }
176− if (xs[0] !== "Cons") { throwError('filter'); }
177− var arr = [];
103+ var arr = [];
178− while (xs[0] === "Cons") {
104+ while (xs[0] === "Cons") {
179− if (pred(xs[1])) { arr.push(xs[1]); }
105+ if (pred(xs[1])) { arr.push(xs[1]); }
180− xs = xs[2];
106+ xs = xs[2];
181− }
107+ }
182− var out = ["Nil"];
108+ return fromArray(arr);
183− for (var i = arr.length; i--; ) {
109+ }
184− out = ["Cons", arr[i], out];
110+ }
111+
112+ function length(xs) {
113+ var out = 0;
114+ while (xs[0] === "Cons") {
115+ out += 1;
116+ xs = xs[2];
185− }
117+ }
186− return out;
118+ return out;
187− }
119+ }
188− }
120+
189− function concatMap(f_76) {
121+ function reverse(xs) { return fromArray(toArray(xs).reverse()); }
190− return function(x) {
122+
191− return concat(map(f_76)(x))
192− }
193− }
194− function all(pred) {
123+ function all(pred) { return function(xs) {
195− return foldl(function(x) { return function(acc) {
124+ while (xs[0] === "Cons") {
196− return acc && pred(x);
125+ if (!pred(xs[1])) return false;
197− };})(true);
126+ xs = xs[2];
198− }
127+ }
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
128+ return true;
403− }
129+ }
404− }
130+ }
405− }()
131+
406− }
407− }
408− function sort(xs) {
132+ function any(pred) { return function(xs) {
409− if (xs[0] === "Nil") { return xs; }
133+ while (xs[0] === "Cons") {
410− if (xs[0] !== "Cons") { throwError('sort'); }
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) {
411− var arr = [];
142+ var arr = [];
412− while (xs[0] === "Cons") {
143+ while (xs[0] === "Cons" && ys[0] === "Cons") {
413− arr.push(xs[1]);
144+ arr.push(f(xs[1])(ys[1]));
414− xs = xs[2];
145+ xs = xs[2];
415− }
146+ ys = ys[2];
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− }
147+ }
421− return out;
148+ return fromArray(arr);
422− }
149+ }
150+ }
151+ }
152+
423− function take(n) { return function(xs) {
153+ function zip(xs) { return function(ys) {
424− if (n <= 0) { return ["Nil"]; }
154+ var arr = [];
425− if (xs[0] === "Nil") { return xs; }
155+ while (xs[0] === "Cons" && ys[0] === "Cons") {
426− if (xs[0] !== "Cons") { throwError('take'); }
156+ arr.push(["Tuple2",xs[1],ys[1]]);
427− var out = [ "Cons", xs[1], ["Nil"] ];
157+ xs = xs[2];
428− var temp = out;
158+ ys = ys[2];
429− xs = xs[2];
159+ }
430− --n;
160+ return fromArray(arr);
431− while (xs[0] === "Cons" && n > 0) {
161+ }
432− temp[2] = [ "Cons", xs[1], ["Nil"] ];
162+ }
433− temp = temp[2];
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]);
434− xs = xs[2];
172+ xs = xs[2];
435− --n;
173+ --n;
436− }
174+ }
437− return out;
175+ return fromArray(arr);
438− };
176+ }
439− }
177+ }
178+
440− function drop(n) { return function(xs) {
179+ 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) {
180+ while (xs[0] === "Cons" && n > 0) {
444− xs = xs[2];
181+ xs = xs[2];
445− --n;
182+ --n;
446− }
183+ }
447− return xs;
184+ return xs;
448− };
185+ }
449− }
186+ }
187+
188+ function concatA(
189+
190+ elm.Native.List = {
450− return {head:head,
191+ head:head,
451− tail:tail,
192+ tail:tail,
452− last:last,
193+ last:last,
194+
453− map:map,
195+ map:map,
454− foldl:foldl,
196+ foldl:foldl,
455− foldr:foldr,
197+ foldr:foldr,
198+
456− foldl1:foldl1,
199+ foldl1:foldl1,
457− foldr1:foldr1,
200+ foldr1:foldr1,
458− scanl:scanl,
201+ scanl:scanl,
459− scanl1:scanl1,
202+ scanl1:scanl1,
460− filter:filter,
203+ filter:filter,
461− length:length,
204+ length:length,
462− reverse:reverse,
205+ reverse:reverse,
463− concat:concat,
206+
464− concatMap:concatMap,
465− and:and,
466− or:or,
467− all:all,
207+ all:all,
468− any:any,
208+ any:any,
469− sum:sum,
470− product:product,
471− maximum:maximum,
472− minimum:minimum,
473− partition:partition,
474− zipWith:zipWith,
209+ zipWith:zipWith,
475− zip:zip,
210+ zip:zip,
476− unzip:unzip,
477− intersperse:intersperse,
478− intercalate:intercalate,
479− sort:sort,
211+ sort:sort,
480− take:take,
212+ take:take,
481− drop:drop};
213+ drop:drop};
482−}();
214+}