Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Livesense tech night immutable-js at a glance

1,346 views

Published on

immutable-jsのListの実装について

Published in: Engineering
  • Be the first to comment

Livesense tech night immutable-js at a glance

  1. 1. Immutable @ JavaScript
  2. 2. var  me  =  {      name:      "Yuta  Shimakawa",      tw:          "@banana_umai",      qiita:    "bananaumai",      github:  "bananaumai"   };
  3. 3. ではございません
  4. 4. at a glance...
  5. 5. 不変データ Seq List Map OrderedMap Set OrderedSet Record
  6. 6. var  list1  =  Immutable.List.of(1,  2);   var  list2  =  list1.push(3,  4,  5);   var  list3  =  list2.unshift(0);   var  list4  =  list1.concat(list2,  list3);   assert(list1.size  ===  2);   assert(list2.size  ===  5);   assert(list3.size  ===  6);   assert(list4.size  ===  13);   assert(list4.get(0)  ===  1);   https://github.com/facebook/immutable-js/
  7. 7. JSオブジェクトとの 相互変換
  8. 8. var  map1  =  Immutable.Map({a:1,  b:2,  c:3,  d:4});   var  map2  =  Immutable.Map({c:10,  a:20,  t:30});   var  obj  =  {d:100,  o:200,  g:300};   var  map3  =  map1.merge(map2,  obj);   //  Map  {  a:  20,  b:  2,  c:  10,  d:  100,  t:  30,  o:  200,  g:  300  } https://github.com/facebook/immutable-js/ var  deep  = Immutable.Map(   {  a:  1,  b:  2,  c:  Immutable.List.of(3,  4,  5)  });   deep.toObject()  //  {  a:  1,  b:  2,  c:  List  [  3,  4,  5  ]  }   deep.toArray()  //  [  1,  2,  List  [  3,  4,  5  ]  ]   deep.toJS()  //  {  a:  1,  b:  2,  c:  [  3,  4,  5  ]  }   JSON.stringify(deep)  //  '{"a":1,"b":2,"c":[3,4,5]}'
  9. 9. 入れ子データ
  10. 10. var  nested  =  Immutable.fromJS({a:{b:{c:[3,4,5]}}});   //  Map  {  a:  Map  {  b:  Map  {  c:  List  [  3,  4,  5  ]  }  }  }   var  nested2  =  nested.mergeDeep({a:{b:{d:6}}});   //  Map  {  a:  Map  {  b:  Map  {  c:  List  [  3,  4,  5  ],  d:  6  }  }  }   var  nested3  =   nested2.updateIn(['a',  'b',  'd'],  value  =>  value  +  1);   //  Map  {  a:  Map  {  b:  Map  {  c:  List  [  3,  4,  5  ],  d:  7  }  }  }   var  nested4     =  nested3.updateIn(['a',  'b',  'c'],  list  =>  list.push(6));   //  Map  {  a:  Map  {  b:  Map  {  c:  List  [  3,  4,  5,  6  ],  d:  7  }  }  } https://github.com/facebook/immutable-js/
  11. 11. 遅延評価(Seq)
  12. 12. var  oddSquares  =  Immutable.Seq.of(1,2,3,4,5,6,7,8)                                      .filter(x  =>  x  %  2)                                      .map(x  =>  x  *  x);  //  not  computed  here!       oddSquares.get(1);  //  9 https://github.com/facebook/immutable-js/
  13. 13. 同等性
  14. 14. var  map1  =  Immutable.Map({a:1,  b:1,  c:1});   var  map2  =  Immutable.Map({a:1,  b:1,  c:1});   assert(map1  !==  map2);   assert(Immutable.is(map1,  map2)  ===  true); https://github.com/facebook/immutable-js/
  15. 15. JSで不変データ
  16. 16. Immutableなリストを 素朴に実装してみた
  17. 17. cloneによる実装
  18. 18. var  _  =  require('lodash');       function  iPush(arr,  val)  {      var  arr2  =  _.clone(arr);      arr2.push(val);      return  arr2;   }       var  arr  =  [];   for  (var  i  =  0;  i  <  100000;  i++)  {      arr  =  iPush(arr,  i);   } https://gist.github.com/bananaumai/cc2f4d90662aa823ce9e
  19. 19. …は cloneのコストが膨大
  20. 20. Linked Listを実装
  21. 21. var  LinkedList  =  {};   LinkedList.prototype  =  {      head:  function()  {          return  this._head;      },          tail:  function()  {          return  this._tail;      },          push:  function(val)  {          return  new  NonEmptyList(val,  this);      },          forEach:  function(fnc)  {          fnc(this._head);          if  (this._tail  instanceof  NonEmptyList)  {              this._tail.forEach(fnc);          }      }   };   var  EmptyList  =  function()  {      this._head  =  null;      this._tail  =  null;   };   EmptyList.prototype  =  Object.create(LinkedList.prototype);   EmptyList.prototype.constructor  =  EmptyList; https://gist.github.com/bananaumai/164b24b264e0f917007c var  NonEmptyList  =  function(head,  tail)  {      this._head  =  head;      this._tail  =  tail;   };   NonEmptyList.prototype  =   Object.create(LinkedList.prototype);   NonEmptyList.prototype.constructor  =  NonEmptyList;     LinkedList.of  =  function()  {      var  _create  =  function(vals,  list)  {          if  (vals.length  ===  0)  return  list;          var  head  =  vals.shift();          return  _create(vals,  new  NonEmptyList(head,  list))      };          return  _create(          Array.prototype.slice.call(arguments).reverse(),          new  EmptyList()      );   };
  22. 22. var  list  =  LinkedList.of();   for  (var  i  =  0;  i  <  100000;  i++)  {      list  =  list.push(i);   }   https://gist.github.com/bananaumai/164b24b264e0f917007c
  23. 23. …は (&pushはそれなりに速いけど・・・) 末尾再帰最適化 されないので難しい (&Object.ArrayのAPIの実現しようとすると・・・)
  24. 24. immutable-jsのアプローチ
  25. 25. Trie http://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4%E6%9C%A8
  26. 26. (def  list  [0  1  2  3  4  5])
  27. 27. ClojureやScalaが採用 しているアプローチ
  28. 28. Immutable.Listの実装
  29. 29. 文字列のキーの代わりに 添字の数値をbitに変換、 パーティショニング
  30. 30. var  list  =  Immutable.List.of(1,…,1000);   list.get(887); http://hypirion.com/musings/understanding-persistent-vector-pt-2#f1n
  31. 31. 実際は5bitずつ分割するので ↓ O(Log32N)
  32. 32. 実際は32通り http://hypirion.com/musings/understanding-persistent-vector-pt-1
  33. 33. var  list1  =  Immutable.List.of(1,2,3,4,5,6,7,8);   var  list2  =  list1.set(5,  "beef"); list1 list2 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  34. 34. 要素のpush var  list1  =  Immutable.List.of(…);   var  list2  =  list.push(…);
  35. 35. 最右のリーフノードに空きがある場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  36. 36. 最右のリーフノードに空きがない場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  37. 37. rootから伸びるすべてのリーフが埋まっている場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  38. 38. 要素のpop var  list1  =  Immutable.List.of(…);   var  list2  =  list.pop();
  39. 39. 最右のリーフノードが2つ以上の要素を持つ場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  40. 40. 最右のリーフノードが1つの要素を持つ場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  41. 41. 削除後rootノードが1つの要素だけをもつ場合 http://hypirion.com/musings/understanding-persistent-vector-pt-1
  42. 42. 簡単なまとめ
  43. 43. Trieによるリストの表現 O(Log32N)のアクセス 最小限のコピー

×