ã¯ããã«
é¢æ°åèšèªã¯ããã®ã·ã³ãã«ããæå¿«ããããã³äºæž¬å¯èœæ§ã倧奜ãã§ãã ç§ã¯äž»ã«Elixir / Erlang / OTPã§æžããŠãä»ã®èšèªãè©ŠããŸããããErlangãšãã®ã¢ã¯ã¿ãŒã¯ãäŸãã°LispãHaskellããããã£ãšèº«è¿ã§ãã ãåãã®ããã«ãErlang == webã§ãããWebçšã«äœæããããã®ã«ã¯ãã¯ã©ã€ã¢ã³ãåŽã®Webã€ã³ã¿ãŒãã§ã€ã¹ïŒhtmlãcssãjs-contentïŒãå«ãŸããããšããããŸãã æ®å¿µãªãããjsã¯çŸä»£ã®Webã®æšæºã§ããã»ãšãã©ãã¹ãŠã®å Žåãã»ãŒãã¹ãŠã®ã¿ã¹ã¯ã«å¯Ÿå¿ããã©ã€ãã©ãªãããããããå€ããå°ãªãããã¯ã©ã€ã¢ã³ãåŽã®ãã©ãŠã¶ãŒã§äœããè¡ãããã®å¯äžã®å©çšå¯èœãªããŒã«ã§ãã ãããã£ãŠããŸã jsãå¿ èŠã§ãã æåã¯ããã©ã ããšé«éé¢æ°ãããã®ã§ãjsã§æžãã®ã¯ç°¡åã§ãã Erlang / Lisp / Haskellã§æžããŠããããã«æ§æãåŠã³ãæžããŠãããŸãã ç§ãã©ãã»ã©ééã£ãŠãããã
èšèªãéžæããŠãã ãã
ãããããçŽç²ãªjsã¯ã³ãŒãã®èšè¿°ã«ã¯ãŸã£ããé©ããŠããŸããã è±å¯ãªãã©ã±ãããšã»ãã³ãã³ãç®ã®æ³¢çŽããã é¢æ°ã®æ¬äœã®ã©ããã«æžããããreturnããšããèšèã¯ãèšèªã®åœä»€æ§ãæ瀺ããå®å šã«äžéæãªãã³ãã§ãããç§ã®æé«ã®ä¿¡å¿µãç Žå£ããŸãã ãå«ãå€ãã®èšèªããããŸã jsã§ã³ã³ãã€ã«ãããæ©èœçïŒ purescript ã fay ã clojurescript ïŒã ããããç§èªèº«ã®ããã«ãç§ã¯coffeescriptãéžæããŸãããããã¯ãæ©èœè ãšå€§å°è»ã®äž¡æ¹ãç解ã§ããããªã劥åãããªãã·ã§ã³ã§ãã éšåçã«ããã®éžæã¯ãç§ããããžã§ã¯ããæ§ç¯ããããã«coffeescriptã§æžãããbrunchã䜿çšãããšããäºå®ã«ãã£ãŠæ£åœåãããŸããã ããšãã°ãfayãšæ¯èŒãããšãjsããcoffeescriptã«åãæ¿ãããªãŒããŒãããã¯ã»ãŒ0ã§ãã
ãã¬ãŒã ã¯ãŒã¯ã®éžæ
2çªç®ã®èå³æ·±ã質åã¯ãã³ãŒããšhtmlããŒãžãæ¥ç¶ããæ¹æ³ã§ãã æ¬åœã«å€ãã®ãªãã·ã§ã³ããããŸãã å®éã«ã¯ããªãå šäœçã«èŠãã巚倧ãªãã¬ãŒã ã¯ãŒã¯ããããããããŸãã ç§èªèº«ã¯ãã°ããã®éangularjsã䜿çšããŠããŸããããããã€ãã®ç·Žç¿ã®åŸãæãããªæ¬ ç¹ãæããã«ãªããŸããïŒäœããããããã«ã¯ããã£ã¬ã¯ãã£ããå¿ èŠã§ããããã§ãªãå Žåã¯ãç¬èªã®ãã€ã¯ãæžãå¿ èŠããããè§åºŠã®å éšæ§é ãç解ããããšã¯èŠãç®ãããé£ããã§ãççŽã«èŠãŠãã ãã-æãäžè¬çã«äœ¿çšãããng-modelãã£ã¬ã¯ãã£ãã¯åæ¹åããŒã¿ãšãã¬ãŒã³ããŒã·ã§ã³ãã€ã³ãã£ã³ã°ãæäŸããŸãããã¡ã³ã¯ã¿ã®èŠ³ç¹ããã¯ããããã¯ãã¹ãŠã®è§åºŠã¢ããªã±ãŒã·ã§ã³ã«å ããŠãã€ããªãã®ãŒçã«å®å šã«äžæ£ç¢ºã§ãããäžè¬çã«ã«ãã»ã«åã«éåããŸã ã¹ã¯ãŒã¿ãŒãªã©ã¯ãã³ãŒãã«å€§ããªéã¿ãä»ããŠããŸãã ã¯ãããšããã§ãè§åºŠã®æ§èœã¯æ¬åœã«ãŸããŸãã§ãã å°ãåã«ç§ã¯ãªã¢ã¯ã·ã§ã³jsã«äŒããŸãã-ãããŠãç§ã®éžæã¯åœŒã«èœã¡ãŸããã§ããã ãã®ã¢ã€ãã¢ã¯ããã®ã·ã³ãã«ããšå€ããå°ãªããæ©èœçãªå®£èšã¹ã¿ã€ã«ã«æéãåããŸãã ã¢ããªã±ãŒã·ã§ã³ã®æäœäžã«äœããã®åœ¢ã§å€åããå¯èœæ§ã®ããç¶æ ããããŸãã ã¬ã³ããªã³ã°ã®ããã«æã jreactã«æž¡ãã ãã§ãã
widget = require("widget") do_render = () -> React.render(widget(state), domelement) if domelement? render_process = () -> try do_render() catch error console.log error setTimeout(render_process, 500)
ããã ãã§ãïŒ éåžžã«ã·ã³ãã«ã§å¹æçã Reactèªäœãã¬ã³ããªã³ã°ã®æé©åãåŠçããŸããããã®åé¡ã«ã¯ãŸã£ããé¢å¿ããªããããããŸããã æ©èœãã©ãã€ã ãšäžèŽããããã«ç¶æ ãªããžã§ã¯ããå€æŽãããããšãä¿èšŒããããã«æ®ããŸãã ãããŠããããã楜ãã¿ãå§ãŸããŸãã
ãããã³ã®ãã©ãã«
æåã®ãããã»ã©éèŠã§ã¯ãªãåé¡ã¯ããœããjsåã§ãã ã¢ãŒã©ã³ã§ã¯ãã¡ããæãããããããŸãããjsã§ã¯è¡šçŸã倧å€ç³ãèš³ãããŸããã ããšãã°ããã®ãããã¯ã«é¢ããããŸãæçã§ã¯ãªãããããªãé¢çœããããªã§ãã ããããå®éã«ã¯ãåå€æã¯ãã£ãã«è¡ãããŸããïŒå°ãªããšãã³ãŒããè¯ãå ŽåïŒãã ãããç§ã¯ãœããjsåãå€ããå°ãªãããã®ãŸãŸåãå ¥ããŸããã
ç§ãjsã§å°ãç·Žç¿ãå§ãããšããæåã¯ãã¹ãŠãå€ããå°ãªããè¯ãã£ãã®ã§ãããããæç¹ã§äœããã®çç±ã§ã¢ããªã±ãŒã·ã§ã³ãæãéãã«æ©èœããªããªããŸããã ããã«æ·±ãç»ããšãæããããã®ãèŠããŸããã
coffee> map = {a: 1} { a: 1 } coffee> lst = [] [] coffee> lst.push map 1 coffee> map.a = 2 2 coffee> lst.push map 2 coffee> map.a = 3 3 coffee> lst.push map 3 coffee> lst [ { a: 3 }, { a: 3 }, { a: 3 } ]
ãã®å Žåãç§ã¯ç¢ºãã«èŠããšæåŸ ããŠããŸããã
coffee> lst [ { a: 1 }, { a: 2 }, { a: 3 } ]
æ¬åœã«ã·ã§ãã¯ã§ããã ãã³ãŽãjsã®ããŒã¿ã¯å€æŽå¯èœã§ãïŒ ãããŠå€æããããã«ãæ°åãæååãnullãæªå®çŸ©ãããè€éãªãã®ã¯ãã¹ãŠåç §æž¡ããããŸãïŒ
ããããç§ã¯ãããèŠããšã
coffee> [1,2,3] == [1,2,3] false coffee> {a: 1} == {a: 1} false
ããããç§ã®é«ªã¯ãããããªå Žæã§åããã ãã®äººçã¯ç§ãæºåããŸããã§ããã jsã®ããŒã¿åããããšãªã¹ãã¯ãå€ã§ã¯ãªãåç §ã«ãã£ãŠæ¯èŒãããŸãã
ç§ã¯ã©ãããã¹ãããèãå§ããŸããã ããšãã°ãå¯å€æ§ã«é¢ããŠãå®æ°ããŒã¿ãã¢ãªãã£ãŒãã®ã©ã ãé¢æ°ã§ã©ããããïŒããšãã°ãå€ãåæåããïŒããšã決å®ãããŸããããã®ãããªå Žåããããã¯äžè¬ã«å¯å€ã§ã¯ãããŸããã§ããã ããããå¿ èŠãšããåŒã§åçŽã«åŒã³åºãããšãã§ãããããïŒããŒã¿ïŒãå€æŽãããããšãæããããšã¯ãããŸããã
coffee> const_lst = () -> [1,2,3] [Function] coffee> new_lst = const_lst().concat([4,5,6]) [ 1, 2, 3, 4, 5, 6 ] coffee> const_lst() [ 1, 2, 3 ]
ååãšããŠããã¹ãŠã®ããŒã¿ãã©ã ãã§ååž°çã«ã©ãããããå Žåããã¹ãŠã®é¢æ°ãã©ã ããåããã©ã ããè¿ãå Žåãèšèªã¯æ¬åœã«æ©èœããããã«ãªããšæããŸããïŒ ååãšããŠãããã¯è§£æ±ºçã§ãã éåžžã®åã«åºã¥ããŠãããã®ã©ã ãããŒã¿åãèšè¿°ããéåžžã®jsåãžã®ååž°çãªé æ¹åããã³éæ¹åå€æã®ããã®é¢æ°ãèšè¿°ããã ãã§ãªãããããã®ã©ã ãåïŒmapãreduceãfilterãzipãªã©ïŒãæäœããããã®é«éé¢æ°ãèšè¿°ããå¿ èŠããããŸãã åæã«ãã¡ãªã¿ã«ããããã®æ°ããã¿ã€ãã¯æãããããããšã¯ã§ããŸããã ååãšããŠãåé¡ã¯è§£æ±ºå¯èœã§ããããã®ã©ã€ãã©ãªã§ãã§ã«å®è£ ãããŠããæ¹æ³ãªã©ã«ãããããªãèšå€§ã§ãã ãããããã®ã¢ãããŒãã«ã¯éåžžã«é倧ãªæ¬ ç¹ããããŸãã
1ïŒç§ãã¡ã®ã³ãŒãã¯é垞空äžã«äžæãããŸããããä»ã®jsã©ã€ãã©ãªã«äŸåããŠããããããããã«ç®ãåãããã³ã«ãã©ã ãåãéåžžåã«ããŸãã¯ãã®éã«å€æããããšãå¿ããªãã§ãã ããã
2ïŒãã®ã¢ãããŒãã§ã¯ããã¡ãããé¢æ°ã®çŽåºŠãšããŒã¿ã®äžå€æ§ãããçšåºŠä¿èšŒããŸããããã©ã³ã¶ã¯ã·ã§ã³æ§ã¯ãããŸããã
3ïŒãã®ãããªã³ãŒãã¯ãåœä»€åã¢ãããŒãã奜ã人ã«ã¯ããŸãæ確ã§ã¯ãããŸãã
ãããã£ãŠãç§ã¯ãã®ã¢ã€ãã¢ãæŸæ£ããŸããïŒããããå°æ¥çã«ã¯æ³šæããå¿ èŠããããŸãïŒã æããã«ãå¯å€æ§ã®åé¡ãå±æçã«è§£æ±ºããåç §ã«ãã£ãŠããŒã¿ãæ¯èŒããããã«ãjsããŒã¿ãå€ã«ãã£ãŠååž°çã«ã³ããŒããŠæ¯èŒããæ¹æ³ãåŠã¶å¿ èŠããããŸããã
ã¯ããŒã³é¢æ°ãæžããŸã
clone = (some) -> switch Object.prototype.toString.call(some) when "[object Undefined]" then undefined when "[object Boolean]" then some when "[object Number]" then some when "[object String]" then some when "[object Function]" then some.bind({}) when "[object Null]" then null when "[object Array]" then some.map (el) -> clone(el) when "[object Object]" then Object.keys(some).reduce ((acc, k) -> acc[clone(k)] = clone(some[k]); acc), {}
ã€ã³ãŒã«é¢æ°ãæžããŸã
equal = (a, b) -> [type_a, type_b] = [Object.prototype.toString.call(a), Object.prototype.toString.call(b)] if type_a == type_b switch type_a when "[object Undefined]" then a == b when "[object Boolean]" then a == b when "[object Number]" then a == b when "[object String]" then a == b when "[object Function]" then a.toString() == b.toString() when "[object Null]" then a == b when "[object Array]" len_a = a.length len_b = b.length if len_a == len_b [0..len_a].every (n) -> equal(a[n], b[n]) else false when "[object Object]" keys_a = Object.keys(a).sort() keys_b = Object.keys(b).sort() if equal(keys_a, keys_b) keys_a.every (k) -> equal(a[k], b[k]) else false else false
æã£ããããç°¡åã§ããããå¯äžã®ãããããããŒã¿ã«åŸªç°ãªã³ã¯ãããå Žåããã¡ããã¹ã¿ãã¯ãªãŒããŒãããŒãçºçããŸãã ç§ã«ãšã£ãŠãããã¯åºæ¬çã«åé¡ã§ã¯ãããŸãããã埪ç°åç §ããªã©ã®æœè±¡åã䜿çšããŠããªãããã§ãã ããŒã¿ã¯ããŒãã³ã°ã®ããã»ã¹ã§äœããã®æ¹æ³ã§åŠçããããšã¯å¯èœã ãšæããŸããããã¡ããã³ãŒãã¯ããã»ã©åçŽã§ãšã¬ã¬ã³ãã§ã¯ãããŸããã äžè¬çã«ããããã®é¢æ°ãšã©ã€ãã©ãªã®ä»ã®ããã€ãã®é¢æ°ãåéããjsã®ããŒã¿ã®å¯å€æ§ã®åé¡ã¯ãã°ããã®é解決ããããšæããŸãã
俳åª
次ã«ããã©ã³ã¶ã¯ã·ã§ã³ããŒã¿ã®å€æŽãå¿ èŠãªçç±ã«ã€ããŠèª¬æããŸãã å€ããå°ãªããè€éãªç¶æ ããããé¢æ°ãå®è¡ããããã»ã¹ã§ãããå€æŽãããšããŸãã
state.aaa = 20 state.foo = 100 state.bar = state.bar.map (el) -> baz(el, state)
å®éã«ã¯ãç¶æ ãå€æŽããããã»ã¹ã¯ãã¡ãããããè€éã§æéãããããå€éšAPIãžã®éåæåŒã³åºããªã©ãå«ãããšãã§ããŸãã ããããèŠç¹ã¯ãã©ããã§ç¶æ ãå€æŽããããã»ã¹ã®ã©ããã§ãfuncïŒç¶æ ïŒé¢æ°ãåŒã³åºãããå Žåã§ã-äœãèµ·ããã®ã§ããããïŒ ååå€æŽãããç¶æ ã¯æå¹ã§ããïŒ ãŸãã¯ãåä¿®æ£ç¶æ ã®ã·ã³ã°ã«ã¹ã¬ããjsãåå ã§ããŸã£ããååšããããã¹ãŠãæ£åžžã§ããïŒ ããã§ãªãå Žåã¯ïŒ ãŸããå€éšåŒã³åºããè¡ãå¿ èŠããããç¶æ ãå€æŽããéããããäžå¯æ¬ ã§ããå Žåã¯ã©ãããã°ããã§ããïŒ ãã®ãããªé£ãã質åã解決ããããã«ãç¶æ ã®å€æŽããã©ã³ã¶ã¯ã·ã§ã³åããŸãã
ãã®åŸãå€ãã®äººããã¥ãŒããã¯ã¹ã«ã€ããŠèŠããŠãããšæããŸãã ãã¥ãŒããã¯ã¹ãæãåºããŸããã ãããŠãã¬ãŒã¹æ¡ä»¶ã«ã€ããŠã ãããŠããããããã¯ã«ã€ããŠã ãããŠãç§ã¯ããããŸã£ããæãã§ããªãããšã«æ°ä»ããã®ã§ããã¥ãŒããã¯ã¹ãäœæããŸããããErlangèšèªãããactorãã®æŠå¿µãåçšããŸãã jsã®ã³ã³ããã¹ãã§ã¯ãã¢ã¯ã¿ãŒã¯ç¹å®ã®ç¶æ ã«ãã£ãŠåæåããããªããžã§ã¯ãã®äžçš®ã§ããã3ã€ã®ããšã®ã¿ãè¡ããŸã
1ïŒã¢ãªãã£é¢æ°1ãŸãã¯0ã®åœ¢åŒã§ãã¡ãã»ãŒãžããåä¿¡ãããã¥ãŒã«è¿œå ããŸã
2ïŒç¬ç«ããŠã¡ãã»ãŒãžãã¥ãŒããã¬ã€ã¯ãããå éšç¶æ ã«ã¢ãªãã£é¢æ°1ãé©çšããŸãïŒã¢ãªãã£é¢æ°0ãåã«åŒã³åºãããç¶æ ã¯å€åããŸããïŒ-ãããã¯ãã¹ãŠãã¡ãã»ãŒãžãåä¿¡ãããé åºã§å³å¯ã«è¡ãããŸãã
3ïŒèŠæ±ã«å¿ããŠããã®å éšç¶æ ã®å€ãè¿ã
åœç¶ãããŒã¿ã®éå¯å€æ§ãç¶æããããã«ãå€æŽãããã³ã«ç¶æ ãè€è£œããgeté¢æ°ã§ã¯ç¶æ èªäœã§ã¯ãªãããã®ã³ããŒãè¿ããŸãã ãã®ããã以åã«äœæããã©ã€ãã©ãªã䜿çšããŸãã ãã®çµæãã³ãŒããååŸããŸãã
window.Act = (init_state, timeout) -> obj = { # # priv # state: Imuta.clone(init_state) queue: [] init: () -> try @state = Imuta.clone(@queue.shift()(@state)) while @queue.length != 0 catch error console.log "Actor error" console.log error this_ref = this setTimeout((() -> this_ref.init()), timeout) # # public # cast: (func) -> if (func.length == 1) and Imuta.is_function(func) @queue.push(Imuta.clone(func)) @queue.length else throw(new Error("Act expects functions arity == 1 (single arg is actor's state)")) zcast: (func) -> if (func.length == 0) and Imuta.is_function(func) @queue.push( ((state) -> Imuta.clone(func)(); state) ) @queue.length else throw(new Error("Act expects functions arity == 0")) get: () -> Imuta.clone(@state) } obj.init() obj
*ã©ã ãããã¥ãŒã«å ¥ããé¢æ°ã¯ãErlangã®handle_casté¢æ°ãšåæ§ã«ãcastããã³zcastãšåŒã°ããŸã
ãã¹ãŠã®js-dataãè€è£œå¯èœã§ããããã§ã¯ãªãããïŒåŸªç°ãªã³ã¯ãšå€éšã©ã€ãã©ãªãæãåºããŠãã ããïŒãå éšç¶æ ã®ã¯ããŒã³ãåé€ãããã¹ãŠãã©ã€ãã©ãªã«åéããã¢ã¯ã¿ã®ã³ã³ã¹ãã©ã¯ã¿ã®å¥ã®ããŒãžã§ã³ãäœæããŸã ã
ã楜ãã¿ãã ããïŒ
coffee> actor = new Act({a: 1}, "pure", 500) { state: { a: 1 }, queue: [], init: [Function], cast: [Function], zcast: [Function], get: [Function] } coffee> actor.cast((state) -> state.b = 1; state) 1 coffee> actor.get() { a: 1, b: 1 } coffee> actor.cast((state) -> state.c = 1; state) 1 coffee> value = actor.get() { a: 1, b: 1, c: 1 } coffee> value.d = 123 123 coffee> value { a: 1, b: 1, c: 1, d: 123 } coffee> actor.get() { a: 1, b: 1, c: 1 } coffee> actor.zcast(() -> console.log "hello") 1 coffee> hello coffee> actor.get() { a: 1, b: 1, c: 1 } coffee> global_var = {foo: "bar"} { foo: 'bar' } coffee> actor.cast((_) -> global_var) 1 coffee> actor.get() { foo: 'bar' } coffee> global_var.baz = "baf" 'baf' coffee> global_var { foo: 'bar', baz: 'baf' } coffee> actor.get() { foo: 'bar' }
ãã¹ãŠã®ç¶æ å€æŽã¯ããã£ã¹ãé¢æ°ã䜿çšããŠãã¥ãŒãä»ããŠæä»çã«å®è¡ãããŸãã ãçŽç²ãªãããŒãžã§ã³ã§ãããããã«ãgeté¢æ°ããååŸããåŸã®ç¶æ ã«é¢ä¿ãªããç¶æ ã¯ã¢ã¯ã¿ãŒå ã«å®å šã«ã«ãã»ã«åãããŸãïŒå€éšãããã£ã¹ãé¢æ°ã«äœããè¿œå ããå Žåãåæ§ã§ãïŒã ãã©ã³ã¶ã¯ã·ã§ã³ã¯ã¡ãã»ãŒãžãã¥ãŒã«ãã£ãŠæäŸãããŸãã jsã§ã®ã¿ãã»ãšãã©Erlangianã³ãŒããååŸããŸããã äœããã®çç±ã§ç¶æ ã§ã¯ããŒã³ãããŠããªãããŒã¿ã䜿çšããå Žåã¯ãã°ããŒãã«ç¶æ ã§ãããŒãã£ãããŒãžã§ã³ã®ã¢ã¯ã¿ãŒã䜿çšããŸãã ååãšããŠããã®ãããªãªãã·ã§ã³ïŒã¢ã¯ã¿ãŒãä»ããŠå³å¯ã«ç¶æ ãå€æŽããå ŽåïŒã§ãåãå ¥ããããããŒã¿ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®å€æŽãæäŸããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ã ãã§ãªããããæå³ã§ã¢ãããã¯ã§ãããããŒã¿ã®å€æŽã1ã€ã®ã©ã ãã§ã¯ãªã3ã€ïŒããšãã°ãå€éšã©ã€ãã©ãªã§ã®äœããã®å®è¡ã®å ŽåïŒã«è»¢éãããšããèãããããŸããã
actor.cast( { prepare: (state) -> prepare_process(state) apply: (state, args) -> do_work(state, args) rollback: (state, args) -> do_rollback(state, args, error) })
ããããç§ã¯ããããã§ã«éå°ã ãšæã£ããç¹ã«çŸåšã®ããŒãžã§ã³ã§ã¯ãããªãã¯åã«æžãããšãã§ããã®ã§
actor.cast((state) -> args = init_args(state) try do_work(state, args) catch error rollback(state, args, error))
ååæ§ãéåžžã«éèŠãªå Žåã
ãããã«
Jsã¯ç§ãæåã«æã£ãã»ã©çµ¶æçã§ã¯ãªãããšãå€æããŸããã ã©ã ãé¢æ°ã®èåŸã«ã¯å®éã®æ©èœçãªãã¯ãŒããããé©åãªã¬ãã«ã®åšçšãã§ãããªã宣èšçãªã¹ã¿ã€ã«ã§èšè¿°ã§ããŸãã ãããŠãŸãã俳åª+åå¿+ç+ãµã¹+匟䞞ïŒErlang websocketsïŒã䜿çšããç°¡åãªäŸã§ãã æ©èœãç¶æãããŠã§ããç¶æããŸãïŒ
UPD
Habrã®äœäººã¯ãç§ã®ã³ãŒãã®å€ãã®é倧ãªãšã©ãŒãææããŸãããããã«æè¬ããŸã:)æ¬ ç¹ãä¿®æ£ããŸãããããªãã¡ïŒ
1ïŒã¯ããŒã³ãã€ã³ãã£ã³ã°é¢æ°ããããé©åã§æçœãªé¢æ°ã¯ããŒãã³ã°æäœã«çœ®ãæããŸãã
2ïŒequalé¢æ°ã§ã¯ãæåã«ãããã©ãŒãã³ã¹ãåäžãããã¯ãã®ããªãæçœãªãã§ãã¯ãè¿œå ããŸãã:)
3ïŒå€func.toStringïŒïŒã«ããé¢æ°ã®æããªãã§ãã¯ãåé€ããŸãã ã
4ïŒé åãæ¯èŒãããšããããããåå®çŸ©ããããã£ãŒã«ãé·ã䜿çšãããåã«èŠçŽ ãæ°ããŸã
5ïŒãªããžã§ã¯ããä¿åãããšãããObject.keysãé¢æ°ã䜿çšããããªããžã§ã¯ããããã¹ãŠã®ããŒãåéããŸãã ããæå³ã§ã¯ãã³ãŒãã¯ããã«ã¹ãªã ã§æ©èœçã«ãªããŸããã
ãã®ã³ãŒãã®æ¹åã«è²¢ç®ããŠããããã¹ãŠã®äººã«æè¬ããŸãã ã©ã€ãã©ãªã®çŸåšã®ããŒãžã§ã³ã¯ã ãããšããã«ãããŸã ã ç§ã¯ããªãã®åžæãšææ¡ãèããŠããããã§ãã