repl.it
JavaScript

A simple Immutable List in JS

fork
loading
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class List {
  constructor(value, tailList) {
    const that = this;
    const headValue = value;
    const tailValue = tailList;
    const sizeValue = 
      tailList 
        ? tailList.size() + 1 
        : headValue
          ? 1 
          : 0;
    
    //Privileged methods
    this.head = () => headValue;
    this.tail = () => tailValue;
    this.size = () => sizeValue;
    
    this.prepend = (v) => new List(v, that);
    this.append = (v) => that.reverse().prepend(v, that).reverse();
    
    this.reverse = () => {
      let val = that;
      let list = new List(val.head());
      val = val.tail();
      while (val) {
        list = list.prepend(val.head(), val);
        val = val.tail();
      }
      return list;
    }
    this.forEach = (func) => {
      let val = that;
      while (val) {
        func(val.head());
        val = val.tail();
      }
    }
    this.map = (func) => {
      let val = that;
      let list;
      while(val) {
        !list 
          ? list = new List(func(val.head()))
          : list = list.prepend(func(val.head()), val);
        val = val.tail();
      }
      return list.reverse();
    }
    this.filter = (func) => {
      let val = that;
      let list;
      while (val) {
        if (func(val.head())) {
          !list
            ? list = new List(val.head())
            : list = new List(val.head(), list)
        }
        val = val.tail()
      }
      return list.reverse();
    }
    this.reduce = (func, zero = null) => {
      let val = that;
      let reducedValue = zero;
      while (val) {
        reducedValue = func(reducedValue, val.head());
        val = val.tail();
      }
      return reducedValue;
    }
  }
  
  //Public methods
  toArray() {
    let arr = [];
    this.forEach(v => arr.push(v));
    return arr;
  }
  
  reduceRight(func, zero) {
    return this.reverse().reduce(func, zero);
  }
  
  //Static methods
  static of(values) {
    let list;
    if (!values) {
      list = new List();
    } else if (values.constructor === Array) {
      values.forEach((v) => !list ? list = new List(v) : list = list.prepend(v));
    } else if (values.constructor === List) {
      return values;
    } else {
      list = new List(values);
    }
    return list.reverse();
  }
}
Native Browser JavaScript