Developing with shadow-cljs dev-server and :proxy-url
Problem
Shadow-cljs has an option for the dev-http server named :proxy-url. With this option, all requests for files not served on the dev-http server will be sent to another server.
However, in a Single-Page Application (SPA), all routes are virtual and handled by the application's router, meaning no files exist for accessing URLs. As a result, :proxy-url sends the request to the remote proxy because no requested files exist.
This behavior is quite frustrating.
The usual structure of an SPA involves a reverse-proxy like Nginx that passes all requests to the front-end application. When accessing certain special paths (for example, paths that start with '/api/'), the reverse proxy sends the requests to a backend API server.
In the documentation, :proxy-url seems useful for realizing the same structure as a reverse-proxy, but it is not.
:proxy-predicate option is the answer
I was googling this problem and tried to implement my own dev-server and apply it to dev-http with the :handler option, but it didnât work well because I couldn't find an easy way to handle cookies.
However, I found the answer while reading the source code of the shadow-cljs dev-http server. It has an undocumented option.
The :proxy-predicate option can be used with :proxy-url.
We can supply a function symbol for this option like the following:
:dev-http {:proxy-url âhttp://localhost:8080â :proxy-predicate my-app.dev-server/api-request?}
The :proxy-predicate function should return true if the dev-http server should send the request to the proxy-url. The function accepts two arguments:
exchange: io.undertow.server.HttpServerExchange object of the âundertowâ http server. config: the config map that is supplied to :dev-http.
The documentation for the HttpServerExchange class is here.
With the :proxy-predicate option, you can choose whether to pass the request to the proxy server based on the requesting paths.
For example:
(defn api-request? [ex config] (let [path ^String (.getRequestPath ex)] (string/starts-with? path "/api/")))
This api-request?
function checks the requested path, and if the path starts with /api/, the dev-http server will send it to the proxy server.
The combination of :proxy-url and :proxy-predicate perfectly handles cookies. This is a good choice for developing SPAs with shadow-cljs.
å®è·µImmutable Data Model
ã¯ããã«
ãã®è¨äºã§ã¯ãImmutable Data Modelã¨å¼ã°ããè¨è¨ææ³ããã¨ã«ããªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹ã«ãããããã¼ãã«è¨è¨ã®è©±ãæ¸ãã¦ãã¾ããã¾ããä»åã®å®è·µã§å©ç¨ãããå¥ã®èãæ¹ã®èæ¯ãç解ããããã«ãOut of the tar pitã¨ããå°è«æã®å 容ã«ãè¨åãã¾ãã
ãç¶æ ã¨ã¯ä½ãï¼ãã¨ããããããã話ãããããåºã¦ãã¾ããããã¼ã¿ãã¼ã¹ã®ãã¼ãã«è¨è¨ã«ã¤ãã¦ã®è©±ã§ãããã¨ãããããããã®SQLãåºã¦ãã¾ãããªã®ã§ããã¼ã¿ã¢ããªã³ã°ã¨ãç¶æ 管çã¨ããç¹ã«SQLã¨ãã«èå³ããªã人ã«ã¯é¢ç½ããªãã¨æãã¾ãã
ãã®ãããã«èå³ããæ¹ã¯ãèªãã§ã¿ã¦æ¬²ããã§ãã Immutable Data Modelããå®éã®ã¢ããªã±ã¼ã·ã§ã³ã§ä½¿ããã¼ã¿ãã¼ã¹ã«æ¡ç¨ããã«ããããã©ãããèãæ¹ã§ãã©ã®ããã«ãã¼ãã«ãæ§æããããèªåãªãã®çµé¨ãæ¸ãã¦ãã¾ãã
å½ããåã§ãããå®è·µãããã®ã§ããã¨ã¯ãããä¸ã¤ã®ã¢ã¤ãã¢ã§ããã®ã§ãå¥ã«ãã¹ããªææ³ã§ããã¨ä¸»å¼µããã¾ããããããã¯ããããã»ãããããããããªãã®ã§ã¯ãã¨ããã¦ãã§ã¯ãããã£ã¦ããã¿ãããªãã®ãããã°ããèªèº«ã®ããã°ã§æ¸ããªã©ãã¦ç¤ºãã¦ããã ããã°ãçºå±çãªè©±ã«ãªãããªãã¨æã£ã¦ãã¾ãã
Immutable Data Modelã¨ã¯
ããã°ã©ãã³ã°è¨èªã®ä¸çã«ã¯ãã¤ãã¥ã¼ã¿ãã«ãªãã¼ã¿ã®æ¹ãä¸å ·åãèµ·ããã«ããå®å ¨ã§ãããã¨ããèãæ¹ãå¤ããããããä¸é¨è¨èªã§ã¯ããããããã¼ã¿èªä½ãæ¹å¤ãããã¨ãã§ããªãï¼æ¹å¤ããæ°ãããã¼ã¿ãä½ããã¨ããã§ããªãï¼è¨èªãåå¨ãã¾ããClojureã¨ãã
ãã¼ã¿ãã¼ã¹ã®ãã¼ãã«è¨è¨ã«ããã¦ãããã¼ãã«ã®Create, Update, Deleteã®ãã¡ãç¹ã«Updateããã·ã¹ãã ãè¤éåããè¦å ã®ä¸ã¤ã ã¨ããèãæ¹ãããã¾ããUpdateããªãã¹ãçºçãããªãããã«ã¯ããã¼ã¿ãæ¹å¤ã§ããªãï¼ã¤ã¾ãCreateããã§ããªãï¼ã¢ãã«ã®æ¹ããé·æçã«å®å®ãããå®å ¨ãªã·ã¹ãã ãä½ããã¯ããã¨ããèãæ¹ã§ãã
Immutable Data Modelã¨å¼ã°ããããã§ãããç¥ãéãã§ã¯ãKawasimaãããåä»ã親ã®ã¯ãã
ã¤ãã¥ã¼ã¿ãã«ãã¼ã¿ã¢ãã«
Web+DB Pressã®ãã¼ã¿ã¢ãã«åã§ãçµæ§è©³ãã解説ããã¦ããã®ã§ããããã§ãã
èãæ¹ã§ããã解çã§ã¯ãªã
å¤ãã®è¨è¨è«ãããã§ããããã«ãImmutable Data Modelã¯ãèãæ¹ãã§ããããç´°ããæç¶ãã¨ã«ã¼ã«ããã£ã¦ããã®ã¨ããã«ããã°èªåçã«è¯ããªããããªæç§æ¸ãã§ã¯ããã¾ããããã¼ã¿ã¢ããªã³ã°ããã¨ãã«ãåå°ã¨ãã¦é¸æã§ãããä¸ã¤ã®æ¹æ³è«ã§ãããã®èãæ¹ããã¨ã«ãå®éã«ã©ã®ããã«ãã¼ãã«ãç¨æãããã¯ãèªåã§èããå¿ è¦ãããã¾ãã
åè¿°ã®Web+DB Pressã®è¨äºã«ããã¦ããæ¦ããããããã¨ãããããã®ã ãã¨ãã説æããææ¡ã¯åºã¦ãã¾ãããããããçããªã®ã§ä¸åä¸å¥ããã®éãããã°ãããã¨ããç©ã¯åºã¦ãã¾ããã
æã£åãæ©ãåçãç¥ããã人åãã§ã¯ãªãã®ã§ãã
ãªã®ã§ããã®è¨äºãããã®èãæ¹ããã¨ã«ãããããè¨è¨ãå®éã«ãã£ã¦ã¿ã¦ãããã©ã©ãã ãããï¼ã¨ããæå³åãã§èªãã§æ¬²ããã§ãã
åãèãæ¹ããã¼ã¹ã«ããã£ã¨ã¨ã¬ã¬ã³ããªæ¹æ³ããããªãã°ãã©ãã©ãæ¡ç¨ãã¦ããã°ããã®ã§ãã
Out of the tar pit
Out of the tar pitã¨ãããå²ã¨æåãªå°è«æããã£ã¦ãããããªè¨è¨çè«ã§å¼ç¨ããã¦ãã¾ããã·ã¹ãã ã«ãããç¶æ ï¼Stateï¼ã¨ãã¸ãã¯ã«ã©ã®ãããªåºå¥ãããã®ããæ¬å½ã«å¿ è¦ãªç¶æ ããã¸ãã¯ã¨ã¯ããããã¯ãããã§ãªããã®ã¯ï¼ã¨ãã£ããã¨ãè«ããåºåããããã¨ã§ãå®å®ããã·ã¹ãã ãä½ãã«ã¯ã©ããããããã®ãï¼ãè«ãã¦ãã¾ãã
Out of the tar pitã«ã¤ãã¦ã¯ãç§ãåã«ããã°ã§è©³ããç´¹ä»ããè¨äºãããã®ã§ããã¡ããèªãã§ã¿ã¦ãã ããã
ã·ã¹ãã ã®è¤éãã¯ã©ãããæ¥ãã®ã â Out of the tar pitãèªã
ãã¡ãã§ç´¹ä»ãã¦ããããã«ãOut of the tar pitã§ã¯ãã·ã¹ãã ã®ç¶æ ã¨ãã¸ãã¯ãã
- å¿ é ã®ç¶æ (Essential State)
- å¿ é ã®ãã¸ãã¯(Essential Logic)
ã¨ãã·ã¹ãã ã®é½åã«ããçã¾ãããä»éçãªãã®ã
- ä»éçãªç¶æ (Accidental State)
- ä»éçãªãã¸ãã¯(Accidental Logic)
ã¨ã«åããä½ãç¶æ ã§ãä½ããã¸ãã¯ãªã®ããä½ãå¿ é ã§ä½ãä»éçãªã®ãã説æãã¦ãã¾ãã
ãªããEssential/Accidentalã®è¨³èªã¨ãã¦ã¯ããæ¬è³ªçãªããå¶æçãªãã¨ããèªã使ããããã¨ãå¤ãã§ãï¼ããã°ã«æ¸ãã¦ããããã«ããã®è¨èã®å¤§å ã§ããã人æã®ç¥è©±ãã®ç¿»è¨³ã§ããã®è¨³èªã使ããã¦ããããã§ãï¼ããå¿ é ã®ããä»éçãªãã¨ããèªã¯ç§ãããã°ã«ããã¦ä½¿ã£ããã®ã§ãããããã§ã¯ãããå¼ãç¶ãã¾ãã
ç¶æ ã¨ãã¸ãã¯
Out of the tar pitã«æ¸ããã¦ããç¹å¾´çãªè©±ã«ãæã ãç¶æ ã¨æã£ã¦ãããã®ã¯ãå®éã«ã¯ç¶æ ã§ã¯ãªãããã¸ãã¯ã§ãããã¨ãã話ãããã¾ãã
æ¶ç©ºã®è©±ã¨ãã¦ãè¨ç®æéã常ã«ã¼ãã®ãæ°å¦çä¸çã«ããã¨ä»®å®ããããã¨ãã²ã¼ã ã«ããããã¬ã¤ã¤ã¼ã®ç¾å¨ä½ç½®ã¯ãç¶æ ã§ã¯ãªããã¸ãã¯ã ã¨ãã話ããã¦ãã¾ãããªããªããè¨ç®æéãã¼ããªã®ã§ããã°ããã¹ã¿ã¼ãå°ç¹ãã¨ããç¶æ ã¨ãã移åæä½ã®å ¨å±¥æ´ãã¨ãã2ã¤ã®ç¶æ ããè¨ç®ããã°ãç¾å¨ä½ç½®ã¯è¨ç®ã§å°ãåºããããã§ããç¾å¨ä½ç½®ã¨ã¯ããã¹ã¿ã¼ãå°ç¹ãã¨ã移åæä½ã®å ¨å±¥æ´ãããã©ã¡ã¼ã¿ã¨ãããç¾å¨ä½ç½®ãé¢æ°ã ã¨ãããã¨ã§ãã
ã¤ã¾ããã¹ã¿ã¼ãå°ç¹ã¨ç§»åæä½ã®å ¨å±¥æ´ã®äºã¤ã¯ç¶æ ã ãããç¾å¨ä½ç½®ãã¯ãå®ã¯ç¶æ ã§ã¯ãªãã£ãã®ã ãã¨ãã話ã§ãã
ä¸æ¹ãå¿ é ã¨ä»éçã®åºå¥ã«ã¤ãã¦ã¯ãOut of the tar pitã«ããã¦ãä½ãå¿ é ã®(Essential)ç¶æ ãªã®ãã¯ã¯ã£ããããã¦ãã¦ããã¦ã¼ã¶ã¼ã®å ¥åãã ããå¿ é ã®ç¶æ ã§ãããã以å¤ã¯å ¨ã¦å¿ é ã®ç¶æ ã§ã¯ããã¾ãããã¦ã¼ã¶ã¼ã®å ¥åã ãã¯ãè¨ç®ã§å°ãåºããã¨ã¯ã§ããªãããå¾ããåãæ»ããã¨ãã§ããªãã®ã§ããã¦ã¼ã¶ã¼ã®å ¥åãè¨é²ãã以å¤ã«ãä»å¾ãã®ãã¼ã¿ãå¾ãæ¹æ³ããªãã®ã§ãã
ãªããã®Out of the tar pitã®è©±ããã¦ãããã¨ããã¨ãImmutable Data Modelãå®è·µããä¸ã§ãã»ãã¨ãã«ãã¼ã¿ãã¼ã¹ã«ä¿åãã¹ãæ å ±ã¯ãªããªã®ãï¼ãã¨ãããã¨ãèããä¸ã§éè¦ã ããã§ãã
ã¦ã¼ã¶ã¼ã®å ¥åã¯ãã¹ã¦ãå¿ é ã®ç¶æ ãã§ãã
ãªã®ã§ãã¦ã¼ã¶ã¼ã®å ¥åã¯ããããªãå ¨ã¦ä¿ç®¡ããããã§ããã以å¤ã¯å¿ é ã§ã¯ãªãã®ã§ãå¯è½ãªéãããã¸ãã¯ã§è¡¨ç¾ãããããããã¹ã¿ã¼ãå°ç¹ã¨ãã¾ãã
å¿ é ã®ãã¸ãã¯
ã§ã¯ããå¿ é ã®ãã¸ãã¯ãã¯Out of the tar pitã«ããã¦ã©ãæ±ããã¦ããããå¿ é ã®ãã¸ãã¯ã¯ãå¿ é ã®ç¶æ ããè¨ç®ã«ãã£ã¦ç´æ¥å°ãåºãããã®ã§ãã
ãªã«ããå¿ é ã®ç¶æ ãã§ããããªã«ãããã¸ãã¯ããªã®ããåºå¥ã§ããã°ããã¼ãã«ã¨ãã¦ç¨æãã¹ããã®ã¯ä½ãªã®ããã¯ã£ãããã¦ãã¾ããæ¬å½ã«ä¿åãå¿ è¦ãªã®ã¯ããå¿ é ã®ç¶æ ãã ãã§ãã
ãã¡ãããç¾å®ã®ä¸çã§ã¯ãè¨ç®æéã¯ã¼ãã§ã¯ãªãã®ã§ããªã«ãããã®æå½ã¦ãããªããã°ããã¾ãããã§ãããæåã®æ®µéã§ãããã¯å¿ é ã®ç¶æ ã§ãããããã¯å®ã¯ç¶æ ã§ã¯ãªããã¸ãã¯ã ãã¨åºåããã§ãã¦ãããã¨ã¯å¤§äºã§ãããå¿ é ã®ãã¸ãã¯ãã®é¨åã«ã¯ãæ¬æ¥ã¯ããã¼ã¿ãã¼ã¹ãã¼ãã«ã¯å¿ è¦ãªãã£ããã¨ããèªèãéè¦ãªã®ã§ãã
ã§ã¯ããªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹ã«ãããããå¿ é ã®ãã¸ãã¯ãã¯ã©ã®ããã«è¡¨ç¾ãããã¹ãã§ããããã
ç§ã¯ããã«ããã¥ã¼ãã使ããã¨ã«ãã¾ããã ãå¿ é ã®ç¶æ ãã®çµã¿åããã§è¡¨ç¾ã§ãããã®ã¯ããã¥ã¼ã§è¡¨ç¾ããã®ã§ãã
ä»éçãªç¶æ ã»ä»éçãªãã¸ãã¯
ã¨ã¯ããããªãã®æå½ã¦ããªãã¾ã¾ãã¥ã¼ã ãã§å ¨ã¦ã表ç¾ã§ãããã¨ããã¨ãã¤ã³ããã¯ã¹ãå ¨ãå¹ããªããã¥ã¼ãã§ãããããããããã¥ã¼ã¨ãã¦å®ç¾©ã§ããªããã®ãåºã¦ãã¾ããããã解決ããããã«ãå¹ççã«ãã¼ã¿ãåãããã®è£å®çãªãã¼ãã«ããã¥ã¼ãå¿ è¦ã«ãªããã¨ãããã§ãããã
ãããã¯ãã·ã¹ãã ã®é½åã§ãããã®ãããªãã·ã¹ãã ã®é½åä¸ç¨æãããã¼ãã«ããã¥ã¼ãããä»éçãªç¶æ ãï¼ãããã¯ãã¸ãã¯ï¼ã¨ã¿ãªããã¨ã«ãã¾ããããããããã¨ãããããããã®ãã¼ãã«ã¯ãå¿ é ã®ç¶æ ã§ã¯ãªããä»éçãªç¶æ ãªã®ã ãªããªã©ã¨ãããããã«ãè¦è¦çã«è¡¨ç¾ãããã¨ãç®æãã¾ãããã¼ãã«åããã¥ã¼åãè¦ãã ãã§ãããããã¯ã¦ã¼ã¶ã¼å ¥åã®ä¿åã¨ããããã¯ãã·ã¹ãã ãã¼ãã«ã®ä¸ç¨®ãªã®ã ãªãã¨ãããããã«ãããã®ã§ãã
ãããã®åæã®ãã¨ã§ãImmutable Data Modelçãªãã¼ãã«è¨è¨ãèãã¦ããã£ã¦ã¿ãçµæãç´¹ä»ããã®ããã®è¨äºã®ç®çã§ãã
ãã¼ãã«è¨è¨
ã¦ã¼ã¶ã¼å ¥åã¯ååã¨ãã¦ãå ¨ã¦ãã¼ãã«ã«ä¿åããã
ãå¿ é ã®ç¶æ ãã§ããã¦ã¼ã¶ã¼ããã®å ¥åã¯ããã¹ã¦ãã¼ãã«ã«ä¿åãã¾ãã
ãããã¼ã¿ãã¦ã¼ã¶ã¼ããã®å ¥åãã©ããã®èå¥ã¨ãªãæ å ±ã«ããã¼ã¿ãã¼ã¹ãã¼ãã«ã«ãããããcreated_atããcreated_byãã¨ãã®ååã§è¨é²ããããæä½è ã¨æä½æ¥æãè¨é²ããã«ã©ã ãããã¾ãã
ãããã®æ å ±ã¯ãããã«ã¦ã¼ã¶ã¼æä½ããããã¨ã示ãã¦ãã¾ãã
Immutable Data Modelã®å
è¨äºã«ããã¦ããæ¥ææ
å ±ã«ã©ã ã¯ãããåå¥ã®ãã¼ã¿ã§ãããã¨ã示ãã¦ãã¦ãä¸ã¤ã®ãã¼ãã«ã«è¤æ°ã®æ¥ææ
å ±ã«ã©ã ãããã®ã¯ãUPDATE
ã®å¿
è¦æ§ãå¢ãã®ã§è¯ããªããå¥ãã¼ãã«ã«ãã¹ããã¨ãã話ãåºã¦ãã¾ãã
ããã¦ãOut of the tar pitã®ãå¿ é ã®ç¶æ ãã®è¦³ç¹ããè¦ã¦ããæ¥ææ å ±ï¼ã¨æä½è æ å ±ï¼ãããã¨ãããã¨ã¯ãããã¯ã¦ã¼ã¶ã¼å ¥åã®è¨é²ãªã®ã§ãããã¡ããã¨ç¶æ ã¨ãã¦ç®¡çãã¹ãã ã¨èãããã¾ãã
ãªã®ã§ãæ¥ææ
å ±ãå¿
è¦ãªæ
å ±ãããã°ããããã¯å
¨ã¦ãåå¥ã®ãã¼ãã«ã«INSERT
ãããã¨ã«ãã¾ããååã¨ãã¦ãå¥ã®ãã¼ãã«ãç¨æãã¦ãå¥ã®ãç¶æ
ãã¨ãã¦ä¿åãã¾ãããããã¯ãããèªä½ãåå¥ã«è¨é²ãã¹ãã¦ã¼ã¶ã¼æä½ãªã®ã§ãã
ãã®ãããªã¦ã¼ã¶ã¼æä½ã®è¨é²ãããã¤ãã³ããã¨å¼ã¶ãã¨ã«ãã¾ãããã¼ã¿ãã¼ã¹ã«ã¯ãå ¥åãã¼ã¿ãã®ãã®ãæ ¼ç´ããããã¼ã¿ãã¼ãã«ãã¨ãã¦ã¼ã¶ã¼æä½ãè¨é²ãããã¤ãã³ããã¼ãã«ãããããã©ã¡ããã¦ã¼ã¶ã¼å ¥åããä½ãããã®ã§ãå¿ é ã®ç¶æ ã¨ãã¦æ±ãã¾ãã
æ´æ°ã¯ã¤ãã³ã
ããã¾ã§ãããã¾ããããæ¢åãã¼ã¿ã®æ´æ°ã¯ãæããã«ã¦ã¼ã¶ã¼å
¥åã§ããããæ´æ°ãã¨ããã¤ãã³ãã§ããImmutable Data Modelã§ã¯ããã¼ã¿ã¯ååã¨ãã¦UPDATE
ãããªãã®ã§ãæ´æ°æä½ãINSERT
ã¨ãã¦å®ç¾ãããã§ãã
ãªã®ã§ããã¼ã¿ã®æ´æ°ã¯ããã¼ã¿ãã¼ãã«ãã®ãã®ã¸ã®ãæ°ããã¬ã³ã¼ãã®INSERT
ã¨ãã¦è¡¨ç¾ãã¾ãã
ã¦ã¼ã¶ã¼ããã¼ã¿ã10åæ´æ°ãããããã®ãã¼ã¿ãä¿åãããã¼ã¿ãã¼ãã«ã«ã¯ãï¼æåã«ä½æãããã¼ã¿ãåããã¦ï¼åè¨11åã®ã¬ã³ã¼ããç»é²ããããã¨ã«ãªãã¾ãã11åã®ã¬ã³ã¼ãã®ãã¡ãææ°ã®ãã®ãããã®ãã¼ã¿ã®ãä»ã®ç¶æ ãã§ãã
ã¤ã¾ããã¦ã¼ã¶ã¼ãæ´æ°ã§ãããã¼ã¿ã®ãã¼ãã«ã¯ã大æµã¯ãå±¥æ´ç¶ã«ãªãã¨ãããã¨ã§ããå±¥æ´ã®ãã¡ãææ°ã®ãã®ãç¾å¨ã®ãã¼ã¿ã表ãã¦ãã¾ããã¾ããåããã¼ã¿ã®è¤æ°ã®å±¥æ´ãåå¨ããããããã¼ã¿ã®IDã¨ã¯å¥ã«ãï¼ããããã¯auto generatedãªï¼ãµãã²ã¼ããã¼ãåå¨ããã§ãããã
åç´ãªã¿ã¹ã¯ç®¡çã·ã¹ãã ãèãã¦ã¿ã¾ããããã¿ã¹ã¯ã表ãtaskãã¼ãã«ã¯
Task history_id (primary key) task_id title description created_at created_by
ãããªæãã«ãªãã§ãããã
ã¿ã¹ã¯ã®æ´æ°ããã£ãå ´åã¯ãåãtask_idã§ãæ°ãããã¼ã¿ãINSERT
ãã¾ããcreate_at
ããã£ã¨ãæ°ãããã®ãããã®ã¿ã¹ã¯ã®ãä»ãã®ç¶æ
ã§ãã
ä»éçãªç¶æ ã®å°å ¥
å±¥æ´ç¶ã®ãã¼ã¿ãã¼ãã«ã«ãããããä»ã®ãç¶æ ã¯ãï¼è¨ç®æéãç¡è¦ããã°ï¼è¨ç®ã§å°ãåºãããã®ãªã®ã§ããã¸ãã¯ã§ããã¾ããããã¦ã¼ã¶ã¼å ¥åãã¼ã¿ã®ä»ã®ç¶æ ã¨ããã®ã¯ãã¦ã¼ã¶ã¼å ¥åãè¨é²ãããã®ããã®ç´æ¥çæ´¾çãã¼ã¿ã§ãããã·ã¹ãã ã®é½åã§å é¨çã«å©ç¨ãããã¸ãã¯ã§ã¯ããã¾ããããããä»éçãªãã¸ãã¯ãã§ã¯ãªãããå¿ é ã®ãã¸ãã¯ãã§ãããã
ãã ãå±¥æ´ã®ææ°ã®ãã®ã ããéããã¨ãããã¸ãã¯ã¯ãç¾å®ã®ä¸çã§ã¯ãããªãéå¹çãªãã®ã«ãªãã¾ããæ¯åãtask_idåä½ã§ã½ã¼ããã¦ãå é ã®ã¬ã³ã¼ããåãåºãå¿ è¦ãããã¾ããããã¯ããªãè¤éãªã¯ã¨ãªãæ¸ãã°ããã¥ã¼ã¨ãã¦å®ç¾ã§ãã¾ãããç¾å®ä¸çã§ã¯ãããªãããã©ã¼ãã³ã¹ãæªããã§ãã
ã¯ã¨ãªã§ãä»ã®ã¿ã¹ã¯ããåå¾ããã¯ã¨ãªã®ä¾:
WITH RankedTasks AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY created_at DESC) AS rn FROM task ) SELECT history_id, task_id, description, created_at FROM RankedTasks WHERE rn = 1;
è¦ãããã«ããã®ã¯ã¨ãªã§ãã¼ã¿ãåå¾ããã®ã¯ãããªãããã©ã¼ãã³ã¹ãæªããã§ãã è¤éãªSQLã¯ã¨ãªã¯ãããã©ã¼ãã³ã¹ã ãã§ã¯ãªããããã°ã©ã ã®ä¿å®æ§ãä¸ãã¾ãã®ã§ãé¿ããããã®ã§ãã ä¸è¨ã®ã¯ã¨ãªããããã¨ã¿ã¦ããç解ã§ãã人ã¯ãå¤ãã¯ãªãã§ãããã
ãªã®ã§ãä»éçãªç¶æ ãå°å ¥ãããã¨ã§ãã¯ã¨ãªãç°¡åã«ãã¤ã¤ãããã©ã¼ãã³ã¹ãæ¹åãã¾ãã
ã·ã³ãã«ã«ãææ°ãã¼ã¿ã表ãããã¤ã³ã¿ã¼ãã¼ãã«ããç¨æãã¾ããGitã®HEADã®ããã«ãã©ã®ãã¼ã¿ãææ°ãã¼ã¿ãªã®ãããã®IDãè¨é²ãã¾ãã
ã¿ã¹ã¯ã®ä¾ã§ç¤ºãã°
current_task_cache task_id (pk) history_id (Taskãã¼ãã«ã®history_idãæãï¼
ãããªãã·ã³ãã«ãªãã¼ãã«ã«ãªãã§ãããã ãã®ãã¼ãã«ã¯ãããã©ã¼ãã³ã¹åä¸ã®ããã«ãã·ã¹ãã ã®é½åã§ç¨æãããã¼ãã«ã§ãããã¦ã¼ã¶ã¼å ¥åã®è¨é²ã§ã¯ããã¾ãããã ããããã®ãã¼ãã«ã¯ãOut of the tar pitã§ããã¨ããã®ãä»éçãªç¶æ ãã§ãã
ä»éçãªç¶æ ã¯ãout of the tar pitã®èãæ¹ãå¾¹åºçã«æ¡ç¨ãããªãã°ãããã®ãã¼ãã«ãåé¤ãã¦ããããã©ã¼ãã³ã¹ã¯å£åãããã®ã®ãã·ã¹ãã ã¯ã¡ããã¨åããã¨ãããç®æããã°ãªãã¾ãããããã¯ã·ã¹ãã éçºã®ãã¬ã¼ããªãã§ãã©ãã¾ã§è¿½æ±ãããã¯ãåèªã§æ±ºããã°ãªãã¾ãããããã®ãã¼ãã«ããããªãã°å©ç¨ãããªããªãã°ãã¸ãã¯ã§å°ãåºããã®ããã«ãããã¨ããé å¼µãã°ã§ããã§ãããããç§ã¯ããã¾ã§ã¯ãããªã£ã¦ãã¾ãããä»éçãªãã¼ãã«ã ããããã°ã©ã çã«ã¯å¿ ãå¿ è¦ãªãã¼ãã«ï¼ãªãã¨åããªãï¼ãã¨ããæ±ãããã¦ãã¾ãã
ãããã«ããããã®ãã¼ãã«ã®å 容ã¯ãã¦ã¼ã¶ã¼å ¥åã®è¨é²ã§ã¯ãªããä»®ã«ãã¼ãã«ã失ããã¦ãããã¸ãã¯ã«ããåä½æå¯è½ã§ããã¨ããäºå®ã¯å¤ããã¾ããããªã®ã§ãä»éçãªãã®ã§ãããã¨ããè¦è¦çã«ãååã§è¡¨ç¾ãããã§ãã
ä»åã¯ãä»éçãªç¶æ ã表ããã¼ãã«ã«ã¯ãæ¥å°¾è¾ã_cacheããã¤ãããã¨ã«ãã¾ããã
ãã£ãã·ã¥ã¨ããã®ã¯ãæ¬æ¥ã¯ãªãã¦ãåããã¨ããæå³ãè¾¼ãã¦ãã¾ããä»åã¯ããªãã¦ãåãã¨ããã¾ã§ã¯ä½ãè¾¼ã¾ãªããã¨ã«ãããã®ã®ãä½ç½®ä»ãã¨ãã¦ã¯ãããããã¼ãã«ã§ãããã¨ãè¾¼ãã¦ãã¾ãã
ãã ãã®ãããã®ååã¥ãã¯ãç¹ã«ã«ã¼ã«ã¯ããã¾ããã®ã§ãèªç±ã«æ±ºããã°è¯ãã¨æãã¾ããããããã¦ã¼ã¶ã¼å ¥åãè¨é²ãããã¼ãã«ã§ã¯ãªããä»éçãªç¶æ ãè¨é²ãã¦ããã®ã ãã¨ãããã¨ãããããããªååä»ãããããã¨ããå§ããã¾ãã
ãã¤ã³ã¿ã¼ãã¼ãã«ãå°å ¥ããããã¨ã§ãææ°ã®ã¿ã¹ã¯ãéãããã¼ãã«ã¯ããã¸ãã¯ã«ããç°¡åã«æ±ãããã¨ãã§ãã¾ãã
SELECT task.* FROM task INNER JOIN current_task_cache c ON c.task_id = task.task_id AND c.history_id = task.history_id;
ãã®è¨ç®ãããã¥ã¼ã¨ãã¦å®ç¾©ãã¦ããã¾ãããå¿ é ã®ãã¸ãã¯ãã®å°å ¥ã§ãã
CREATE VIEW current_task AS SELECT task.* FROM task INNER JOIN current_task_cache c ON c.task_id = task.task_id;
ããã§ãcurrent_taskããSELECT
ããã°ããã¤ã§ããææ°ã®ã¿ã¹ã¯ãéãããã¼ãã«ã§ãããã®ããã«ããã¼ã¿ãåå¾ã§ãã¾ãã
ãã®ãããªå½¢ã§ããã¾ãã¯å¿ é ã®ç¶æ ãè¨é²ããããã®ãã¼ãã«ãä½ãããããããä½ã³ã¹ãã§è¨ç®å¯è½ãªæ´¾çãã¼ã¿ã¯ããã¥ã¼ã§å®ç¾©ããããä½ã³ã¹ãã§è¨ç®ã§ããªãå ´åã¯ãä½ã³ã¹ãã§è¨ç®ã§ããããã«ããããã®ä»éçãªç¶æ ãå°å ¥ããããã使ã£ã¦ãã¥ã¼ãä½ããã¨ããæ¹éã§ããã¾ãã
ãã®ãã¼ã¿æ§é ã§ã¯ããã¼ã¿ã®æ´æ°ä½æ¥ã«ããããã¼ã¿ãã¼ã¹ãã¼ãã«ã®æä½ã¯ã
- å¿
é ã®ç¶æ
ã®
INSERT
- ä»éçãªç¶æ
ã®
INSERT
ãããã¯UPDATE
ããåå¨ããªããã¨ã«ãªãã¾ããä¸è¨ã®ä¾ã§è¨ãã°ãTaskãã¼ã¿ã®æ´æ°ã¨ã¯ã
task
ãã¼ãã«ã¸ã®æ°ãã¼ã¿ã®INSERT
current_task_cache
ãã¼ãã«ã¸ã®ããã¤ã³ã¿ãã¼ã¿ã®INSERT
ãããã¯UPDATE
ã§è¡¨ç¾ããããã¨ã«ãªãã¾ããããããå¿
é ã®ç¶æ
ãã§ãããã¼ãã«ã«ãUPDATE
ãªã©ã®ãINSERT
以å¤ã®æä½ãè¡ããããããã°ãè¨è¨ãã¹ã®å¯è½æ§ãæ¤è¨ãã¾ãã
ãã¼ã¿ã®ç¶æ å¤æ´ã¯ã¤ãã³ãã§ãã
ãã¦ããã®ã¿ã¹ã¯ãå®äºãããã©ããã¹ãã§ããããã
å²ã¨ä¸è¬çãªãã¶ã¤ã³ã ã¨ããã¼ãã«ã«completed_at
ã®ãããªæ¥ä»ã«ã©ã ãããããã®ã«ã©ã ã«å¤ãããã°ããã®ã¿ã¹ã¯ã¯å®äºãã¦ããã¨ã¿ãªããã¨ãããã®ã§ãã
ãããImmutable Data Modelã§ã¯ããã¼ãã«ã®UPDATE
ãè¡ããªãï¼ä»åã®è¨è¨ã§ã¯ãå¿
é ã®ç¶æ
ãã®UPDATE
ã¯è¡ããªãï¼æ¹éã§ãã®ã§ããã®ããæ¹ã¯åãã¾ããã
ããã«è¨ãã°ãã¿ã¹ã¯ãå®äºãããã¨ããã®ã¯ã¦ã¼ã¶ã¼ã®å ¥åã§ãããã¦ã¼ã¶ã¼ã®å ¥åã¯å ¨ã¦ãå¿ é ã®ç¶æ ããªã®ã§ããã¼ãã«ã«åå¥ã®ãã¼ã¿ã¨ãã¦ä¿åãããã¹ãã§ãã
ãã®ãããªãæ¢åã®ãã¼ã¿ã®ç¶æ å¤æ´ããã¤ãã³ããã¨å¼ã³ã¾ããã¤ãã³ãã¯ã¤ãã³ãã¨ãã¦ããã®ã¤ãã³ããèµ·ããã¨ãããã¨ãè¨é²ããªãã¦ã¯ããã¾ããã
ãªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹(RDB)ã®ãã¼ã¿ã¢ããªã³ã°ã«è©³ããæ¹ã§ããã°ããã¼ã¿ã ãã§ã¯ãªããã¤ãã³ããããã¡ãã¨è¦æ¥µãã¦ãã¼ãã«ã¨ãã¦åé¢ãã¦è¨é²ãã¹ããã¨ããèãæ¹ã¯ãããªãåããæå±ããã¦ããèãæ¹ã ã¨ãããã¨ã¯ãåç¥ã ã¨æãã¾ããä¾ãã°ãç§ããã¼ã¿ãã¼ã¹ã»ã¢ããªã³ã°ãå¦ã¶ä¸ã§ä»ã§ããå§ããã¦ããæ¬ã®ä¸ã¤ã«ã楽ã ERDã¬ãã¹ã³ãã¨ããæ¬ãããã¾ãã
ãã¡ãã¯2006å¹´ã®æ¬ã§ããªãå¤ããã®ã§ããããã®é ã§ããã¤ãã³ããã¤ãã³ãã¨ãã¦èªèããã®ã大äºã§ãã¤ãã³ãããã¼ã¿ãã¼ãã«ã«ã«ã©ã ã¨ãã¦çµã¿è¾¼ãã®ã¯è¯ããªããã¡ããã¨ã¤ãã³ãã¨ãã¦è¨é²ãã¹ããã¨ããèãæ¹ãå¼·ã奨å±ããã¦ãã¾ãã
ã¤ã¾ãããã¼ã¿ãã¼ã¹ãã¼ãã«è¨è¨ã®èãæ¹ã§ã¯ãããªãåããåããã¨ã奨å±ããã¦ããã®ã§ãããä¸ã®ä¸ã§ã¯ãã¼ãã«ã«ãcompleted_atããªã©ã®ã«ã©ã ãç¨æãããã¨ããä½ãæ¹ã®æ¹ããã£ã¨ãã£ã¨å¤ãã¾ã¾ã ã£ãã®ã§ãããä»ãImmutable Data Modelã¨ããè¨è¨ææ³ãä»ãã¦ãç§ãã¡ã¯åã³åãã¨ããã«æ»ã£ã¦ããã®ã§ãã
ãªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹ã®ã¢ããªã³ã°ã§å¥¨å±ããã¦ããèãæ¹ã¨ãImmutable Data Modelã¨ã"Out of the tar pit"ã«ãããç¶æ 管çã®èãæ¹ã¨ããä»ããã§ç¶ºéºã«ç¹ãã£ãã¨ãè¨ããããããã¾ããã
ã¤ãã³ãããã¼ãã«ã¨ãã¦è¨é²ãã
ããã§ã¯ãããã¿ã¹ã¯ãå®äºãããã¨ããã¦ã¼ã¶ã¼æä½ã§ããã¨æãããå¿
é ã®ç¶æ
ãã®ä¸ã¤ã¨ãã¦è¨é²ãã¾ããtask_completed
ãã¼ãã«ã¯ä»¥ä¸ã®ãããªæ§æã«ãªãã§ãããã
task_completed task_id (PK) completed_at completed_by
ã·ã³ãã«ã«ãçµäºããã¿ã¹ã¯ã¸ã®ãªã³ã¯ã¨ãªãtask_id
ã¨ãå®äºããæ¥æã¨å®äºè
ãè¨é²ãã¾ãããäºå®ãè¨é²ãããã¨ãã観ç¹ã§æãã·ã³ãã«ãªãã¼ãã«å®ç¾©ã§ãããããªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹ã§ã¯å¶ç´ã使ãã¾ããããtask_id
ã¯å¤é¨ãã¼ã¨ãã¦è¨å®ããã®ãè¯ãã§ãããããã®å ´åãtask
ã«ç´æ¥FOREIGN KEYã§çµã³ã¤ãããã¨ãã§ããªãç¹ã«æ³¨æãã¦ãã ãããtask
ã¯å±¥æ´ç¶ã«ãªã£ã¦ãããããtask_id
ã¯ãã©ã¤ããªãã¼ã§ã¯ããã¾ãããå¤é¨ãã¼ãè²¼ãå ´åã¯ãcurrent_task_cache
ãã¼ãã«ã«å¼µããã¨ã«ãªãã§ãããã
ãã¦ãããã§ãã¦ã¼ã¶ã¼ãã¿ã¹ã¯ãå®äºããã¨ããç¶æ
ãã®è¨é²ã¯ã§ãã¾ããããå®éã«ã¢ããªã±ã¼ã·ã§ã³ã§å¿
è¦ã¨ãªãã®ã¯ãå®äºããã¿ã¹ã¯ãã®ä¸è¦§ã§ãã£ã¦ãã¿ã¹ã¯ãå®äºããã¤ãã³ãã®ãã¼ã¿ãã§ã¯ãªãã§ããããtask
ã¨task_completed
ããããå®äºããã¿ã¹ã¯ãä¸è¦§ãè¨ç®ããã®ãããã¸ãã¯ã®å½¹å²ã§ãããã¸ãã¯ã¯ä»¥ä¸ã®ããã«ãã¥ã¼ã§è¡¨ç¾ã§ãã¾ãã
CREATE VIEW completed_task AS SELECT task.*, comp.completed_at, comp.completed_by FROM current_task task -- current_taskã¯ãåè¿°ãããææ°ã®ã¿ã¹ã¯ã ããåå¾ã§ãããã¥ã¼ã§ã INNER JOIN task_completed comp ON comp.task_id = task.task_id;
è¯ãããã§ãããtask_completed
ãã¼ãã«ã«ãã¼ã¿ããªãã¿ã¹ã¯ã¯ããããå®äºãã¦ããªãã®ã§ããããINNER JOIN
ã§ããªãã¿ã¹ã¯ã¯å
¨ã¦æé¤ãã¦è¯ãããã§ãã·ã³ãã«ã«INNER JOIN
ã ãã§è¡¨ç¾ã§ãã¾ãã
ã¾ããããã§ã¯ãã¥ã¼ã®å®ç¾©ã®ããã«current_task
ãã¥ã¼ãå©ç¨ãã¦ãã¾ãã®ã§ãããã°ãæ¢åã®ãã¸ãã¯ã«æ°ãããã¸ãã¯ãç©ã¿ä¸ãã¦ãæ°ãããã¸ãã¯ãçã¿åºãã¦ããã¨ãè¨ãã¾ãã
ãã®ããã«ãã¤ãã³ããåå¥ã«è¨é²ãããã¸ãã¯ï¼ãã¥ã¼ï¼ã§çµã¿åãããã¨ããæ¹æ³ã§ããã°ã表ç¾ãããç¶æ ãå¢ããã¨ãã¦ããã·ã³ãã«ã«è§£æ±ºã§ãã¾ãã ä¾ãã°ãã¿ã¹ã¯ã¯ä¿çã§ããã¨ããå ´åããã®ãä¿çãããã¨ããã¤ãã³ãããã·ã³ãã«ã«ããä¿çãããã¨ããäºå®ãè¨é²ãããã¼ãã«ãç¨æããã ãã§äºè¶³ãããã§ãã
task_delayed task_id (PK) delayed_until delayed_at delayed_by
ããã¤ã¾ã§ä¿çãããããè¨é²ããããã«delayed_until
ã¨ããã«ã©ã ãå¢ãã¦ãã¾ãããåºæ¬çãªæ§é ã¯task_completed
ã¨åãã§ãããä¿çãããã¿ã¹ã¯ããããå®äºããã¿ã¹ã¯ãã¨åãããã«ãã·ã³ãã«ãªãã¥ã¼ã§è¡¨ç¾ã§ãã¾ãã
CREATE VIEW delayed_task AS SELECT task.*, delayed.delayed_until, delayed.delayed_at, delayed.delayed_by FROM current_task task INNER JOIN task_delayed delayed ON delayed.task_id = task.task_id;
ãã®ããã«ãã¿ã¹ã¯ã«å¯¾ããæ°ããç¶æ
ãå¢ããã¨ãã¦ãããã®ç¶æ
å¤åãè¨é²ããã¤ãã³ããã¼ãã«ãç¨æããã ãã§ãããå
ã®task
ãã¼ãã«ã«æãå ãããã¨ãªããæ°ããªç¶æ
ãã©ãã©ã追å ã§ãã¾ããç¶æ
ãè¨é²ãããããã°ã欲ãããã¼ã¿ã¯ããã¸ãã¯ï¼ãã¥ã¼ï¼ã§å°ãåºããã¨ãã§ãã¾ãã
åé¤ãã¤ãã³ã
ã¿ã¹ã¯ãåé¤ãããå ´åã®ãã¨ãèãã¦ã¿ã¾ãããã
ãããããã¿ã¹ã¯ãåé¤ããããã¨ããã®ã¯ãªãã§ãããããããã®ã¿ã¹ã¯ã¯ãããããªããã¨ã«ãããã¨ããã¦ã¼ã¶ã¼ã®ææ決å®ã§ããããã®æä½ã¯è¨é²ãããã¹ãã§ããçµå±ãåè¿°ã®ãã¿ã¹ã¯ãå®äºãããã¨ããã¿ã¹ã¯ãä¿çãããã¨ãã¨åããªã®ã§ãã
ãªã®ã§ãããã¨ãåãã§ãã
ã¾ããä¸è¨ã®ãããªãã¤ãã³ããè¨é²ãããã¼ãã«ãä½ãã
task_abandoned task_id (PK) abandoned_at abandoned_by
æ¾æ£ãããã¿ã¹ã¯ãè¨ç®ãããã¥ã¼ãä½ãã°OKããã§ãã
CREATE VIEW abandoned_task AS SELECT task.*, ab.abandoned_at, ab.abandoned_by FROM current_task task INNER JOIN task_abandoned ab ON ab.task_id = task.task_id;
ããã§è¯ãããã§ãã
ä»ã¢ã¯ãã£ããªã¿ã¹ã¯ãåå¾ãã
æ¾æ£ãããã¿ã¹ã¯ã¯ããã¯ãã¢ã¯ãã£ããªã¿ã¹ã¯ã§ã¯ããã¾ãããæ®éã®ãã¼ã¿ãã¼ã¹è¨è¨ã§ããã°ãDELETEããããã¼ã¿ã«è¿ããã®ãªã®ã§ããã¯ããã®ã¿ã¹ã¯ã¯åå¨ããªããã¨ããæ±ãããããã§ããã
å ãã¦ãããèãã¦ã¿ãã°ãå®äºããã¿ã¹ã¯ããæ¶ãã¦ã¯ããªããã®ã®ããã¯ããå¦ç対象ã¨ãªããããªãçãããã¿ã¹ã¯ã§ã¯ããã¾ããã
ã¢ããªã±ã¼ã·ã§ã³ã«è¡¨ç¤ºããã¨ããããã¾ã å¦çãã¦ããªãã¿ã¹ã¯ä¸è¦§ã«ã¯è¡¨ç¤ºããããªããã¼ã¿ã§ãããã
ã¤ã¾ãã¯ãææ°ã¿ã¹ã¯ãã¼ã¿current_task
ããããå®äºããã¿ã¹ã¯ããæ¾æ£ããã¿ã¹ã¯ããå
¨ã¦çãããã®ããä»ã¢ã¯ãã£ããªã¿ã¹ã¯ã¨ãããã¨ã«ãªãããã§ãã
ããã¯ãä»ã¾ã§ã«è¨é²ããã¦ã¼ã¶ã¼æä½ã®è¨é²ããããã¸ãã¯ã§åå¾ã§ãããã§ãããä¾ãã°ã以ä¸ã®ãããªãã¥ã¼ãä½ãã°ã©ãã§ããããã
CREATE VIEW active_task AS SELECT task.* FROM current_task task LEFT JOIN task_completed comp ON comp.task_id = task.task_id LEFT JOIN task_abandoned ab ON ab.task_id = task.task_id WHERE comp.completed_at IS NULL AND ab.abandoned_at IS NULL;
task_completed
ã¨ãtask_abandoned
ã¨ãããããã¨ãJOINã§ããªãã¿ã¹ã¯ãæ¢ããã¨ããè¨ç®ãè¡ãããã§ãã
ããã§ä»ã¢ã¯ãã£ããªã¿ã¹ã¯ãåããããã«ãªã£ãâ¦ã¨è¨ãããã¨ãããªã®ã§ãããæ£ç´ããã®ã¯ã¨ãªã¯ã¨ã¦ãé ãã§ãããã
ãã¼ã¿ãå°ãªããã¡ã¯ããã§ãããããå¤ããªã£ã¦ããã¨ãIS NULL
ã¯ã¨ãªã®ããã§ãã¼ã¿ãã¼ã¹INDEXã®å¹æã¯æå¾
ã§ããªãã§ãããããã¥ã¼ã§è¡¨ç¾ã¯ã§ãã¦ããå®ç¨ã¨ãã¦ã¯é
ããããã¸ãã¯ã¨ãããã¨ã«ãªãããã§ãã
ããã¯ãcurrent_task_cache
ãå°å
¥ããæã¨åãã±ã¼ã¹ã§ããtask
ãã¼ãã«ã«ã¯å
¨æ´æ°å±¥æ´ãå
¥ã£ã¦ããããããä»ã®ãã¼ã¿ããå¾ãããã«ã¯ãæ¯åã½ã¼ããã¦ææ°å¤ãåå¾ããå¿
è¦ãããã¾ããããã®ããã«ã¯ãããªãè¤éãªSQLãæ¸ãå¿
è¦ããã£ããããSQLãã·ã³ãã«ã«ããããã©ã¼ãã³ã¹ãæ¹åããããã«ãcurrent_task_cache
ãã¼ãã«ããä»éçãªç¶æ
ãã¨ãã¦å°å
¥ããã®ã§ããã
ä»åãåãã¼ãã«ã¨LEFT JOIN
ãããã®ã¯ããç¶æ
ãè¨é²ãããã¼ãã«ã«ãã¼ã¿ããªããã¨ãã調ã¹ãããã§ããããªã¬ã¼ã·ã§ãã«ã»ãã¼ã¿ãã¼ã¹ã¯ãããããã¼ã¿ããããã¨ãã調ã¹ãã®ã¯é«éã§è¡ãã¾ãããããªããã¨ãã調ã¹ãã®ã¯é
ããã®ã§ãï¼ããããå
¨ãã¼ã¿ãèµ°æ»ããªãã¨ããªããã¨ãã確å®ã§ããªãã§ãããï¼ã
ã§ããã°ãåç´ã«ãä»ã®ç¶æ ããè¨é²ãã¦ããã°ããã§ãããã
task_status_cache task_id (PK) status
status
ã«ã¯ãactive
ãcompleted
ãabandoned
ã®ããããã®å¤ãå
¥ãã¾ããENUM
ãã¼ã¿åãåå¨ãããã¼ã¿ãã¼ã¹ã§ããã°ãENUM
ã¨ãã¦å®ç¾©ãã¦ãããã§ãããã
ãã®ãã¼ãã«ã«ã¯ãããã¿ã¹ã¯ã®ãç¾å¨ã®ç¶æ ããè¨é²ãã¾ãã
ãã¼ã¿ä½æç´å¾ã§ããã°active
ã«ãªããå®äºããã¨completed
ãæ¾æ£ããã¨abandoned
ã«ãªãã¨ããããã§ãã
ãã®ãã¼ãã«ã使ãæã¯ãstatus
ã§æ¤ç´¢ãããã¨ãå¤ãã§ããããããtask_id
ã¨status
ã§INDEXãä½ã£ã¦ãããæ¹ããããã©ã¼ãã³ã¹çã«æå©ã§ãããã
ãã®ãã¼ãã«ã«ãã¼ã¿ãå
¥ããã¿ã¤ãã³ã°ã«ã¯ãè²ã
èãæ¹ãããã§ããããä¸çªåç´ãªæ¹æ³ã¯ãä½æããæãå®äºããæãæ¾æ£ããæã«ãã¤ãã§ã«ãã®ãã¼ãã«ã®INSERT
ãããã¯UPDATE
ãè¡ããã¨ã§ãã
ã¤ã¾ãããã¿ã¹ã¯ã®å®äºããä¾ã«ã¨ãã°ããå®äºãã¨ããæä½ã¯ã
task_completed
ã¸ã®ãã¼ã¿ã®INSERT
task_status_cache
ã®ã対象ãã¼ã¿è¡ã®status
ãcompleted
ã«UPDATE
ãã
ã¨ããï¼ã¤ã®æä½ã«ãªãããã§ãã
å®éã®ããã°ã©ã ã§ã¯ãããããããã¿ã¹ã¯ãå®äºãããã¨ããé¢æ°ãã¡ã½ãããããã¯ãã§ããã®é¢æ°å ã§ãã®æä½ãè¡ãããããã¿ã¹ã¯ãå®äºãããå ´åã¯å¿ ããã®é¢æ°ãå¼ã¶ãã¨ããããã°ã©ã æ§é ãä½ãã°ãé¢æ°ãå¼ã¶å´ããã¯ä¸è¨ã®ï¼æä½ã¯é è½ãããã§ãããã
ãããã¯ããã¿ã¹ã¯ã®ææ°ç¶æ
ãåè¨ç®ããé¢æ°ããããã°ã©ã å
ã«ç¨æãã¦ãããtask_completed
ãtask_abandoned
ãªã©ãç¶æ
ãå¤ãããã¼ãã«ã¸ã®INSERT
å¾ã«ãã®é¢æ°ãå¼ã³åºããã¨ããæ¹æ³ãããã§ããããããããã¼ã¿ã®ç»é²ãå³åº§ã«åæ ãããªãã§ãè¯ãã±ã¼ã¹ï¼æ´æ°ãã¦ã¼ã¶ã¼ã«è¦ããã®ã¯å°ãå¾ã«ãªã£ã¦ãè¯ãã±ã¼ã¹ï¼ã§ããã°ããã®é¢æ°ãéåæã«å®è¡ãã¦ãããã§ãããã
å¾è¿°ãããå®äºç¶æ
ãã復å
ããªã©ã®æä½ãããéã«ãtask
ã®ãä»ãã®statusãåè¨å®ãããå ´åã¯ããã¡ãã®æ¹æ³ã®æ¹ããå®è£
ãç°¡åã«ãªãã§ãããï¼å®äºããã¿ã¹ã¯ã復å
ããå ´åãactive
ã¹ãã¼ã¿ã¹ã«ããã®ãæ£ãããã©ããã¯ãã¢ããªã±ã¼ã·ã§ã³ã®ä»æ§ã«ããã¾ããä¾ãã°ããä¿ç(delayed)ããã¹ãã¼ã¿ã¹ã®ä¸ã¤ã¨ãã¦æ±ããã¦ããã¢ããªã±ã¼ã·ã§ã³ã®å ´åãå®äºããã¿ã¹ã¯ã復å
ããã¨ãã«ãactive
ã«ãªãã¹ããdelayed
ã«ãªãã¹ããã¯ãã¢ããªã±ã¼ã·ã§ã³ã®ä»æ§ã«ããã§ããããã¢ããªã±ã¼ã·ã§ã³ã§å
±éã®ã¿ã¹ã¯ç¶æ
ã®åè¨ç®é¢æ°ãããã°ãåã«ãããå¼ã³åºãã ãã§æ£ããã¹ãã¼ã¿ã¹ã«ãªãã¯ãã§ãï¼
ãããã¯ãå®æçã«åè¨ç®é¢æ°ãéåæã«èµ·åããtask_completed
ãtask_abandoned
ã¸ã®ãã¼ã¿ã®INSERT
ããå¾ãæ¾ç½®ãã¦ããã°ãã©ããã®ã¿ã¤ãã³ã°ã§åæã«å®äºç¶æ
ãæ¾æ£ç¶æ
ã«ãªãã ãããã¨ããä½ãã§ãããããããã¾ããã
ãªãã«ããããã®ä»éçãªç¶æ
ãã¼ãã«ã§ããtask_status_cache
ãå°å
¥ããã°ãã¢ã¯ãã£ããªã¿ã¹ã¯ãåå¾ãããã¸ãã¯ï¼ã¯ã¨ãªï¼ã¯ä¸æ°ã«åç´ï¼ãã¤é«éï¼ã«ãªãã¾ãã
CREATE VIEW active_task AS SELECT task.* FROM current_task task INNER JOIN task_status_cache sts ON sts.task_id = task.task_id WHERE sts.status = 'active';
ããã§ããç¾å¨ã¢ã¯ãã£ããªã¿ã¹ã¯ããåå¾ããããã®ãã¸ãã¯(ãã¥ã¼)ãå®æãã¾ããã
ã¤ãã§ã«ããå®äºããã¿ã¹ã¯ããæ¾æ£ããã¿ã¹ã¯ããè¨ç®ããããã®ãã¥ã¼ãã以ä¸ã®ããã«æ¸ãç´ãã¦ãããã§ãããã
ç¹ã«ãtask_status_cache
ã®æ´æ°ãé
延ããã¦ããå ´åã¯ããã¡ãã®æ¹ããtask_status_cache
ã®å
容ã«ãã£ã¦ã¹ãã¼ã¿ã¹ã確å®ãã¦ããã®ã§ãé½åãè¯ãããããã¾ããã
CREATE VIEW completed_task AS SELECT task.*, comp.completed_at, comp.completed_by FROM current_task task INNER JOIN task_status_cache sts ON sts.task_id = task.task_id INNER JOIN task_completed comp ON comp.task_id = task.task_id WHERE sts.status = 'completed'; CREATE VIEW abandoned_task AS SELECT task.*, ab.abandoned_at, ab.abandoned_by FROM current_task task INNER JOIN task_status_cache sts ON sts.task_id = task.task_id INNER JOIN task_abandoned ab ON ab.stask_id = task.task_id WHERE sts.status = 'abandoned';
ä¿çããã¿ã¹ã¯(delayed_task
ï¼ã«ã¤ãã¦ãã対象ã¿ã¹ã¯ãããã¯ãã¢ã¯ãã£ãã§ãªãï¼å®äºãããæ¾æ£ããããããï¼ã¿ã¹ã¯ã ã£ãå ´åã«ã¯ãä¿çããã¿ã¹ã¯ã¨ãã¦ãä¸è¦ã¨ãªãã®ã§ããã¥ã¼ãå°ãå¤æ´ããactive_task
ãã¥ã¼ã«ä¾åããããã«å¤æ´ããæ¹ãè¯ãããã§ãã
CREATE VIEW delayed_task AS SELECT task.*, delayed.delayed_until, delayed.delayed_at, delayed.delayed_by FROM active_task task INNER JOIN task_delayed delayed ON delayed.task_id = task.task_id;
è¦æ¯ã¹ã¦ã¿ãã¨ãããã¾ãããFROM
å¥ããcurrent_task
ããactive_task
ã«å¤ãã£ãã ãã§ãããã®ããã«ããã¥ã¼ã¨ãããã¸ãã¯ãå°å
¥ãããã¨ã§ããã¥ã¼å士ãçµã¿åãããæ°ãããã¸ãã¯ãå°å
¥ãããã¨ãã§ããããã§ãã
ããã¾ã§ã®éç¨ã§ããå¿ é ã®ç¶æ ããè¨é²ãããã¼ãã«ã«ã¯ä¸åæãå ãããä»éçãªç¶æ ã®å°å ¥ã¨ããã¥ã¼ã®å®ç¾©å¤æ´ã ãã§å¯¾å¿ãã¾ããããã¸ãã¯ï¼ãã¥ã¼ï¼ã§ãç¶æ ã¨ã¤ãã³ããçµã¿åããã¦ã欲ãããã¼ã¿ãä½ãåºãææ³ãªã®ã§ãä¸çªå¤§åãªãå¿ é ã®ç¶æ ããè¨é²ãããã¼ãã«ã«ã¯æãå ãããã¨ãªãããã¸ãã¯ãåæ§æããã ãã§ã欲ãããã¼ã¿ãå¾ããã¨ãã§ãã¦ããããã§ãã
è¦ç´ ãã·ã³ãã«ãªã¾ã¾ã«ããçµã¿åããããã¨ã§ã欲ãããã¼ã¿ãä½ãåºã
Immutable Data Modelã§ã¯ããã¼ã¿ã®UPDATE
ãè¡ããªããã¨ãçæ³çã§ãããå®éã®ãã¼ã¿ãã¼ã¹è¨è¨ã§ã¯ãæ¬å½ã«INSERT
ã ãã§æ§æããã¨ãããã©ã¼ãã³ã¹ãªã©ã®å¤ãã®åé¡ãçºçãããã¨ãããã¾ãã
ãªã®ã§ã"Out of the tar pit"ã®èãæ¹ããã¼ã¹ã«ããã¦ã¼ã¶ã¼å
¥åããè¨é²ãããå¿
é ã®ç¶æ
ãã§ãããã¼ãã«ã¨ãããã§ãªãã·ã¹ãã é½åã®ãã¼ãã«ã¨ãåé¢ãããå¿
é ã®ç¶æ
ãã§ãããã¼ãã«ã«ã¯Immutable Data Modelã®èãæ¹ãå¾¹åºãã¦INSERT
ããè¡ãããããã«ããããã©ã¼ãã³ã¹ãã¯ã¨ãªã®è¤éåãªã®ã©ã®åé¡ã¯ããä»éçãªç¶æ
ãã¨ãã¦å°å
¥ããã·ã¹ãã ãã¼ãã«ã«ãã£ã¦è£ããã¨ããæ¦è¡ãåãã¾ããã
ã©ããã¦ã¼ã¶ã¼å ¥åã表ããå¿ é ã®ç¶æ ãã§ãããã©ããã·ã¹ãã é½åã®ãä»éçãªç¶æ ããªã®ããæ確ã«ããããã«ãä»éçãªç¶æ ãè¨é²ãããã¼ãã«åã«ã¯ãæå³çã«ã_cacheãæ¥å°¾è¾ãã¤ãããã¨ã§è¦è¦åãè¡ãªã£ã¦ãã¾ãã
ã¾ããå®éã«ã¢ããªã±ã¼ã·ã§ã³ã§å¦çããããã¼ã¿ã¯ãã¦ã¼ã¶ã¼å ¥åã®çµã¿åããã«ãã£ã¦å¾ããããè¨ç®çµæãã®æ¹ã§ãããã¨ãå¤ãã®ã§ããããã®ãã¸ãã¯ããã¥ã¼ã§è¡¨ç¾ãã¦ãã¾ãã
ãã®ä½ãã§ã¯ãã¢ããªã±ã¼ã·ã§ã³ã®ãã¼ã¿ã¢ã¯ã»ã¹ï¼å¤æ´ã¨åå¾ï¼ã¯ã
- ã¢ããªã±ã¼ã·ã§ã³ããã¼ã¿ãå¤æ´ããæã«ã¯ããå¿ é ã®ç¶æ ãã¨ãä»éçãªç¶æ ããæ´æ°ãã
- ãã¼ã¿ãä¿åããããã«ã¯ãå°ç¨ã®é¢æ°ãã¡ã½ãããç¨æããããã°ã©ã ããã¯å¿ ããã®é¢æ°çµç±ã§ä¿åãããããªã·ã¹ãã æ§æãä½ããã¨ã§ããå¿ é ã®ç¶æ ãã¨ãä»éçãªç¶æ ãã確å®ã«æ´æ°ãããããã«ãã
- ã¢ããªã±ã¼ã·ã§ã³ããã¼ã¿ãåå¾ããæã«ã¯ããå¿ é ã®ãã¸ãã¯ãã§ãããã¥ã¼ãããã¼ã¿ãåå¾ãã
ã¨ããã®ãåºæ¬çãªæ§æã«ãªãã¾ãã
å¿ é ã®ç¶æ ãä»éçãªç¶æ ãåé¢ããå¿ é ã®ç¶æ ã®ä¸ã§ããã¤ãã³ããè¦æ¥µãã¦ç´°ããå°ããªãã¼ãã«ã«åå²ãã¾ãããããã«ãããè¦ç´ ã¯å¢ãã¾ããããä¸ã¤ä¸ã¤ã®ãã¼ãã«ã¯ãä¸ç¨®é¡ã®ãã¼ã¿ãã管çãã¦ããªãããã«ã§ãã¾ããããã®ãããªåç´ãªãã®ãããã¥ã¼ã¨ããããã¸ãã¯ãã使ã£ã¦çµã¿åããããã¨ã§ãå®éã«æ¬²ãããã¼ã¿ãä½ãåºãã¦ãã¾ãã
ãã®ãããªèãæ¹ã¯ãClojureéçºè ã®Rich Hickeyãçºè¡¨ãããSimple Made Easyãã¨ãããã¬ã¼ã³ãã¼ã·ã§ã³ã§èª¬æãããã·ã³ãã«ããã¨åæ§ãªãã®ã§ããRich Hickeyã¯ããã·ã³ãã«ãããããç°¡åã§ãããã¨ã¯åºå¥ãã¦èª¬æãã¾ãããã·ã³ãã«ã§ããã¨ã¯ãããããä¸ã¤ã®äºæããæ±ã£ã¦ããªããã¨ãããã¨ã§ãããã®éããä¸ã¤ã®ãã®ã§ããããã®ãã®ãæ±ã£ã¦ããç¶æ ã§ããããã®ãããªç¶æ ããComplectãã¨ãã£ã¦ãããããã®ç´ã絡ã¾ãåã£ã¦ãããããªç¶æ ã ã¨èª¬æãã¦ãã¾ãã
ãã·ã³ãã«ãªãã·ã¹ãã ã¨ã¯ããããããä¸ã¤ã®å½¹å²ããæã£ã¦ããªããã®ããçµã¿åããããã¨ã§ä½ãããã·ã¹ãã ã§ããããã®ããã«ä½ãããã·ã¹ãã ã¯ãçµã¿åããæ¹ãå¤ãããã¨ã§ãèªç±ã«åæ§æã§ããã®ã§ãã
ã¾ããRich Hickeyã¯ãç©äºãã·ã³ãã«ã«ãããã¨ããã¨ãè¦ç´ ã®æ°ã¯å¢ãããã¨ãè¨ã£ã¦ãã¾ããå®éãä»åã®è¨è¨ã§ã¯ãæ¥ä»ã«ã©ã ãåèã«ããã¼ã¿ã®è¨é²ã¨ã¤ãã³ãã®è¨é²ãåé¢ããçµæãä¸ã¤ã®ãã¼ãã«ã«ããããã®æ¥ä»ã«ã©ã ããããããªãã¼ãã«ãããããã¼ãã«æ°ãå¢ãã¦ãã¾ããããã«ã表ç¾ãããã¤ãã³ããå¢ãããã³ã«ããã¼ãã«æ°ã¯å¢ãã¦ãããã¨ã§ãããã
ä¸æ¹ã§ãä¸ã¤ä¸ã¤ãã·ã³ãã«ã«ãã¦åå²ããããããããã¸ãã¯ã«ãã£ã¦ãçµã¿åããã«ãã£ã¦æ¬²ãããã¼ã¿ãä½ãåºããã¨ãã§ãã¦ãã¾ããä»åã®è¨è¨ã§ã¯ãOut of the tar pitã®ãç¶æ ã¨ãã¸ãã¯ã®åé¢ããå¿ é ã¨ä»éçã®åé¢ããåãå ¥ãããã¨ã§ããã¼ã¿ãã¼ã¹ã«ä¿åãããã¼ã¿ããå¿ é ã®ç¶æ ãä»éçãªç¶æ ãããããçµã¿åãããããã®ãã¸ãã¯ï¼ãã¥ã¼ï¼ã¨ããå½¢ã«å解ããããã¼ãã«ã¨ããå½¢ã§è¡¨ç¾ãããç¶æ ãããã¥ã¼ã¨ããå½¢ã§è¡¨ç¾ããããã¸ãã¯ã«ãã£ã¦çµã¿åããããã¨ããæ¹æ³ãæ¡ç¨ãã¾ããã
ãã®æ¹æ³ã§ããã°ãåã ã®ãã¼ãã«ãã·ã³ãã«ã«ç¶æãã¤ã¤ããã大ããªã·ã¹ãã ãæ§æãããã¨ãã§ããã®ã§ã¯ãªãã§ããããã
çºå±çã«æ§æãå¤åããã
ããã§èª¬æããä½ãæ¹ã¯ãåãªãã¢ã¤ãã¢ã¨ããããã§ã¯ãªããå®éã®ã¢ããªã±ã¼ã·ã§ã³ã§ãå©ç¨ãã¦ãã¦ãå®ç¨æ§ããããã®ã§ãããå®éã®ã¢ããªã±ã¼ã·ã§ã³ã§ã¯ããã£ã¨è¾¼ã¿å ¥ã£ãç¶æ å¤åã管çããªããã°ãããªãã±ã¼ã¹ãããã¾ãã
ä¾ãã°ããééã£ã¦å®äºããã¿ã¹ã¯ã¯ã復å ãããã¨ãã§ãããã¨ããä»æ§ãããã¨ããããã©ãã§ããããã
- 誤ã£ãæä½ãªã®ã ãããåã«èª¤ã£ã¦æ¿å
¥ããã
task_completed
ãåé¤ï¼DELETEï¼ãã¦ãã¿ã¹ã¯ã®statusãåè¨ç®ããã°ãã - å®äºããã¿ã¹ã¯ã復å ããã®ã¯ã¦ã¼ã¶ã¼æä½ãªã®ã ããããããè¨é²ãããªããã°ãããªã
ã©ã¡ãã®æãããã§ããããã1ãåããã2ãåããã¯ãã¢ããªã±ã¼ã·ã§ã³ã®ä»æ§ã¨ããã¬ã¼ããªãã絡ãã§ããã®ã§ãä¸æ¦ã«ããã¨ãããã¨ã¯ã§ãã¾ãããåãªãã¢ã³ãã¥å¦çã§ããã¨èããã°ã1ã®é¸æè¢ãããã§ããããã¦ã¼ã¶ã¼å
¥åãè¨é²ããå¿
é ã®ç¶æ
ã§ããtask_completed
ã«DELETE
ãå®è¡ãããã¨ã«ãªãã¾ãããã¢ã³ãã¥ã ã¨èããã°ãã·ã¹ãã çã«å
ã®ç¶æ
ã«å¾©å¸°ããã¨ããæå³ã§ãé¸æçã«ã¯ããã§ãããããã¡ããã1ã®é¸æè¢ã¯ããå¿
é ã®ç¶æ
ãã§ããã¯ãã®task_completed
ãã¼ãã«ã«å¯¾ãã¦DELETE
ãå®è¡ãããã¨ããç¦å¿ãç¯ãã¦ããï¼ã¨èãããã¨ãã§ããã§ãããã
2ãé¸æããå ´åã¯ãtask_completion_reverted
ã®ãããªããå®äºããã¿ã¹ã¯ã復å
ããããã¨ãè¨é²ãããã¼ãã«ãå¿
è¦ã«ãªãããã§ãã
åãã¿ã¹ã¯ã«å¯¾ãã¦ããå®äºãæä½ãè¤æ°åçºçãããã¨ã«ãªããããtask_completed
ã¯ãtask_id
ããã¼ã¨ãããã¼ãã«ã§ã¯ãã¡ã«ãªãã¾ããhistory_id
ã®ãããªãè¡ãç¹å®ãããã¼ãå¿
è¦ã«ãªãã§ãããã
è¤æ°ã®task_completed
ã®ã©ããã¢ã¯ãã£ããªã®ããç¹å®ããããã«ãtask
ãã¼ãã«ã®ããã«ããã¤ã³ã¿ã¼ãã¼ãã«ãç¨æãã¦ææ°ã®ã¬ã³ã¼ããç¹å®ããæ¹æ³ãããã§ããããããã¡ãã¯å±¥æ´æ
å ±ã¨ããããã¯ãrevertãããtask_completed
ã¨ãactiveãªtask_completed
ããããã¨ãããã¨ãªã®ã§ãåè¿°ã®task_status_cache
ã®ããã«ãtask_completed
ã«å¯¾ãã¦ç¾å¨ã®ã¹ãã¼ã¿ã¹ã表ãã·ã¹ãã ãã¼ãã«ãç¨æããã¨ããæãããã§ãããã
ãããã¼ãã«ã®é¢é£ãã¼ãã«ã¨ãã¦ãç¶æ
ã表ããã¼ãã«ãå°å
¥ããï¼ä¾ãã°ãtask
ã«å¯¾ãã¦task_delayed
ã¨ããé¢é£ãã¼ãã«ãç¨æããï¼å ´åã®å¯¾å¿æ¹æ³ãä¸å®ã«ä¿ã¤ã¨ããã¼ãã«æ§æå
¨ä½ã®ç解ãç°¡åã«ãªãã¾ãã®ã§ãããã¯ãã¹ãã¼ã¿ã¹ãã¼ãã«ãå°å
¥ããæ¹æ³ã§ããã¾ãããã
task_completed_status_cache
ãã¼ãã«ãå°å
¥ãã¾ãã
task_completed history_id (PK) task_id completed_at completed_by
task_completed_status_cache task_completed_history_id (PK) status
status
ã«ã©ã ã¯ãactive
ãããã¯reverted
ã§ãtask_completed
ä½ææã«ã¯active
ã¨ãã¦INSERT
ãã¦ãããå®äºããã¿ã¹ã¯ã®å¾©å
ãè¡ãããã¿ã¤ãã³ã°ã§ã
task_completion_reverted
ãã¼ãã«ã«INSERT
ãã¾ãï¼å¾©å ã®äºå®ãè¨é²ããï¼task_completed_status_cache
ã®status
ãreverted
ã«UPDATE
ããtask
ã®ã¹ãã¼ã¿ã¹ãæ´æ°ããé¢æ°ãå¼ã³åºã
ä¸è¨æä½ããããã¨ã§ã復å ããã¾ãã
ä»ã¾ã§ã®task_completed
ã¨åããã¼ã¿ãåãããã®ãã¥ã¼ãç¨æãããã¨ã§ãä»ã®é¨åã¯ãã¥ã¼ãåç
§ããã°ãä»ã¾ã§ã¨åãç¶æ
ãç¶æã§ãã¾ãã
CREATE VIEW active_task_completed AS SELECT comp.* FROM task_completed comp INNER JOIN task_completed_status_cache sts ON sts.task_completed_history_id = comp.history_id WHERE sts.status = 'active';
ãã®ãã¥ã¼ã¯ãå
ã
ã®task_completed
ã¨åããã¼ã¿ãè¿ãã¯ãã§ãã
ã¤ã¾ããtask
ãã¼ãã«ã§è¡ãªã£ãã®ã¨åããã¨ãæ·¡ã
ã¨å®æ½ãã¦ããã°ãå¿
è¦ãªæ
å ±ã¯æ¼ããªãè¨é²ã§ãããããã¥ã¼ãä»ãã¦ãå
ã®ãã¼ãã«ã¨åããã¼ã¿ã簡便ã«åããããã«ä½ããã¨ãã§ããããã§ããã©ã®ãã¼ãã«ã§ãèãæ¹ã¯ä¸è²«ãã¦ããããã¼ã¿å©ç¨å´ããè¦ãã¨ãä»ã¾ã§task_completed
ãç´æ¥è¦ãã°è¯ãã£ãã¨ããããactive_task_completed
ãã¥ã¼ãåç
§ããããã«å¤ããã ãã§ãããã
å³ï¼ã¯ãä»è¡ããã¨ãã¦ããæ¡å¼µãè¡ãåã®ç¶æ ã表ãã¦ãã¾ãã
task_completed
ããtask
ã¨åããããªå±¥æ´ç¶ã®ãã¼ãã«ã«å¤ããã¨ãããããã以ä¸ã®ãããªæ§æã«ãªãã§ãããã
task
ã§è¡ã£ãã®ã¨åãææ³ããtask_completed
ã§ãè¡ããactive_task_completed
ã¨ãããã¸ãã¯ï¼ãã¥ã¼ï¼ã«ãã£ã¦ãå
ã®task_completed
ã¨åãç¶æ
ãä½ãåºãã¦ãã¾ããããããã¢ããªã±ã¼ã·ã§ã³ããã¼ã¿ãèªã¿åãã¨ãã«ã¯ãcompleted_task
ãªã©ã®ï¼å³ã®ä¸çªä¸ã«ããï¼ãã¥ã¼ã使ã£ã¦åå¾ãã¦ããã¯ããªã®ã§ãã¢ããªã±ã¼ã·ã§ã³ã³ã¼ãããã¼ã¿ãå©ç¨ãã¦ããé¨åã«å½±é¿ãä¸ãããã¨ã¯ããã¾ããï¼ãã¡ãããä¿åé¨åã«ã¯ä¿®æ£ãå¿
è¦ã§ããï¼ã
ãã®ããã«ããã®ã¢ããªã³ã°ã®å©ç¹ã¯ãç¶æ³ãè¤éåãã¦ããããã¼ãã«ã追å ããããå¿ è¦ãªãã°ä»éçãªç¶æ ã¨ãªãcacheãã¼ãã«ã追å ããããããããçµã¿åããã¦æ¬²ãããã¼ã¿ãè¨ç®ãããã¥ã¼ãä½ããã¨ããä½æ¥ãç¹°ãè¿ãã¦ãããã¨ã§ãã¤ã¾ããåãããæ¹ãç¹°ãè¿ãé©ç¨ãã¦ããã ãã§ãã¢ãã«ãçºå±ããã¦ãããã¨ãã§ããã¨ããã«ããã¾ããææ³ã®ä¸è²«æ§ã¯ãå ¨ä½ãææ¡ãããã¨ãç°¡åã«ãã¦ããã¾ãã
å ¨ä½ãè¤éã«è¦ãã¦ãããã®ãã¼ãã«ããåºæ¬ã¨ãªãå¿ é ã®ç¶æ ã表ããã¼ãã«ãªã®ã ãªããããã¦ãã¡ãã¯ãã·ã¹ãã é½åã®ä»éçç¶æ ãã¼ãã«ãªãã ãªããå¤ãåãã¨ãã¯ããã¡ãã®ãã¥ã¼ãåç §ããã°åãããã¨ããã大æ ãåããããã«ãååã¥ããªã©ã§å·¥å¤«ããã°ãèªã¿è§£ããã¨ãã§ããã®ã§ãã
éã®å¼¾ä¸¸ãããªã
Immutable Data Modelãæ¡ç¨ããã¨ãINSERT
ã ãã§ãã¼ã¿ãæ§æãã¦ããé¢ä¿ä¸ãå¿
ããå±¥æ´ç¶ã®ãã¼ã¿ãç¾ãã¾ããå±¥æ´ä¸ã®ãã¼ã¿ã¯ããã段éã§ã®ãã¼ã¿ãã©ãã ã£ãã®ããè¨ç®ããã°ç¹å®ã§ããã¨ããç¹ã§å©ç¹ãå¤ãã§ãããå
¨ã¦ã®ã·ã¹ãã ã§å¿
è¦ã¨ããããã§ãããã¾ããã
å¤ãã®ãã¸ãã¹ããã»ã¹ã§ã¯ããå ¨ã¦ã®ã¦ã¼ã¶ã¼æä½ãè¨é²ãã¹ãããã¨ãã質åã¸ã®åçã¯ãå®ã¯ãYesãã«ãªããã¨ã®æ¹ãå¤ãã§ããç´ã®ä¼ç¥¨ç®¡çã ã£ãæ代ã§ããä¼ç¥¨ã¯ãã¨ã§æ¸ãæãããã¨ã¯ã§ãããã赤ä¼ç¥¨ï¼èµ¤ä¼ï¼ãã§ãã£ã³ã»ã«ãè¨é²ãããé»ä¼ç¥¨ï¼é»ä¼ï¼ãã§ä¿®æ£ãã¼ã¿ãè¨é²ããããªã©ãæç³»åã«å¤æ´å¦çãå ¨ã¦ãããããã«ãªã£ã¦ãããããã§ããã¸ãã¹ããã»ã¹ã§ã¯ãã³ã³ãã¥ã¼ã¿å¦çããããåãããå±¥æ´ãè¨é²ããã®ã¯å½ããåã ã£ãã®ã§ããããããæ¥ã«å¿ è¦ãªããªããã¨ã¯ããã¾ãããç¾ä»£ã§ããçºæ³¨ããã£ã³ã»ã«ãããããã¨ãã£ã¦ãçºæ³¨ãã¼ã¿ãæ¶ãã¦ããããã§ã¯ãªãã®ã§ããããããå±¥æ´ã¯è¨é²ãããã¹ãã ãã¨èããæ¹ãç¾å®ã®ãã¸ãã¹å®æ ã«åã£ã¦ããã¯ãã§ãããããã®ç°å¢ã«ãImmutable Data Modelã¨ãããã§æ¸ããææ³ã¯å½¹ç«ã¤ã§ãããã
ã§ããä¸ã®ä¸ã«ã¯ããã¸ãã¹ããã»ã¹ã表ç¾ãã¦ããããããªãã¢ããªã±ã¼ã·ã§ã³ãããããããããã§ããããã§Immutable Data Modelãæ¡ç¨ããã¨ãä»ã¾ã§UPDATE/DELETEããã°è¯ãã£ãã¨ããã«ãæ¥ã«å±¥æ´ç®¡çãææ°ãã¼ã¿ç¹å®ãªã©ã®å¦çãå ¥ãè¾¼ãã§ãããã¨ã«ãªãã¾ãã
ãªã®ã§ãããã¹ã¦ãImmutable Data Modelã«ãªãã¹ããã¨èããå¿ è¦ã¯ãªãã§ãããã
ä¸æ¹ã§ããImmutable Data Modelããã®ãããæ´»ãããé åã¨ããã®ãééããªãããã®ã§ï¼åè¿°ã®ãã¸ãã¹ããã»ã¹ãªã©ï¼ãä»ä½ããã¨ãã¦ããã¢ããªã±ã¼ã·ã§ã³ããªããªã®ãã«ãã£ã¦ãæ¡ç¨ãã¹ããã©ãããã£ã¡ãå¤æãããã¨ã大äºã§ãããã
Immutable Data Modelã¯ãèãæ¹ã ããå è¡ãã¦åºã¾ã£ã¦ããç¶æ ãªã®ã§ãã©ãå®ç¾ãããã¯ãåå¥ã«æ¤è¨ããå¿ è¦ãããã¾ããããã®å®éã®å®ç¾ææ³ã¨ãã¦ãã²ã¨ã¤ã®ãããããæ¹æ³ã§ã¯ã¨ãªããã©ã¼ãã³ã¹ãç¶æããªããå®ç¾ã§ããããã¨ããæ¡ã¨ãã¦åèã«ãã¦ããããã°ã¨æãã¾ãã
çµãã
ãã¾ã©ãã®Clojureã®ã¯ãããã
Clojure 1.9ããããããClojureã®å§ãæ¹ã大ããå¤ãã£ãã®ã§ããããã®è¾ºããã¾ã¨ããè¨äºãè¦å½ãããããã§ã«Clojureããã£ã¦ã人ããç¥ããªãç¶æ ã£ã½ãã®ã§ãæ¥ãã§æ¸ãã¦ã¿ã¾ããã
大ããå¤ãã£ãã®ã¯ã clojure
ããã³ clj
ã¨ããã³ãã³ããå°å
¥ããããã¨ã§ããããã¾ã§ã¯Clojureã®å®è¡ã«ã¯ Leiningen
ã®ãããªãã«ããã¼ã«ã使ãã®ãä¸è¬çã§ãã¹ã¯ãªããçãªã³ã¼ããæ¸ãã®ã«ã¯åãã¦ãªãå°è±¡ã§ãããã1.9ããã¯ã clojure
ã³ãã³ãã« .clj
ãã¡ã¤ã«ã渡ãã¨å®è¡ã§ããããã«ãªãã¾ãããã¾ããã³ãã³ããç¨æããããã¨ã§ãã·ã§ã«ã»ã¹ã¯ãªããåé ã« #!
㧠clojure
ã³ãã³ãã¸ã®ãã¹ãæ¸ããã¨ã§ãã·ã§ã«ã¹ã¯ãªããã¨ãã¦Clojureã³ã¼ããè¨è¿°ã§ããããã«ãªãã¾ããã
ãã®äºã¤ã®ã³ãã³ããã¤ã³ã¹ãã¼ã«ããæé ããç°å¢ãã¨ã«ç¨æããã¦ãã¾ãã
ã¤ã³ã¹ãã¼ã«
Mac
homebrewã«å¯¾å¿ãã¦ã¾ãã
brew install clojure
Linux
ã¾ã apt-getãyumã¨ãã«ã¯å¯¾å¿ãã¦ãã¾ããããã¤ã³ã¹ãã¼ã«ã»ã¹ã¯ãªãããç¨æããã¦ããã®ã§ããããå®è¡ããã°ç°¡åã«ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
ãã¡ãã®ãã¼ã¸ã«æ¸ãã¦ããï¼è¡ã®ã³ãã³ããå®è¡ããã¨ãClojureãã¤ã³ã¹ãã¼ã«ããã¾ãã
https://clojure.org/guides/getting_started#_installation_on_linux
Windows
æ®å¿µãªãããã¾ã æä¾ã§ãã¦ããªãããã§ãã ã¨ã¯ãããclojureã¯åãªãjarãã¡ã¤ã«ãªã®ã§ãclojure.jarãæåé ç½®ãããã¨ã§ãªãããã¡ããå®è¡å¯è½ã§ãã
ããããMicrosoftèªèº«ãWindowsã§åãLinuxç°å¢ãæä¾ãã¦ããã®ã§ããã£ã¡ã§å®è¡ããæ¹ãç°¡åãªããã«æãã¾ãã
REPL
ãªã«ã¯ã¨ããããREPLã§ãã
Clojureãã¤ã³ã¹ãã¼ã«ããã¨ãclj
ã³ãã³ãã¨clojure
ã³ãã³ãã®ï¼ã¤ã®ã³ãã³ãã使ããããã«ãªãã¾ãã
clj
ã³ãã³ãã®ã»ããREPLå®è¡ç¨ã³ãã³ãã§ããåã«clojure REPLã®å®è¡ã ãã§ã¯ãªããREPLä¸ã§ã®ã³ãã³ããã¹ããªæ©è½ãªã©ããªã³ã«ãªããããã»ããã¢ãããã¦ããã¾ãã
clojure
ã³ãã³ãã¯.cljãã¡ã¤ã«ãå®è¡ããããã®ã³ãã³ãã§ãããã¡ããããã®ã§ãclojureãã¤ã³ã¹ãã¼ã«ããã¦ããç°å¢ã§ããã°ã #!/usr/bin/env clojure
ãã¹ã¯ãªãããã¡ã¤ã«ã®å
é è¡ã«æ¸ããã¨ã§ãã·ã§ã«ã¹ã¯ãªããã®ããã«clojureããã°ã©ã ãå®è¡ãããã¨ãã§ãã¾ãã
ã¨ããããã§ãclj
ã³ãã³ããå®è¡ããã¨ãClojure REPLãèµ·åãã¾ãã
(+ 1 2) ;;=> 3 (require '[clojure.string :refer [split upper-case]]) ;=> nil (->> (split "aaa,bbb,ccc" #",") (map upper-case)) ;=> ("AAA" "BBB" "CCC")
Clojureã®é¢æ°ãè¦ãã¦ããã¨ãã¡ãã£ã¨ããè¨ç®ã¨ãã¯REPLã§ããã£ã¨ããã°ã©ã æ¸ããããã¦ãã¾ãã¾ãã
使ãçµãã£ãããCtrl+dã§çµäºã§ãã
ã¹ã¯ãªãããæ¸ã
Clojure 1.9ããã¯ãClojureèªä½ã«ä¾åã©ã¤ãã©ãªãå¦çããæ©è½ãçµã¿è¾¼ã¾ãã¾ããã1.8ã¾ã§ã¯ãLeiningenãªã©ã®ãã«ããã¼ã«ãå¿ è¦ã§ããããå¿ è¦ãªãã¨ããä¾åã©ã¤ãã©ãªã®èªåãã¦ã³ãã¼ããã ããªã®ãªããClojureåä½ã§ã§ããããã«ãªã£ãã®ã§ãã
ãã¡ããããã«ããã¼ã«ã«ã¯ä¾åæ§ç®¡ç以å¤ã«ãããããªæ©è½ãããã¾ãããã¡ãã使ãããå ´åï¼ãããã¸ã§ã¯ããè¦æ¨¡ã«ãªãã¨å¤§æµã¯å¿ è¦ã§ãããï¼ã¯ãClojureåä½ã§ã¯é£ããã®ã§ãããªãã«ãã«ããã¼ã«ã使ãã¾ããããä¸çªã¡ã¸ã£ã¼ãªã®ã¯ Leiningen ã§ãããã¡ããã¤ã³ã¹ãã¼ã«ã¹ã¯ãªãããããã¾ãï¼Windowsç¨ã®batãã¡ã¤ã«ãããï¼
ãã¦ãã¡ãã£ã¨ããã¹ã¯ãªãããæ¸ããããã©ããã®ããã«ã¯å¤é¨ã©ã¤ãã©ãªãå¿ è¦ã ãã¨ããã±ã¼ã¹ã¯ããããã¾ãããã¨ãã°Clojureã§httpã¢ã¯ã»ã¹ãå¿ è¦ãªå ´åãclj-http ã¨ããæåãªã©ã¤ãã©ãªã使ããã¨ãå¤ãã§ãããå½ç¶ããã¯ãå¥éç¨æããå¿ è¦ãããã¾ããã
Clojure 1.9ã«ã¯ã deps.edn
ã¨ããç¹æ®ãªãã¡ã¤ã«ãã«ã¬ã³ãã»ãã£ã¬ã¯ããªã«é
ç½®ãããã¨ã§ãå¿
è¦ãªä¾åã©ã¤ãã©ãªãèªåãã¦ã³ãã¼ãããæ©è½ã追å ããã¾ããã
clojureã³ãã³ããå®è¡ããã¨ãã«ãã«ã¬ã³ãã»ãã£ã¬ã¯ããªã«deps.ednãããã°ããã®ä¸ã«è¨è¿°ãããä¾åã©ã¤ãã©ãªããã¹ã¦ãã¦ã³ãã¼ããã¦ãããã¹ã¯ãªãããå®è¡ãã¾ããã¤ã¾ããã¹ã¯ãªããã¨ãã¦æ¸ããclojureããã°ã©ã ï¼ããã¹ããã¡ã¤ã«ï¼ã¨ãã£ããã«deps.ednãé ããã¨ã§ãã¹ã¯ãªããããå¤é¨ã©ã¤ãã©ãªãå©ç¨ãããã¨ãã§ãã¾ãã
deps.ednã®è§£éã¯ãclojure
ã³ãã³ãå®è¡æã ãã§ãªããclj
ã³ãã³ãå®è¡æã«ãè¡ããã¾ãã®ã§ãREPLã§ä½æ¥ããããã©ããã®ä½æ¥ã«ã¯å¤é¨ã©ã¤ãã©ãªãå¿
è¦ãã¨ããã¨ãã«ããããã£ã¨deps.ednãæ¸ãã°ãREPLå
ã§å¤é¨ã©ã¤ãã©ãªã使ããã¨ãã§ãã¾ãã
deps.ednã¯æ¬¡ã®ãããªãClojureã®ãããææ³ã§æ¸ããããã¡ã¤ã«ã§ãã
{:deps {clj-http {:mvn/version "3.9.0"}}}
ãã®ãããªãã¡ã¤ã«ãããã¦ãããã£ã¬ã¯ããªã§clj
ã³ãã³ããå®è¡ãã¦ã¿ã¾ããããREPLèµ·åæã«clj-httpã®ãã¦ã³ãã¼ããè¡ããã¾ãã
ã¡ãã£ã¨ãhttpæ¥ç¶ã試ãã¦ã¿ã¾ããããã
(require '[clj-http.client :as http]) ;=> nil (http/get "https://google.co.jp/" {}) ;=> Googleãã¼ã¸ã®HTMLããã¹ã
ãããªæãã§ãå¿ è¦ãªã©ã¤ãã©ãªã使ã£ã¦REPLã§ä½æ¥ã§ããããã§ãã
deps.ednã使ã£ã¦ããå°ãè¤éãªããã°ã©ã ãçµã
1ãã¡ã¤ã«ã¨ããã»ã©å°ããã¯ãªããã©ããã«ããã¼ã«ä½¿ãã»ã©ã§ããªãã使ãæ¨ã¦ã®ãã¼ã«ããã°ã©ã ãä½ããã¿ãããªãã¨ãããã§ããããClojureã ã¨ãããã°ã©ã ã¯åå空éã«åå²ãã¦æ¸ãã¦ããã®ãæ®éã§ãããããã¨ãã¡ã¤ã«ãè¤æ°ã«ãªãã¾ãããåå空éã«é層ãããå ´åã¯ããã£ã¬ã¯ããªãå¿ è¦ã§ãã
deps.ednã¨åãå ´æã« src
ã¨ãããã£ã¬ã¯ããªãããã°ããã®ä¸ã«ã½ã¼ã¹ãã¡ã¤ã«ãé
ç½®ããã¦ãããã®ã¨è§£éãã¾ããsrcã®ä¸ã«ãåå空éã«åããããã£ã¬ã¯ããªé層ãä½ãã°ãã¡ããã¨ã½ã¼ã¹ãè¦ã¤ãåºãã¦ããã¾ãã
- deps.edn - helloworld.clj - src/ - util/ - string.clj - net.clj
ä¸è¨ã®ããã«é
ç½®ããã°ããã®ããã°ã©ã ã¯ã helloworld.clj
ã¨ããå®è¡ç¨ã¹ã¯ãªããã¨ã¯å¥ã«ã
- util.string
- util.net
ã®ï¼ã¤ã®åå空éã追å ãããããã°ã©ã ã¨ãªãããã§ãããã¨ãã°ã helloworld.clj
ãããrequire
ã使ã£ã¦ãutil.string
ãutil.net
åå空éãå©ç¨ãããã¨ãã§ãã¾ãã
Clojureåä½ã§ããdeps.ednã¨çµã¿åããããã¨ã§ãã¡ãã£ã¨è¦æ¨¡ã®å¤§ããã®ããã°ã©ã ã§ããä½ããã¨ãã§ããããã§ãã
ã¨ãã£ã¿ãç¨æãã
Clojureã¯LISPç³»ã®è¨èªã§ãã®ã§æ¬å¼§ãå¤ç¨ãã¾ãããä¸ã®LISPerãã¡ãã©ãæ¬å¼§ãæ±ã£ã¦ããã¨ããã¨ãæ¬å¼§ã®å¯¾ããè¦ã¥ãããã®ãã¨ãã¦ã§ã¯ãªãããããå©ç¨ãã¹ããæ§é ãã¨æãã¦ãã¾ããå ¨ã¦ãæ¬å¼§ã§å²ããã¦ããã®ã ãããæ¬å¼§åä½ã§ç§»åãããã«ãããããã§ãããå°ç¨ã®ã¨ãã£ã¿æ©è½ã使ã£ã¦ãã¾ãããã®æä½ã«æ £ããã¨ãæ¬å¼§ã«ã¯ãããããããã¿ãæããã®ã§ãã
Clojureããã°ã©ãã¯ãã¨ãã£ã¿ã®åã使ã£ã¦ãæ¬å¼§ãå·§ã¿ã«å©ç¨ãã¾ãããã ã®ããã¹ãã¨ãã£ã¿ã§æ¬å¼§ãæ±ãã®ã¯ã誰ã§ãã¤ãããã®ã§ããããã¯ãä»ã®è¨èªã§ãåãã§ããããªãã¿ã®è¨èªããä½ã®ãµãã¼ãããªãããã¹ãã¨ãã£ã¿ã§æ¸ããã¨ããã¨ãçµæ§å¤§å¤ãªã¯ãã§ãã
ã¾ããæ¸ãã¦ããããã°ã©ã ãREPLã使ã£ã¦ãã£ã¨åä½ç¢ºèªãã¤ã¤æ¸ãã¦ãããã¨ããã¹ã¿ã¤ã«ãã¡ã¸ã£ã¼ãªã®ããããã¨ãã£ã¿ããç°¡åã«REPLãèµ·åããããREPLã«ã½ã¼ã¹ãéãè¾¼ãã ããREPLããä½æä¸ã®ããã°ã©ã ã®åå空éã«ã¢ã¯ã»ã¹ãã¦é¢æ°ãå®è¡ããããããã¸ã§ã¯ãå ã®é¢æ°ãæ¢ãããããããããã°ãIDEçãªæ©è½ã欲ããã§ãã
ãããã®ãµãã¼ããªãã«Clojureã³ã¼ããæ¸ãã®ã¯ãã¯ã大å¤ã§ããã ã®ããã¹ãã¨ãã£ã¿ã§Javaãæ¸ãçãªããã©ããããã¾ããã ãããClojureããµãã¼ãããã¾ã¨ããªã¨ãã£ã¿ãç¨æãã¾ãããã
Clojureã§ãã£ã¨ãã¡ã¸ã£ã¼ãªéçºç°å¢ã¯
Emacs + CIDER
ã§ããã¨ãã£ã¿ã¨ãã¦emacsãããã®ãã©ã°ã¤ã³ã®CIDERãIDEæ©è½ã¨ãã¦éçºãã¾ãã
ãããEmacsã¯å¾æãããªããã©Vimã¯ä½¿ãããã¨ããæ¹ã ã¯
Spacemacs + CIDER
ã§ããSpacemacsã¯Vimãã¼ãã¤ã³ãã§ä½¿ããemacsã®ãããªãã®ã§ãCIDERã使ãã¾ãã
ããããã©ã¡ããå¿å¾ããªããã¨ããæ¹ããããã°ã©ã è¨èªãã¯ãããã®ã«EmacsãVimã®ãããªè¤éãªã¨ãã£ã¿ãè¦ããã¨ããããå§ããªãã¨ãããªããã¨ããã®ã¯ãã¾ãã«ããã¼ãã«ãé«ãã¨æãã¾ãã
ãªã®ã§ãç§ã®ä¸æ¼ãã¯ãæè¿ããããªè¨èªããµãã¼ããã¦ããã¨ã§ã¦ã¼ã¶ã¼ã®å¤ããIntelliJ IDEAã使ããã¨ã§ããIDEAã®ãã©ã°ã¤ã³ã¨ã㦠Cursive ã¨ããClojureéçºæ¯æ´ãã©ã°ã¤ã³ãããã¾ãããã¡ãã¯ãã¸ãã¹ã§ä½¿ãå ´åã¯ææã§ããããªã¼ãã³ã½ã¼ã¹éçºãå¦ç¿ç¨ã¨ã§ã¯ç¡æã§ããææçã¯ãå人ã«ç´ä»ãã©ã¤ã»ã³ã¹ã ã¨99ãã«ã§ããä¼æ¥å¥ç´ã§å人ã«ç´ä»ãããªãï¼ãããããã©ã¤ã»ã³ã¹æ°ãã§è²·ãã¿ã¤ãï¼ã ã¨ããã¡ãã£ã¨é«ãã§ãã
ã¨ãããããå¦ç¿ç¨ã«è©¦ãåã«ã¯ç¡æã§ãã®ã§ãããããã¾ããåºæ¬çãªã¨ãã£ã¿æä½ã¯ãIDEAã®æ¨æºæä½ããã®ã¾ã¾ä½¿ãã¾ãã®ã§ããã§ã«IDEA使ã£ã¦ãããªãå¦ç¿ã³ã¹ããä½ãã§ããCursiveã«ã¯REPLãµãã¼ããããããä½æ¥ä¸ã®é¢æ°ãREPLã«éãæ©è½ãªã©ãåãã£ã¦ã¾ãã
ï¼ãã¸ãã¹ã§ã¤ãããªããèªåãä»äºã§ä½¿ããã¼ã«ãä½ã£ã¦ãããä½è ã¸ã®æ¬æã¨ãã¦ãã¡ããã¨ãéãæããï¼
æ§é ç·¨é (Structural Editing)
ãããã®ã¨ãã£ã¿ã使ãã«ãã¦ããæ¬å¼§ããã£ãããå¹ççã«æ±ãããã® æ§é ç·¨é(Structural Editing)
ãè¦ãããã¨ããããããã¾ããPareditã¨ãParinferãæåã§ããSpacemacsã ã¨ãSPC+kãæ¼ããã表示ãããã¡ãã¥ã¼ã«ãæ§é ç·¨éã®ããã®é
ç®ãããã¾ãã
Clojureã§ã³ã¼ããæ¸ãã¦ããã¨ãããã®æ¬å¼§å ã«æ¬¡ã®è¡ã®æ¬å¼§ã丸ãã¨ç§»åããããã¨ãããã®é¨åãæ¬å¼§ã®å¤ã«è¿½ãåºããããã¨ãããã®æ¬å¼§å ã®ã³ã¼ããããä¸è¦ã ãã丸ãã¨æ¶ããããã¨ãããã®æ¬å¼§å ¨ä½ã丸ãã¨ã³ãã¼ããããã¨ãã£ããã¨ãããã£ã¡ã ãããã¾ããæ§é ç·¨éã§ãããã§ãã¾ãã
(my-great-func {:name "yano", :place "japan"})
ã®ãããªããã°ã©ã ãããã¨ãã¦ãããã£ã¨ããã® my-great-func
ãå®è¡ããã«ã¯æ¡ä»¶ããããã ã£ããwhenãifã§å²ããªãã¨...ãã¨èããã¨ãã¾ãã
(when condition (my-great-func {:name "yano", :place "japan"})
ã¨ãæ¸ãã¦ãã°ãããã§ãï¼ä¸ã®ã³ã¼ãã¯ãéãæ¬å¼§ã足ãã¾ããï¼ã
ã¾ããæ§é ç·¨é使ç¨ä¸ã¯ãæ¬å¼§ã¯å¸¸ã«ãã¢ã§æ¸ãè¾¼ã¾ãã¾ããéãæ¬å¼§ãæ¸ãã¨éãæ¬å¼§ãèªåçã«æã¡è¾¼ã¾ãã¾ãã次ã®ãããªæãã«ãªãã§ãããã
(when condition) (my-great-func {:name "yano", :place "japan"})
åæã«ãã¢ã«ãªãã®ã§ã(when conditionã¨æ¸ãã¦ããã¨ãå¿ ãæ¬å¼§ã®å å´ã«ãªãã¾ãã
ããã§ãconditionã®å¾ãã«ã(my-great-func ...)
ã®æ¬å¼§ã丸ãã¨æã£ã¦ãããããã§ãã
ãã¼æä½ã¯ã¨ãã£ã¿ã«ãã£ã¦ç°ãªãã¨æãã¾ãããSpacemacs+CIDERãªããwhen condition
ã®æ¬å¼§ã®å
å´ã«ã«ã¼ã½ã«ãããç¶æ
ã§ããSPC k sãã¨ãã¼ãæã¤ã¨ããSlurpï¼å¸ãåãï¼ãã¨ããæä½ãå®è¡ããã¾ããã¤ã¾ãã(when ...) ã®æ¬¡ã«ãã(my-great-func ...)ã¨ããæ¬å¼§ã®ãããã¯ãã(when ...)ã®æ¬å¼§ã®ä¸ã«å¸ãè¾¼ãããã§ãã
çµæã¨ãã¦ã次ã®ãããªã³ã¼ãã«å¤ããã¾ã
(when condition (my-great-func {:name "yano", :place "japan"}))
- æ¬å¼§ãæã¡è¾¼ãã¨å¸¸ã«ãã¢ã§æã¡è¾¼ã¾ãã
- æ¬å¼§åä½ã§ãé£ã®æ¬å¼§ãå¸ãè¾¼ãã ããä»ã®æ¬å¼§ãå¤ã«è¿½ãåºããããããã¨ã§ãã«ããï¼ãã¼ã¹ãã«ãã£ã¦ééã£ã¦æ¬å¼§ãæ¶ãã¦ãã¾ããªã©ã®ãã¹ãèµ·ããªããªã
- æ¬å¼§åä½ã§ç§»åããã®ã§åãªãã«ããï¼ãã¼ã¹ãããå§åçã«ãã¹ãã«ãã
Clojureããã°ã©ãï¼ããã¦ããããã¯LISPããã°ã©ãï¼ã¯æ§é ç·¨éã§æ¬å¼§ãæ±ã£ã¦ããã®ã§ãæ¬å¼§ããã©ãã§éãã¦ãã®ãããããããªãèªã¿ã«ãããã®ãã§ã¯ãªããæ¬å¼§åä½ã§è¿½ãåºãããå¸ãè¾¼ãã ããã«ããããããã¼ã¹ããããã§ããã便å©ãªç·¨éåä½ã ãã¨æã£ã¦ãã®ã§ããããªããéãæ¬å¼§ã¨éãæ¬å¼§ã§å²ããã¦ãããã¨ããLISPã®ç¹æ§ããã£ã¦ãããªã®ã§ãã
ä½è«ã§ãããClojureã¯æ¬å¼§ã®ç¨®é¡ã () ã ãã§ã¯ãªãã[], {}, ãªã©ã使ãã®ã§ãã¨ãã£ã¿ä¸ã§ã¯ããããè²åãããã¦ã¡ãã£ã¨èªã¿ããããã¨ããå©ç¹ããã£ãããã¾ãã
æ§é ç·¨éã«ã¯ããããªæ©è½ããã£ã¦ãæ£ç´ç§ãå ¨é¨è¦ãã¦ã¯ããªãã§ãã
- Slurp ï¼é£ã®æ¬å¼§ãå¸ãè¾¼ãï¼
- Barf ï¼æ¬å¼§ã追ãåºãï¼
- ã«ãã ï¼æ¬å¼§åä½ã§ã®ã«ããï¼
- ã³ãã¼ ï¼æ¬å¼§åä½ã§ã®ã³ãã¼ï¼
- åé¤ ï¼æ¬å¼§ã丸ãã¨æ¶ãï¼
ãã®ï¼ã¤ãè¦ããã ãã§ãä½æ¥å¹çãå ¨ãå¤ãã£ã¦ããã®ã§ãããããã§ãã
Slurpã¨Barfã¯ããåãå¸ãè¾¼ããã¨ãå¾ããå¸ãè¾¼ãããªã©ãåå¾ã©ã£ã¡ãå¦çãããã§ããããã2種é¡ããã¾ãããã¾ãã¯ãå¾ããå¸ãè¾¼ãããå¾ãã«è¿½ãåºããã®ã»ããè¦ãããã¨ããããããã¾ããå®éã®ã³ã¼ãã£ã³ã°ã§ãããããã¨ã¯ã大æµãã£ã¡ã®ã¯ãã§ããæ £ãããåãå¦çã§ããããã«è¦ããã°ããã§ãããã
æ§é ç·¨éã¯ãEmacs, Spacemacs, Cursiveã®ãããã®ã¨ãã£ã¿ã§ã使ãã¾ãããã ãããããã®æ©è½ãå¼ã³åºããã¼æä½ã¯ã¨ãã£ã¿ã«ãã£ã¦ç°ãªã£ã¦ããã®ã§ãèªåã®å¥½ããªã¨ãã£ã¿ã§ã®æä½ã調ã¹ã¦ã¿ã¦ãã ããã
ã¾ã¨ã
JavaVMãå
¥ã£ã¦ããåæã§ããã°ãClojure 1.9ããã¯ã clojureã³ãã³ãã®ã¤ã³ã¹ãã¼ã«
ã ãã§ãç°¡åã«Clojureãå§ããããã·ã§ã«ã»ã¹ã¯ãªããã®ããã«Clojureã³ã¼ããå®è¡ãããã¨ãã§ããããã«ãªãã¾ãããè¥å¹²ãã¼ãã«ãä¸ãã£ãããã«æãã¾ããã¾ãã deps.edn
ãå°å
¥ããããã¨ã§ãå¤é¨ã©ã¤ãã©ãªãã¹ã¯ãªããã³ã¼ãããç°¡åã«å©ç¨ãããã¨ã§ããããã«ãªãã¾ããã
ã¡ãã£ã¨ã試ãã¦ã¿ãã®ã¯ã©ãã§ããããã
ãªãã¸ã§ã¯ãæåã¨ã¯ã¾ã£ããéãClojureã®ä¸çã¨å®éã®Webéçº
ä»åã¯ãè¨äºã§ã¯ãªããã京é½ãLINE Developer Meetup #38ã§ãClojureã¨Webéçºã«ã¤ãã¦è©±ããã®ã§ããã®æã®ã¹ã©ã¤ããç´¹ä»ãã¾ãã
ãã¡ãããã覧ãã ãããï¼æ³¨ï¼Slideshareã®ä»æ§ãªã®ããå ã®ã¹ã©ã¤ãã§ã¯æ¹è¡ä½ç½®ãªã©æã£ã¦ããã®ãå´©ãã¦ãã¾ã£ã¦ãã¾ãï¼
Clojure + core.async ã«ããéåæï¼ä¸¦åããã»ã¹ã®ä¸ç
core.asyncã«ããéåæããã°ã©ãã³ã°
core.async ã¯Clojureç¨ã®ãäºå®ä¸æ¨æºã®éåæããã°ã©ãã³ã°ã®ã©ã¤ãã©ãªã§ãã
core.asyncã®ä¸çªãããããã説æã¯ããGo-langã®channelã®Clojureçãã¨ããè¨ãæ¹ã§ããããgoãã¯ãã«ãã£ã¦go-blockãä½ãããã®ãããã¯å ãéåæã«åãã¾ãããã®ãããã¯ã常é§ããã°ã軽éããã»ã¹ã¨ãããã¤ã«ãªãã¾ããããã»ã¹å士ã®ããã¨ããããå£ã¨ãã¦ããã£ãã«(channel)ãããã¾ããcore.asyncã使ã£ãããã°ã©ã ã§ã¯ããã£ãã«ã¸ã®å ¥åºåãä»ãã¦éåæ軽éããã»ã¹ã«ãã¼ã¿ãå¦çããããã¨ã§ãå ¨ä½ã®ã·ã¹ãã ãä½ãä¸ãã¾ãã
goãã¯ãã¯ã¹ãã¼ããã·ã³ãä½ãããã£ãã«ã¸ã®å ¥åããããã³ã«ãã·ã³ãï¼å転ãã¾ãããã®ä¸å転æã«ããã£ãã«ãå¾ ã¡åãã¦ããgoãããã¯ã«ã¹ã¬ãããå²ãå½ã¦ããã次ã®ãã£ãã«å ¥åºåã¾ã§CPUã使ã£ã¦å¦çãåãããã£ãã«ã®å ¥åºåã§ã¾ãå¥ã®goãããã¯ã«å¦çãæ ããã¨ããå½¢ã§ãéãããCPUä¸ã§ãã¹ã¬ãããå±±ã»ã©èµ·åãããã¨ããªããå¹çããåä½ããã®ã売ãã®ä¸ã¤ã§ãã
ãã®ãããªä»çµã¿ï¼OSã®å調åãã«ãããã»ã¹ã¨åããããªåçï¼ãªã®ã§ãgoãããã¯ã¯å®éã«ã¯ããã»ã¹ã§ãã¹ã¬ããã§ã¯ãªããã¹ãã¼ããã·ã³ã«ãã£ã¦ç®¡çãããããã°ã©ã åä½ã«éãã¾ããããã£ã¦ãcore.asyncã¯ã¹ã¬ãããä¸ã¤ã§ãã£ã¦ãã¡ããã¨åãã¾ããcore.asyncéçºå½åãããClojureScriptï¼JavaScriptããã¹ãè¨èªã¨ããClojureå®è£ ï¼ã§ãåããã¨ãæ³å®ãã¦ä½ã£ã¦ããã¨ãããã¨ã§ãã®ã§ããªãã§ã¯ã®å®è£ ã§ãããã
ã·ã³ãã«ãªä»çµã¿
core.asyncã®ä½¿ãæ¹ã«ã¤ãã¦ã¯å ¬å¼ããã¥ã¡ã³ãã¨ãã®ã»ãã詳ããã®ã§è©³ç´°ã¯ãã¡ããè¦ã¦ãããã¨ãã¦ãç°¡åã«æ¦è¦ã ããæ¸ãã¨ãå®è¡åä½ãgoã§å²ã¿ããã®ãªãã§channelãèªãã ãæ¸ãããããã¨ãgoã§æ¸ãããå®è¡åä½ã次ã ã¨åãæ¿ãã£ã¦å®è¡ããã¾ãã
以ä¸ã¯ãCloureã®REPLã«æã¡è¾¼ãã°ãã®ã¾ã¾åä½ãããcore.asyncã使ã£ãããã°ã©ã ã³ã¼ãã§ãã
(import '[java.util Date]) (require '[clojure.core.async :refer [chan go-loop >! <! timeout] :as async]) (def ch (chan)) ; ãã£ãã«ãä½ã ;; æ¸ãè¾¼ã¿éåæããã㯠(go-loop [] (when (>! ch (Date.)) ; ãã£ãã«ã«æ¸ã (<! (timeout 2000)) ; 2ç§å¾ 㤠(recur))) ;; èªã¿è¾¼ã¿éåæããã㯠(go-loop [] (when-let [date (<! ch)] ; ãã£ãã«ãèªã (println "now:" date) (recur)))
go-loop
ã¯
(go (loop [] ;; å¦ç ))
ã®çç¥å½¢ã§ãå¤ç¨ããã®ã§ç¨æããã¦ãã¾ãã
åç´ãªgoãããã¯ã¯ãéåæå¦çãçµããã¨ããï¼åº¦ã¨å®è¡ããã¾ãããããããloopããã°ããã£ã¨åãç¶ããéåæãããã¯ããä½ãã¾ãããããã軽éããã»ã¹ãã«è¿ããã®ã§ãã軽éããã»ã¹å士ããã£ãã«ã使ã£ã¦ãã¼ã¿ãããã¨ããããã¨ããããã°ã©ã ãä½ãã«ã¯ãæ¯ågoã¨loopãæ¸ããªããã°ãããªãã¦ãå°ã é¢åãªã®ã§ãäºã¤ãã¾ã¨ããgo-loopãã¯ããç¨æããã¦ãã¾ãã
ãã®ããã°ã©ã ã¯ãçæ¹ã®goãããã¯ãç¾å¨æ¥æããã£ãã«ã«æ¸ãè¾¼ãã§2ç§å¾ ã¤ãããä¸ã¤ã®goãããã¯ã¯åããã£ãã«ãèªã¿è¾¼ã¿ãèªããããããç»é¢ã«åºåãã¾ãããããã®goã«ã¼ãããã£ãã«ãéããããã¾ã§loopãç¶ãã¾ããç¾å¨æå»ãçæããããã»ã¹ã¨ãåãåã£ãæå»ãåºåããããã»ã¹ã®ãï¼ã¤ã®è»½éããã»ã¹ãåãã¦ããã¨èããã°ããã§ãããã
ãã®ããã«ãcore.asyncã§ã¯ãããã°ã©ã ãå¦çåä½ãã¨ã«goãããã¯ã§å²ã£ã¦éåæå¦çã«ãããã®goãããã¯éã§ã®ãã¼ã¿ã®ããã¨ãã«ã¯ãã£ãã«ã使ãã¾ãã
goãããã¯ã¯ããã£ãã«ãããã¼ã¿ãèªã¿æ¸ããããã¨ãã¦ããããã£ãã«ã«ã¾ã ãã¼ã¿ããªãã£ããããã£ãã«ã«ã¾ã æ¸ããªãç¶æ
ã ã£ãããparkï¼å¾
æ©ï¼ç¶æ
ã«ãªãã¹ã¬ããã解æ¾ãã¾ããããã¦æºåãã§ããã°ã¾ãã¹ã¬ããã«å²ãå½ã¦ããã¦åãåºãã¾ãã
é常ã«å°ãªãã¹ã¬ããæ°ã§ãããããã®éåæãããã¯ãå®è¡ã§ããããã§ãã
è¤éãªã¹ã¬ããå¶å¾¡ãæ¸ããªãã¨ããã·ã³ãã«ã«ãã£ãã«ãèªã¿æ¸ãããã¨ãããgoã§å²ããã¨ã§ãç°¡åã«å¹çãã並åããã°ã©ã ãæ¸ããã®ãcore.asyncã®å¼·ã¿ã§ããããã°ã©ã ãæ¸ãå´ã¯åç´ã«ãããããã¨ãä¸ããä¸ã¸æ¸ãã¦ããã ãã§ããã®ã§ããcallback hellã¨å¼ã°ãããããªãéåæã³ã¼ã«ããã¯é¢æ°ãä½æ®µã«ãéãªããããªãã¨ã¯ããã¾ãããgoãããã¯ãä¸ããã©ãã©ãæ¸ãã¦ããã°ããã®ã§ãã
ã¨ãããã¾ã§ã¯ãcore.asyncã«ãã¨ãã¨åãã£ã¦ããåºæ¬æ©è½ã§ããããã«ãClojure 1.7ã®è¨èªæ¡å¼µã«ãããæ°ããè¦ç´ ã追å ããã¾ããããã®æ©è½ã«ãããcore.asyncã¯ä¸æ®µã¨ä¾¿å©ã«ãªãã¾ããã
Transducerã®ç»å ´
core.asyncã®ããã«ãClojureã®è¨èªã¬ãã«ã§ã®æ¡å¼µã¾ã§ãè¡ããã¾ãããããããClojure 1.7ã§ã®Transducersã®å°å ¥ã§ãã
Transducerã¨ããã®ã¯ãããã£ã±ã«è¨ãã¨ãmapå¦çãfilterå¦çããã対象ã¨ãªããªãã¸ã§ã¯ãï¼ã³ã¬ã¯ã·ã§ã³ï¼ãçãã¦ãå¤æå¦çã ããæãåºãã¦æ½è±¡åãããã®ã§ãã(map change-fn coll)ã¨ããå¦çãªããéè¦ãªãã®ã¯ãã²ã¨ã¤ã²ã¨ã¤ã®è¦ç´ ã«change-fnãé©ç¨ãããã¨ããå¤æå¦çã§ãã£ã¦ãcollã¯å¼æ°ã«éããªããã ã£ãããã®å¤æå¦çé¨åã ããæãåºãã¦å¥ã®ãªãã¸ã§ã¯ãã¨ãã¦æ±ããããã«ããããã¨ããããã§ãã
å®éãtransducerã®ä½ãæ¹ã¯ãä¸ã®èª¬æéãã®ãã®ã§ãã
(map change-fn coll) ; ãã¤ãã®mapå¦çãcollã®åè¦ç´ ã«change-fnãé©ç¨ããé 延ãªã¹ããä½ãåºã
(let [xf (map change-fn)] ; åæ§ã®å¦çãè¡ãtransducerãçæãããå¼æ°ã¯å¾ãã渡ããã¨ãã§ããã (sequence xf coll)) ; collã®åè¦ç´ ã«xfã¨ããtransducerãé©ç¨ããé 延ãªã¹ããä½ã
ãã¤ãã®mapãfilteré¢æ°å¼ã³åºãæã«ã対象ã¨ãªãcollectionã渡ããªããã°ãå¤æå¦çã ããåãåºããtransducerã«ãªãã®ã§ãã
ããã«ãtransducerã¯åæãããã¨ãã§ãã¾ããtransducerã¯ç¹å®ã®ã«ã¼ã«ã«åã£ã¦å®è£ ãããé¢æ°ã«éããªãã®ã§ãClojureæ¨æºã®é¢æ°åæé¢æ° comp ã§ç°¡åã«åæã§ãã¾ãã
(comp 第1ã®transducer 第2ã®transducer 第3ã®transducer)
ãã ã®é¢æ°ãcompããå ´åãä¸çªå¾ãã®é¢æ°ããé ã«å®è¡ããã¾ãããããtransducerã®å ´åããã®æ§é ä¸ãå®éã®å®è¡ã¯é ããè¡ããã¾ããä¸ã®ä¾ã§ã¯ã第1ã®transducerããé ã«ã3ã¾ã§å®è¡ãããããªãåætransducerãã§ãã¾ãã
(require '[clojure.string :as string]) ;; string/upper-caseã§å¤§æåã«mapããå¾ã ;; T以å¤ã®ãã®ã«filterããtransducerãä½ã (def xf (comp (map string/upper-case) (filter #(not= % "T")))) ;; sequenceã¯å¼æ°ã«transducerãé©ç¨ãããªã¹ããä½ã ;; 大æåã«å¤æãããå¾ãTã§ãªãæåã ãã«filterããã¾ãã (apply str (sequence xf "TEST")) ; => "ES"
ãªããã®ãããªã¢ã¤ãã¢ãç¨æããããã¨ããã¨ãï¼çµç·¯ã¯ãããããããã§ãããããç§ã®èªèã§ã¯ï¼core.asyncã®éçºéä¸ã§å¿
è¦æ§ãèªèãããããã§ãããã¨ãã¨core.asyncã«ã¯ããã£ãã«ã«å
¥åºåãããã¼ã¿ã«å¯¾ãã¦mapãfilterãå®è¡ããããã®ãå°ç¨ã®é¢æ°ãããããç¨æããã¦ãã¾ããã clojure.core.async/map>
ã¨ããã§ããæ¨æºã®mapé¢æ°ã¨ã®éãã¯ãå¦ç対象ãã³ã¬ã¯ã·ã§ã³ããã£ãã«ããã¨ããéãã ãã§ãå®éã«ãããããã¨ï¼mapããããfilterãããï¼ã¯åããªããã§ããã ã£ããããã®åãé¨åã ããæãåºããã¨ããã®ã¯èªç¶ãªçºæ³ã§ãã
ã¨ããããã§ãClojure 1.7ã«ã¯Transducerãå°å
¥ãããmapãfilterã¨ãã£ããã¨ãã¨ãã£ãå¤ãã®é¢æ°ãæ¡å¼µããã¦ããã¾ã¾ã§ã®å¦çã®ã»ãã«ãtransducerãä½ãåºãæ©è½ã追å ããã¾ããã
åæã«ãcore.asyncã«ãã£ããå°ç¨ã®mapãfilterã¨ãã£ãé¢æ°ç¾¤ã¯ãdeprecatedæ±ãã¨ãªãã¾ããã代ããã«ããã£ãã«ã«å¯¾ãã¦transducerãè¨å®ãããã¨ãã§ããããã«ãªãã¾ãããããã«ããããã£ãã«å
¥åºåï¼é¢æ°ã®å®è¡ãã¨ããä¸çãã§ããããã¾ããã
ç¾å¨ã®core.asyncã¯ãåãªãClojureçgoã«ã¼ãã³å®è£ ã®åãè¶ ãã¦ãtransducerã®å°å ¥ã«ãããé¢æ°å®è¡ã¨ã³ã¸ã³ã¨ãã¦ã®æ©è½ãåãã¾ããã
;; å ¥åããæååã大æååããtransducerãè¨å®ãããã£ãã«ãçæãã (require '[clojure.string :as string] '[clojure.core.async :refer [chan go >! <!]]) (let [ch (chan 1 (map string/upper-case))] ; 大æååããtransducerãã»ãããããã£ãã«ãä½ã ; å°æåãæ¸ãè¾¼ãã§ã¿ã (go (>! ch "test")) ; èªã¿è¾¼ãã§åºåããã¨ã大æåã«ãªã£ã¦ããï¼ (go (println "result:" (<! ch)))) ;;=> result: TEST
core.asyncã«ã¯ããã£ãã«ã¨ãã£ãã«ãçµåãã pipe
ã¨ããé¢æ°ãããã®ã§ãããã使ã£ã¦å¤æå¦çãã¤ãªãããã¨ãã§ãã¾ãã
(require '[clojure.core.async :refer [chan go-loop >! <! pipe onto-chan]]) (let [only-odd-ch (chan 1 (filter odd?)) ; å¥æ°ã ããéããã£ãã« double-ch (chan 1 (map #(* % 2))) ; ï¼åã«ãããã£ãã« ch (chan) piped (-> ch (pipe only-odd-ch) ; ch ã only-odd-ch ã«é£çµãã (pipe double-ch))] ; åè¡ã®é£çµçµæãããã« double-ch ã«é£çµãã ;; onto-chané¢æ°ã¯å é¨ã§goãããã¯ã使ã£ã¦ã³ã¬ã¯ã·ã§ã³ã®ä¸èº«ãéåæã«ãã£ãã«ã«æ¸ãè¾¼ã (onto-chan ch [1 2 3 4 5 6]) ;; é£çµããæ«å°¾ã«ããpipedãããéåæã«ãã¼ã¿ãä¸ã¤ãã¤èªã (go-loop [] (when-let [data (<! piped)] (println "data:" data) (recur)))) ;; å¥æ°ã®1, 3, 5 ã2åã«ãªã£ã¦é çªã«åºåããã ; => data: 2 ; => data: 6 ; => data: 10
pipeã«ãã£ã¦ãã£ãã«ãçµåãã¦transducerãé 次å®è¡ãã¦ãããã¨ãã§ããããã§ãã
ãããããã ãã§ã¯ãé¢æ°ãé 次å®è¡ãã¦ããã ãã§ãç´æ¥é¢æ°ãå¼ã¶ã®ã«æ¯ã¹ã¦ãããã©ããããªã£ã¦ãã ãã§ã¯ãªãã§ããããã
å®ã¯ããã ãã§ããé¢æ°ãç´æ¥å¼ã³åºãã®ã¨ã¯éãå©ç¹ãããã®ã§ãããããã¯ä¸æ¦ç½®ãã¾ããããcore.asyncã¯ä¸¦åå®è¡ã©ã¤ãã©ãªã§ããtransducerã®å®è¡ã並ååãã¾ãããï¼
pipelineã«ããé¢æ°ã®ä¸¦åå
transducerã®ç»å ´ã§ããã¼ã¿ã®å¤ææä½ãç°¡åã«æ½è±¡åãããã¨ãã§ããããã«ãªãã¾ããããã£ãã«ã®å ¥åºåã¨é¢æ°ãç´ä»ãããã¨ãå¯è½ã«ãªã£ãããã§ãã
ããã§pipelineãç»å ´ã§ãã
pipelineã¨ããã®ã¯ããã®åã®éãï¼ãã£ãã«ã¨ãã£ãã«ã®ï¼ãã¤ãã©ã¤ã³ãæ§ç¯ããé¢æ°ã§ãããã¤ãã©ã¤ã³ã®æ§ç¯ã«ã¯ãå
¥åã¨åºåã®ãã£ãã«ã«å ãã¦ãå®è¡ãããé¢æ°ãããã«ä¸¦åæ°ãæå®ã§ãã¾ãã
pipelineé¢æ°ã¨ã¯ããã£ãã«ãããã£ãã«ã«ãã¼ã¿ã転éããã¨ãã«é¢æ°ãé©ç¨ããã¨ããå¦çã®ããé¢æ°ãé©ç¨ãããé¨åã並ååããããã¨ãããã®ã§ãã
(pipeline 4 out-ch my-great-transducer in-ch)
ãã®ï¼è¡ã§ãin-chããout-chã¸ã®ãã¤ãã©ã¤ã³ãæ§ç¯ããã¦ãin-chã«ãã¼ã¿ãå ¥ããã¨ãout-chããåºåããã¾ãããã®éä¸ã«ãmy-great-transducerã«ãããã¼ã¿ãå¦çãããã®ã§ããããã®transducerã®å®è¡ã¯ãæ大ã§ï¼ä¸¦åã§å¦çããã¾ãï¼ã¡ãªã¿ã«ãout-chã¸ã¯in-chã«ãã¼ã¿ãå ¥ã£ã¦ããé åºã§çµæãåºåããããã¨ãä¿è¨¼ããã¦ããã®ã§ãé çªã¯å£ãã¾ããï¼ããã£ãã«ã«ç«ã¦ç¶ãã«ï¼ã¤ãã¼ã¿ãå ¥ã£ã¦ããã°ããããã¯ä¸¦åã§å¦çãããã¨ãããã¨ã§ãã
ãã£ãã«ãtransducerãpipelineã®3ã¤ã§ãcore.asyncã®å½¹è ããããã¾ãããcore.asyncã¯Clojureã§goãããã¯ãå®ç¾ããã©ã¤ãã©ãªã§ããã¤ã¤ããã®ä¸ã«ããtransducerã¨ããå¤æé¢æ°ã並åå®è¡ããpipelineãæ§ç¯ãã¦ããã®pipelineå士ãã¤ãªãããã¨ã§ä¸¦åããã°ã©ã ãæ§ç¯ãããã¨ããä¸çãã§ãã¦ãããã§ãã
ãã®ä»çµã¿ã¯ãé¢æ°ã«ããããã°ã©ã ã¢ãã«ã«ãããæå³ã§ã®å½±é¿ãä¸ãã¾ãã
ãã¨ãã°ãããããã®ãªã¯ã¨ã¹ããåãä»ãããµã¼ãããã°ã©ã ã§ããã¼ã¿å¦çããã»ã¹ãä¸ã¤åå¨ãã¦ãããã«å¦çãä¾é ¼ãããããªããã°ã©ã ã¢ãã«ãèãã¦ã¿ã¾ãããããµã¼ãããã°ã©ã ã¯ãããããã®ãªã¯ã¨ã¹ãã並åã«åãä»ãã¾ãããããã®ã¨ã³ã¸ã³ããã¡ãã並åã§åãã¦ã»ããã§ãããªãã°ããã¼ã¿å¦çãè¡ãpipelineãæ§ç¯ãã¦ããã®å ¥åãã£ãã«ã«ãã¼ã¿ãå ¥ããã°ããã®ã§ãï¼ pipelineãã並åå¦çãå®è¡ãã軽éããã»ã¹ã¨ãªãã®ã§ãã
pipelineã¯å ¥åããªãéãå¾ æ©ãã¦CPUãæ¶è²»ãã¾ããããå ¥åãã£ãã«ã«æ¸ãè¾¼ãã°ãã¤ã§ãåãã¾ããgo-loopã§å¦çãç¹°ãè¿ãã®ã¨åããã¨ããpipelineã¯è¡ã£ã¦ãã¾ãããã ãgo-loopã¯å¦çãéåæåãã¦ããã¯ãã¦ãã並ååã¯ãã¦ããã¾ãããpipelineã¯ãtransducerã並åã«å®è¡ãã¦ããã¾ãã
å¹ççãªãã¼ã¿å¦çã¨ã³ã¸ã³ãæ§ç¯ãã
ãã®ããã°ã©ã ã¯ãµã¼ãããã°ã©ã ãªã®ã§ãããããã®ãªã¯ã¨ã¹ããå¤é¨ããåãä»ãã¾ããç§é100ã¨ããã£ã¨ã¨ããã¨ã«ãã並åã«ããããã®è¦æ±ãåãä»ãã¾ãã
ä¸æ¹ã§ãµã¼ãã®CPUæ°ã«ã¯éããããããã§ããã¹ã¦ã®ãªã¯ã¨ã¹ããã¨ã«ãã¼ã¿å¤æé¢æ°ãç¡å¶éã«ã¯å®è¡ãããããã¾ãããä¸åº¦ã«å®è¡ããå¤æå¦çã¯ãä¾ãã°CPUã³ã¢æ°ã¾ã§ã¨ãã«çµãããããã§ããããã§ãããã°ã©ã ã®ä¸å¿ã«ããã¼ã¿å¤æã¨ã³ã¸ã³ãã¨å¼ã¶ãå ¥åºåãåãä»ããããã»ã¹ãç¨æãã¾ãããªã¯ã¨ã¹ããåãä»ãããããã®ã¨ã³ã¸ã³ã«ãã¼ã¿ãæå ¥ããã¨ã並åã«ãã¼ã¿å¤æãå®è¡ããæå¾ã«ã¬ã¹ãã³ã¹ãè¿ããã®ã¨ãã¾ãããã
ãªã¯ã¨ã¹ããåãä»ãããµã¼ãèªä½ã®å®è£
ã¯ä»åã®ãã¼ãã§ã¯ãªãã®ã§ç¡è¦ãããã¨ã«ãã¦ãã¨ãããã read-ch
ãèªã¿è¾¼ãã¨ãªã¯ã¨ã¹ããèªã¿è¾¼ãã¦ã write-ch
ã«æ¸ãè¾¼ãã¨ã¬ã¹ãã³ã¹ãè¿ããã¨ãããã¨ã«ãã¦ããã¾ãããã
ç¨æãããã®ã¯
- ãªã¯ã¨ã¹ãããã¤ãã©ã¤ã³ã«æµãè¾¼ãé¢æ°ï¼å§ç«¯å¦çï¼
- ãã¼ã¿ãå¤æããé¢æ°
- ã¬ã¹ãã³ã¹ãåºåããé¢æ°ï¼çµç«¯å¦çï¼
ããã ãã§ãããã¤ãã©ã¤ã³ã«ã¯å¿ ãå§ã¾ãã¨çµãããããã®ã§ãã¯ãã¾ãã«ã¯ä½ãããã®å§ç«¯å¦çããçµããã«ã¯ä½ãããã®çµç«¯é¢æ°ãããã¯ãã§ãä»åã®å ´åã®å§ç«¯å¦çã¯ãªã¯ã¨ã¹ããã¨ã³ã¸ã³ã«æ¸¡ãï¼ãã¤ãã©ã¤ã³ã«æµãï¼ãããªä½ãã§ãçµç«¯å¦çã¯ããã¬ã¹ãã³ã¹ãè¿ããã¨ãããã¨ã«ãªãã¾ããçµç«¯å¦çã¯ãããã¦ãã®å ´åã¯ããã¤ãã©ã¤ã³ã®æå¾ã®åºåãèªã¿åã£ã¦ããããï¼ãã¡ã¤ã«ã¨ããããã¯ã¼ã¯ã¨ãï¼ã©ããã«æ¸ãåºããã¨ããå¦çãè¡ããããªãgoãããã¯ã§ãã
ã¨ã³ã¸ã³ãä½ã
ãã¼ã¿ãå¤æããé¢æ°ã®å
容èªä½ã¯ä»åã¯éè¦ã§ã¯ãªãã®ã§ãã¨ãããã great-convert-xf
ã¨ãããããtransduceré¢æ°ããããã¨ã«ãã¾ããå¤åããããé¢æ°ãtransduceråãã¦ããã«compã使ã£ã¦åæãããããªãã®ã§ããããã使ã£ã¦ä¸¦åãã¤ãã©ã¤ã³ãä½ãã¾ãã
(require '[clojure.core.async :refer [chan pipeline]]) (def in-ch (chan)) (def out-ch (chan)) (def engine (pipeline 8 out-ch great-convert-xf in-ch))
ãªãã¨ä»åã¯ããã§ã¨ã³ã¸ã³ã¯å®æã§ãããengineã¨åä»ãããã®pipelineã¯ãin-chã«ãã¼ã¿ãæ¸ãè¾¼ã¾ããã¨ãgreat-converté¢æ°ãæ大8並åã§å®è¡ãã¦ããã¾ãï¼
ãã¡ããä»åã¯ä¸çªå¤§å¤ãª great-convert-xf
transducerã®å®è£
ãçç¥ãã¦ãããããããã§æ¸ãã§ããããã§ãããé¢æ°ããåå¨ããã°ãããã並åã¨ã³ã¸ã³åããã®ã¯ç°¡åã ã¨ãããã¨ããããã¨æãã¾ãã
å§ç«¯å¦ç
å§ç«¯å¦çãè¡ãã¹ãã¯ããããã¯ã¼ã¯ããã®ãªã¯ã¨ã¹ããå ¥ã£ã¦ããread-chãèªã¿åã£ã¦ãã¨ã³ã¸ã³ã®å ¥åã§ããin-chã«æµãè¾¼ãã ãã§ãã ãããã¯ã¼ã¯ããæ¥ããã¼ã¿ãããã®ã¾ã¾ã¨ã³ã¸ã³ã«æµãè¾¼ãããã¼ã¿æ§é ã®å ´åã¯ãã¨ã¦ãç°¡åã§ãã
(pipe read-ch in-ch false)
read-chã¨in-chãç´æ¥ã¤ãªãã¡ããã°ããã®ã§ãï¼ æå¾ã®å¼æ°falseã¯ãread-chãcloseãããå ´åã«æ¥ç¶å ãã£ãã«(in-ch)ãcloseããªããã¨ããæå³ã§ãããããå¿ããã¨ãä¸åã®ãªã¯ã¨ã¹ããå¦çããã¨ããã§ã¨ã³ã¸ã³ã®å ¥åãã£ãã«ãéãããã¦ãã¾ãã®ã§æ³¨æã§ãã
ã§ããå®éã«ã¯ããããã¯ã¼ã¯ããæ¥ããã¼ã¿ã¯ããã¤ããªã ã£ãããJSONæååã ã£ããããã®ã§ãã¨ã³ã¸ã³ãå¦çã§ãããã¼ã¿å½¢å¼ã«å¤ãã¦ããæµãè¾¼ããã¨ã«ãªãã¾ããgo-loopé¢æ°ã§å®ç¾ã§ãã¾ãã
(require '[clojure.core.async :refer [go-loop <! >!]]) (go-loop [] (when-let [req (<! read-ch)] (when (>! in-ch {:data (convert-request req) :write-ch write-ch}) (recur))))
ãã®go-loopã¯ãread-chãéããããï¼èªã¿åãçµæãnilã«ãªãï¼ããã¨ã³ã¸ã³ã®å ¥åãã£ãã«ãéããããï¼æ¸ãè¾¼ã¿ã§falseãè¿ãï¼ãããã¾ã§ãç¡éã«ã«ã¼ããã¾ãããã¤ã³ãã¯ãããã¯goãããã¯ãªã®ã§ãç¡é§ã«ã«ã¼ããã¦CPUãæ¶è²»ããªããã¨ã§ãããã£ãã«ããèªã¿åãããã¼ã¿ãããã°ãcore.asyncã«ãã£ã¦goãããã¯ã«å¦çã¹ã¬ããã«å²ãå½ã¦ããã¾ããããã¦æ¬¡ã®ãã£ãã«å ¥åºåæã«åã³ä¼æ¢ç¶æ ã«æ»ããã»ãã®goãããã¯ã«å¦çãåãã¾ããCPUãå¹ççã«å©ç¨ã§ããã®ã§ãã
ã¨ã³ã¸ã³ã«æµãè¾¼ããã¼ã¿ã¯ãå å·¥æ¸ã¿ãã¼ã¿ã¨ãã¬ã¹ãã³ã¹ãåºåããããã®ãã£ãã«ã®ãäºã¤ã®è¦ç´ ã®å ¥ã£ããããã§ãã
çµç«¯å¦çãä½ã
çµç«¯å¦çã¯å§ç«¯å¦çã®éã§ãã®ã§ãä¼¼ããããªå¦çã¨ãªãã¾ããã¨ã³ã¸ã³ããã¯ãã¨ã³ã¸ã³ã«æµãè¾¼ãã ã®ã¨åãå½¢å¼ã®ãããã¨ãã¦ãã¼ã¿ãåºåããããã®ã¨ãã¾ãã
(go-loop [] (when-let [{:keys [data write-ch]} (<! out-ch)] (>! write-ch data) (recur)))
ãã®çµç«¯å¦çã¯ãã¨ã³ã¸ã³ã®åºåãã£ãã«(out-ch)ãéããããã¾ã§ãç¡éã«ã«ã¼ããã¾ããå§ç«¯å¦çã¨åãããã«ã¼ãã«ãã£ã¦CPUãç¡é§ã«æ¶è²»ãããã¨ã¯ããã¾ããã
ããã§ãå§ç«¯å¦çâã¨ã³ã¸ã³âçµç«¯å¦çã¨ãããµã¤ã¯ã«ãã§ããããã¾ãããã¨ã³ã¸ã³ã¯core.asyncã®pipelineã使ããã¨ã§ä¸¦åã«å®è¡ããã¾ããã¨ã³ã¸ã³ãå¦çããé¢æ°ãã²ã¨ã¤ã ãã®ãã¨ã¦ãã·ã³ãã«ãªä¾ã§ãããcore.asyncã§ä¸¦åå¦çãµã¼ãããã°ã©ã ãä½ãã¨ãã®åºç¤ãã¡ããã¨å ¥ã£ã¦ãã¾ãã
pipelineãæ¡å¼µãã
ãã¤ã³ãã¯ãä¸åº¦ãã®æ§é ãã§ãã¦ãã¾ãã°ãã¨ã³ã¸ã³ã®é¨åã¯å®¹æã«å¤æ´ã§ããã¨ãããã¨ã§ããããã°ã©ã ã®å¤§æ ã¨ãã¦ãå§ç«¯âã¨ã³ã¸ã³âçµç«¯ãã¨ããæ§é ããã§ãã¦ããã°ããã¦ãã¨ã³ã¸ã³ã®é¨åããã£ã¨æ¡å¼µãã¦ãããã®æ§é ããå¤ãããªããã°åé¡ãªãã®ã§ãã
ãããããã ããã¨ã³ã¸ã³é¨åã®ããã°ã©ã ãé£ãããã§ãã£ã¦ããããæ¸ãã¦ãªãã®ã ãããã¨ããã®ã¯ãã®éãã§ããããããã¤ã³ãã¯ãããã°ã©ã ã®æ¡å¼µããcore.asyncã®ãã¤ãã©ã¤ã³ã®æ¡å¼µã¨ããå½¢ã§è¡ããã¨ããã¨ããã§ãã
é¢æ°ã¯å¯çµåã§ããï¼
Clojureã®ä½è ã§ããRich Hickeyããcore.asyncã«ã¤ãã¦èª¬æãã ãã¬ã¼ã³ãã¼ã·ã§ã³ ãããã¾ãããã®åç»ãã¿ãã¨ãcore.asyncã¯ãã goã«ã¼ãã³ãclojureã§å®ç¾ãããã®ã¨ããã®ã¨ã¯å¥ã®è¦³ç¹ããããã¨ããããã¾ããRichã¯ããã®ãã¬ã¼ã³ãã¼ã·ã§ã³ã®ä¸ã§ãï¼ãªãã¸ã§ã¯ãæåã®å©ç¹ã¨æ¬ ç¹ã¨å¯¾æ¯ãã¤ã¤ï¼é¢æ°ããã°ã©ã ã®å©ç¹ã¨æ¬ ç¹ãç°¡åã«è©±ãã¦ãã¾ããããã§Richãé¢æ°ã®å©ç¹ã¨ãã¦ããã®ã¯ãé¢æ°ã¯ãã¸ãã¯ãæ½è±¡åã§ããã¨ãããã¨ï¼ä¸æ¹ããªãã¸ã§ã¯ãã¯ãã¸ãã¯ã¨ããããã¯ããèªä½ããã·ã³ã§ãããã¨ãã¦ã¾ãï¼ãæ¬ ç¹ã¯ãé¢æ°ã¯ã©ããã¦ãå¯çµåã«ãªããã¡ã ãã¨ãããã¨ã§ãã
é¢æ°å¼ã³åºãã®é£éãå解ãã¦ãéä¸ã«åå²ï¼ifæã¨ãï¼ãæã¿è¾¼ãã®ã¯ãçµæ§éª¨ã®æããä½æ¥ã§ãããã¸ãã¯ãå¤ããããäºå®ä¸æ¤è¨¼ãããç´ãã§ãã
ããã§ãRichã¯ãé¢æ°ï¼ãã¼ã¿ã®å ¥åã¨åºåãããï¼ãããã¥ã¼ï¼ãã¼ã¿ãå ¥åãã¦åºåããã¨ããæ©è½ãããªãåç´ãªæ§é ï¼ã¨çµã¿åããããã¨ã§ãé¢æ°å士ã®å¯çµåãã»ã©ããã¨ãã§ãããã¨è¨ã£ã¦ãã¾ãã
ãããããRichã¯ãä»®ã«core.asyncã®éåææ©è½ãä¸å使ããã«ããã¥ã¼ï¼ãã£ãã«ï¼ãä»ãã¦é¢æ°ã¨é¢æ°ãçµã³ã¤ããã ãã§ããå©ç¹ã¯ããã¨è¨ã£ã¦ãã¾ãã
ãã¼ã¿å¦çã¨ã³ã¸ã³ã¯ãè¤éãªåå²ãå«ãã 巨大ãªé¢æ°ã§ããããããpipelineã使ã£ã¦ã容æã«åæ¥ç¶å¯è½ãªé¢æ°ã®éã¾ãã¨ãã¦ä½ããã®ã§ããä½ãããpipelineã¨ããã®ã¯ããã£ãã«ã¨ããåã®ãã¥ã¼ãä»ãã¦é¢æ°å士ãæ¥ç¶ããããã®ãã®ã ããã§ãã
ãã¤ãã©ã¤ã³ã«åå²ãçµã¿è¾¼ã
ãã¤ãã©ã¤ã³ã®å ¥åºåã¯ãã£ãã«ãªã®ã§ãããããã®ãã¤ãã©ã¤ã³ãç¨æãã¦ããããã¤ãã©ã¤ã³ã®åºåãã£ãã«ãå¥ã®ãã¤ãã©ã¤ã³ã®å ¥åãã£ãã«ã¨ãã¦æå®ããã°ï¼ãããã¯ãpipeé¢æ°ã§äºãã®å ¥åã¨åºåãã£ãã«å士ãã¤ãªããã°ï¼ããã¤ãã©ã¤ã³ãã¤ãªãåããã巨大ãªãã¤ãã©ã¤ã³ãä½ããã¨ãã§ãã¾ãã
ããã«ãcore.asyncã«ã¯ããã£ãã«ã«å ¥ã£ã¦ãããã¼ã¿ããå¥ã®è¤æ°ã®ãã£ãã«ã«ãæ¡ä»¶ã«ãã£ã¦æ¯ãåããé¢æ°ãç¨æããã¦ãã¾ããpubã¨subã§ãã
ããåºåç¨ãã£ãã«ã«pubé¢æ°ãé©ç¨ããã¨ãpublicationã¨ããç¹æ®ãªãªãã¸ã§ã¯ããä½ãã¾ããpublicationã¯ããã£ãã«ã«å ¥ã£ã¦ãããã¼ã¿ã®ç¨®å¥ãèå¥ãããã¨ãã§ãã¾ããããã«ãå¥ã®ãã£ãã«ãsubé¢æ°ã使ã£ã¦publicationã«ç»é²ãããã¨ãã§ãã¾ãããã®ç»é²æã«ããã®ãã£ãã«ã«ã¯ããã¼ã¿ã®ç¨®å¥ãAã®ãã¼ã¿ã ããæµãã¦ãã ãããã¨ããæå®ãã§ããã®ã§ãã
ãã¨ãã°ããã¤ãã©ã¤ã³ã«å ¥ã£ã¦ãããã¼ã¿ããæ°è¦ãã¼ã¿ããæ´æ°ãã¼ã¿ããåé¤ãã¼ã¿ãã«åããã¦ããã±ã¼ã¹ãèãã¦ã¿ã¾ãããããã®ä¸ç¨®é¡ãããããè¡ãã¹ãä½æ¥ã¯å¾®å¦ã«ç°ãªãã¾ããããããã¨ããpub/subã使ã£ã¦ããã£ãã«ãä¸ã¤ã«åå²ããããã¨ãã§ãã¾ãã
(let [publication (pub ch :type)] (sub publication :new new-data-ch) (sub publication :update update-data-ch) (sub publication :delete delete-data-ch))
ã¤ã¡ã¼ã¸ã¨ãã¦ã¯ãããªæãã§ãï¼éãªææ¸ãå³ã§ãã¿ã¾ããï¼
ããã§ãããã¨ãã¨ã¯æ°è¦ã¨åé¤ãããªãã¨èãã¦ããâãæ¥ã«ããå®ã¯æ´æ°ãã¼ã¿ãããã¾ããâ¦ãã¨ãè¨ããã¦ãã¾ã£ããã¨ããã±ã¼ã¹ãèãã¦ã¿ã¾ãã
core.asyncã§ã¯ããã¨ãã¨ã®ãæ°è¦ãç¨ãã¤ãã©ã¤ã³ã¨ããåé¤ãç¨ãã¤ãã©ã¤ã³ã«å½±é¿ãä¸ããã«ããæ´æ°ãç¨ãã¤ãã©ã¤ã³ã追å ãããã¨ãã§ãã¾ããåã«ããæ´æ°ãç¨ãã¤ãã©ã¤ã³ãä½ã£ã¦ããã®å ¥åãã£ãã«ããåå²publicationã«è¿½å ããã°ããã®ã§ãã
core.asyncã¯ååãããéåæå¦çã§æ³¨ç®ããã¾ããããå¯çµåããé¢æ°å¼ã³åºããççµåã«ãããã¨ããç®çãå ¥ã£ã¦ããã®ã§ããæ¢åã®é¢æ°ï¼pipelineã«transducerã¨ãã¦çµã¿è¾¼ã¾ãã¦ããï¼ã¯å¤æ´ãããªãã®ã§ããã®é¨åã®åãã¹ãã¯ä¸è¦ã§ããæ°ããé¢æ°ãç¨æãããã¹ãããtransduceråããpipelineãæ§ç¯ããããã¨ã¯ãã£ãã«ã¨ãã£ãã«ãã©ãæ¥ç¶ããããã¨ããã ãã®åé¡ã§ãããã£ãã«å士ã®æ¥ç¶ã工夫ãããã¨ã§ãé¢æ°ã®åå²ãå®è¡é åºãå¶å¾¡ã§ããããã§ããããããåé¢æ°ã¯å¹ççã«ä¸¦åå®è¡ãããã®ã§ãã
ãã¤ãã¹ãä½ã
ç°å¸¸ãçºçããã±ã¼ã¹ãªã©ãæ£å¸¸ãªããã°ã©ã ã®æµããç¡è¦ãã¦ãå¥ã®å¦çã«ã¸ã£ã³ããããã¨ããã±ã¼ã¹ã¯çµæ§ããã¾ããå®éãããã°ã©ãã³ã°è¨èªã®ä¾å¤ã¨ãã£ããã¨ããã®ã¯ãæ£å¸¸ãªããã°ã©ã ãæµããç¡è¦ãã¦ä¾å¤å¦çã¸ã¨ã¸ã£ã³ãããå¦çãªè¨³ã§ãé¢æ°ãã¤ãªãã¦ããã°ã©ã ã®æµããä½ããã¤ãã©ã¤ã³ã§ãã£ã¦ãããã¯ãåæ§ã®ãã¨ãå¿ è¦ã«ãªãã±ã¼ã¹ã¯ããå¾ã¾ãã
core.asyncã§ã¯ãpipelineã§å®è¡ãããé¢æ°ã¯ä¸¦åã«å®è¡ãããï¼å¥ã¹ã¬ããã§åãï¼ã®ã§ãåç´ã«ä¾å¤å¦çãè¡ããã¨ãã§ãã¾ããããã®ä»£ããã«ãexception-handlerã¨å¼ã°ããä¾å¤å¦çç¨ã®é¢æ°ã使ããã¨ãã§ãã¾ããexception-handlerã¯ãå¼æ°ã¨ãã¦ä¾å¤ä¸ã¤ãåãåãé¢æ°ã§ããã°ããªãã§ãæ§ãã¾ããã
pipelineã«è¨å®ããtransducerå ã§ã¨ã©ã¼ãçºçããã¨ãï¼ããã°ï¼exception-handleré¢æ°ãå¼ã°ãã¾ããexception-handlerã¯ä½ããã¦ãããã§ãããexception-handleré¢æ°ã®çµæããtransducerã®å®è¡çµæã«ãªãã¾ãã
;; exception-handlerãè¨å®ããpipelineãä½ãä¾ (let [ex-handler (fn [ex data] (handle-error ex) nil)] (pipeline 8 out-ch (map my-greate-fn) in-ch false ex-handler))
ããã§ã¯ä½¿ãã¾ããããå®ã¯ããã£ãã«ãä½æãã chan é¢æ°ã«ããexception-handlerã渡ããã¨ãã§ãã¾ãããã£ãã«ã«transducerãã»ããããæã«ãtransducerå ã§çºçããã¨ã©ã¼ãå¦çããããã«ä½¿ãã¾ãã
é常ãã¨ã©ã¼ã¨ãªã£ããã¼ã¿ã¯ãã¤ãã©ã¤ã³ã®å ã«é²ãããããã¾ãããããããã¨ãã¯ãexception-handleré¢æ°ã®æ»ãå¤ãnilã«ãã¾ããcore.asyncã®ãã£ãã«ã«ã¯nilãå¤ã¨ãã¦æµããã¨ãã§ããªãä»æ§ã§ãã®ã§ãexception-handlerãnilãè¿ãã¨ããã®ãã¼ã¿ã¯ãã¤ãã©ã¤ã³ã®å ã«ã¯æµãã¾ããã 代ããã«ãexception-handlerã«å¥ã®åºåç¨ãã£ãã«ã渡ãã¦ãããããã«ãã¼ã¿ãæµãã®ã§ãããã®ãã£ãã«ã®å ã«ã¯ãä¾å¤ãå¦çããããã®pipelineãè¨å®ãã¦ããã¾ãã
;; ãã¤ãã¹ç¨channelã¨ãã¦bypass-chããã§ã«ãããã®ã¨ãã ;; ãã®ex-handleré¢æ°ã¯ãåãåã£ãä¾å¤ãbypath-chã«è»¢éããã (defn ex-handler [ex] (go (>! bypass-ch ex)) nil)
ãã®ãããªexception-handlerããã¹ã¦ã®pipelineã«è¨å®ãã¦ããã°ãä¾å¤ã¯ãã¹ã¦ãbypass-chãçµç±ãã¦ãä¾å¤å¦çç¨pipelineã¸ã¨æµãã¦ãããã¨ã«ãªãã¾ããã¨ã©ã¼ã®ããã®ãã¤ãã¹ãä½ã£ãããã§ãã
core.asyncã«ã¯pub/subã«ããåå²ã¨ã¯å¥ã«ãmergeã«ããé£çµæ©è½ãããã¾ãããããã¤ãã¹ã«æµãã¦ããã¦å¦çããå¾ãæçµçã«ã¯åãçµç«¯å¦çã«æ¥ç¶ãããã¨ãã£ããã¨ãå¯è½ã§ãã
;; çµç«¯å¦çã«ã¤ãªãã last-ch ã¨ãããã£ãã«ãããã¨ãã ;; ãã¹ã¦ã®ãã£ãã«ãé£çµããall-data-chãä½ãããããlast-chã« ;; é£çµãã (let [all-data-ch (merge [new-ch update-ch delete-ch bypass-ch])] (pipe all-data-ch last-ch))
ä¾å¤ãå¦çããpipelineã¾ã§å«ããã¨ããã®ã·ã¹ãã ã®å ¨ä½åã¯ãããªæãã«ãªãã¾ãã
ãã®æè»æ§ããcore.asyncã®å¼·ã¿ã§ããé¢æ°ãtransducerã¨ãã¦pipelineã«çµã¿è¾¼ããã¨ã§ä¸¦ååããããã«ããã£ãã«ã¨ãããã¥ã¼ãä»ãã¦ãpipelineãæè»ã«çµåãã¦ãã·ã¹ãã å ¨ä½ãä½ãã®ã§ããClojureèªèº«ã®ããã¼ã¿ã¯åºæ¬çã«ä¸å¤ã§ãããã¨ããæ§è³ªããéåæå¦çã®å®å ¨æ§ãé«ãã¦ããã¦ãã¾ããå ¥åã¨åºåãããªããé¢æ°ãã¨ãåããå ¥åã¨åºåãããªãããã¥ã¼ãã使ããã¨ã§ãã¼ã¿ã®æµããä½ããããã«ããã«ããã®transducerã¨ããå¤æå¦çãçµã¿åãããã¨ãpipelineã¨ãã並ååé¢æ°ãä½ãä¸ããããã®ã§ããããããèªç±ã«çµã¿æ¿ããããããã§ãï¼
ã¾ã¨ã
ã¡ãã£ã¨ããä¾ã§ããããã¤ãã©ã¤ã³ãã¤ãªãã¦ãåå²ãä¼´ãããã°ã©ã ãä½ãä¸ããã¤ã¡ã¼ã¸ãã§ããã§ããããã
- goã¨channelã®äºã¤ã§ãéåæãããã¯éã®ãã¼ã¿ã®ããã¨ããå®ç¾ãã
- transducerã«ããå¤æå¦çãæ½è±¡åããåæå¯è½ã«ãã
- channelã¨transducerãçµã¿åããã¦ãtransducerã並åå®è¡ããpipelineãä½ã
- pipelineå士ããchannelãä»ãã¦åå²ãããçµåããããã¦ã¤ãªãåããã
- ãã¼ã¿ããã¤ãã©ã¤ã³ãçµç«¯ã«åãã£ã¦æµãã¦ããã¨ãããã¹ã¦ã®å¦çã¯èªåçã«ä¸¦åã«å®è¡ãããï¼
goï¼éåæãããã¯ï¼, channelï¼ãã¥ã¼ï¼, transducerï¼å¤æå¦çï¼, pipelineï¼å¦çã®ä¸¦åå®è¡ï¼ã¨ããï¼ã¤ã®æ¦å¿µãçµã¿åããããã¨ã§ã並åããã°ã©ã ãã§ãã¦ãã¾ãã¾ããï¼
ãããããä¸ã¤ã®ä»äºã ããè¡ããããªç©ããçµã¿åããã¦è¤éãªå¦çãä½ãä¸ããããããããããæ··ãè¾¼ã¾ãªãï¼ã³ã³ãã¬ã¯ããããªãï¼ã¨ããã®ã¯ãClojureã®ç®æããSimple Made Easyãã®ä¸ç観ã¨ãåã£ã¦ãã¾ãããcore.asyncã¯ãClojureãããå½¢ã§ã並åããã°ã©ã ã®ä½ãæ¹ãå¤ããä»çµã¿ãå®ç¾ãããClojureã®ãã©ã¼ã©ã¤ãã©ãªã®ä¸ã¤ã§ãã
core.asyncã«ã¯ãä»ã«ãããã£ãã«ã«å ¥ã£ã¦ãããã¼ã¿ãè¤æ°ã®ãã£ãã«ã«ï¼åããã¼ã¿ãï¼è»¢éãã multiple ããè¤æ°ã®ãã£ãã«ããã¼ã¸ãã¤ã¤ããã£ãã«åä½ã§æµããä¸æçã«åæ¢ã§ãã mixãè¤æ°ã®ãã£ãã«ããæåã«ãã¼ã¿ãå ¥ã£ã¦ãããã®ãé¸æã§ãã alt! ãªã©ããã£ãã«ãã¤ãªãåãããããã®é¢æ°ãç¨æããã¦ãã¾ãããããã使ãã°ãæè»ã«ãã£ãã«ã®æ¥ç¶ãåçã«åãæ¿ãããªã©ã®å¦çãã§ãã¾ãããã£ãã«ã®çµã¿åããã¨ä¸¦ååãããcore.asyncã®å¼·ãã§ããããã ã®goãããã¯ã§ã¯ãªãã¨ãããã¨ãåããã§ããããã
宣ä¼
clj-ebisu ã§ãcore.asyncã使ã£ãæã®ãããããããªãã©ãã«ã¨åé¿æ¹æ³ã«ã¤ãã¦ãã¡ãã£ã¨ãããã¬ã¼ã³ãã¼ã·ã§ã³ããããã¨ã«ãªãã¾ããããã¦ãã
Clojureã¨ãSimple Made Easyã
ããã°ã©ãã³ã°è¨èªã¨ããã®ã¯ããã®ä½è ãçæ³ã¨ããä¸çã«åãããã«ãã¶ã¤ã³ããã¦ãããã®ã ããï¼ã¿ããªä¿¡ããªãããã ãã©ãJavaã§ãããããªã®ã§ããï¼ãClojureã®ãã¨ãç解ããã«ã¯ãä½è ã§ããRich Hickeyã®ããã°ã©ãã³ã°è¦³ãç¥ãã®ãæã£åãæ©ãã§ãããã
Rich Hickeyã¯ãã¾ãã¾ãªãã¬ã¼ã³ãã¼ã·ã§ã³ãçºè¡¨ãã¦ãã¦ãå¤ãã¯ãããã§è¦ããã¾ãã示åã«å¯ãã§ç®èãå¹ãã¦ã¦ãããããã®ã§ããã¡ã³ãå¤ãã¦ãå½¼ã®ç¬ç¹ã®é«ªåï¼å¾å¹´ã®ããã¯ææ風ï¼ãããããRich Hickey’s Greatest Hitsãã¨ããããã°è¨äºããã£ãããã¾ãï¼ãã¬ã¼ã³ãã¼ã·ã§ã³åç»ã¸ã®ãªã³ã¯éã§ãï¼ã
ãã ãå½¼ã®ãã¬ã¼ã³ãã¼ã·ã§ã³ã¯é£è§£ãªè±èªãåºã¦ãã¦ãç§ã®ãããªãªã¹ãã³ã°è¦æ人éã«ã¯é³å£°ã ãã§è´ãã®ã¯é£ããã§ãããããã人ã¯å½å¤ã§ãå¤ãããããæå¿ãæ¸ãããã(transcript)ãå ¬éãã¦ããããã¾ããã§ãã®ã§ãç§ã¯å½¼ã®ãã¬ã¼ã³ããè´ããã®ã§ã¯ãªããèªãã ããã§ãããã åç»ã§ãªã«ãèµ·ãã¦ãã®ãããããªãã¨æç« ã ãã§ã¯æå³ãåãããªãã¨ããï¼ç¹ã«ç¾å ´ã®ã¸ã§ã¼ã¯ã¨ãï¼ãããã®ã§ãåç»ãç®ãéããã¨ããããããã¾ãã
å½¼ã®æåãªãã¬ã¼ã³ãã¼ã·ã§ã³ã«ãSimple Made Easyãã¨ãããã®ãããã¾ããå ·ä½çãªã³ã¼ãã£ã³ã°ã«ã¤ãã¦ã®ãã¬ã¼ã³ã¨ããããã¯ãã·ã³ãã«ãã¨ã¯ä½ãï¼ãèªã£ããã®ã§ããå½¼ã®ãã¬ã¼ã³ãã¼ã·ã§ã³ã«ã¯ããããããå®éã®ã³ã¼ãã£ã³ã°ã§ã¯ãªããããã°ã©ãã³ã°ã®åå°ã¨ãªãèãæ¹ãæ 度ã«ã¤ãã¦ã®ãã®ããã£ã¦ããªããªãé¢ç½ãã®ã§ããå½¼ã®å²å¦ãèªã£ããã®ã¨ãè¨ãããã®èãæ¹ã¯ãå½ç¶Clojureã«ãåæ ããã¦ããã®ã ã¨æãã¾ãã
Simple Made Easyã®å 容ã¯ãä¸åº¦ãæ ªå¼ä¼ç¤¾ã¦ã¼ã¶ãã¼ã¹ã§ãã¬ã¼ã³ãã¼ã·ã§ã³ãããæ©ä¼ããã£ãã¨ãã«è³æã«ã¾ã¨ãããã¨ãããã¾ããä»åã¯ããã®è³æããã¨ã«ãã©ãããå 容ã®ãã¬ã¼ã³ãã¼ã·ã§ã³ã ã£ãã®ãç´¹ä»ãããã¨æãã¾ãããã ãããã¯ã翻訳ãã§ã¯ãªãã¦ç§ã®ç解ããå 容ã®ç´¹ä»ã§ãããã¨ã«æ³¨æãã¦ãã ãããRich Hickeyãå ·ä½çã«ã©ãè¨ã£ã¦ããã®ãã¯ãå½¼ã®ãã¬ã¼ã³ãç´æ¥è¦ã¦ãã ããã
ã·ã³ãã«ã¨ç°¡åã¯éã
ä¸ã®ä¸ã§ã·ã³ãã«ã ã¨è¨ããããã®ã®ä¸ã«ã¯ãå®éã«ã¯ã·ã³ãã«ã§ã¯ãªããåã«ãç°¡åãã§ãããã®ãããããæ··ãã£ã¦ã¾ãããã®ãã¼ã«ã使ãã°ã³ãã³ãä¸çºã§ãµã¼ããæ§ç¯ã§ãã¦ãããã·ã³ãã«ã ï¼ãªã©ãªã©ããã¡ããç°¡åãªãã¨ã¯ããèªä½ä¾¡å¤ã®ãããã¨ãªã®ã ãããã©ãï¼å°ãªãã¨ããã é£ããããã¯ï¼ãã·ã³ãã«ã¨ç°¡åãæ··åããã®ã¯è¯ããªããããããæ··åãããããä¸ã®ä¸ã«ã¯ãï¼ä½¿ãã®ã¯ï¼ç°¡åã ãã©ççã«è¤éãªãã®ãç¾ãã¦ããããã§ãã
ã·ã³ãã«ã¨ç°¡åã¯éãã
ç°¡åã«ä½¿ãããã©ãããã®ãããè¤éãªãã®ã¨ããã®ã¯ãããããããã¾ãããæ°ã«å ¥ãã®IDEã¯ã©ãã§ãããJSãªãã°ãwebpackã¯ã©ãã§ããããï¼ Spring Bootã使ãã°Javaã§ç°¡åã«APIãµã¼ããä½ãã¾ãããSpring Bootã¯ã·ã³ãã«ã§ããããï¼
ã·ã³ãã«ã¨ç°¡åã¨ã®éããæ確ã«ããããã«ãRichã¯ãããã§ãããç°¡åãã¨ã¯ã©ããããã®ããç´è§£ãã¦ããã¾ããå½¼ãæããã人ããç°¡åããªãã®ã«æ±ãã¦ããã¤ã¡ã¼ã¸ã¯ã次ã®ãããªãã®ã§ãã
- æ £ãã¦ãã
- ããã«ä½¿ãå§ãããã
- ä¼¼ããããªãã®ããã§ã«ç¥ã£ã¦ã¦ã身è¿ã
- ä»ã®èªåã®è½åã®ç¯çå ã
ãç°¡åãã¨ããã®ã¯ãã ãããããã»ãã¨æ¯ã¹ã¦ãã¨ããæ¯è¼ãå ¥ãã®ã§ããæ £ãã¦ããã«ããã身è¿ã§ããã«ããããä»ã®èªåã®ç¥ã£ã¦ãä½ãã¨æ¯ã¹ã¦ãã¨ããæ¯è¼ãªã®ã§ãã
ã§ãããããã¿ãªããç°¡åããªãã®ã ããé¸æãã¦ãããã誰ãæ°ãããã¨ãå§ãããã¨ã¯ã§ãã¾ãããæ°ãããã¨ã¯ã身è¿ã§ããªãããæ £ãã¦ãããªãããããã¦ãã¯ä»ã®è½åã®ç¯çå¤ã ããã
ã·ã³ãã«ã¨ã¯
ä¸æ¹ã§ã·ã³ãã«ã¨ããã¨ãã±ã£ã¨ããããããããªãã¦ã²ã¨ã¤ã ããã ã¨ãããã®ãã¼ã«ã¯æ©è½ãå°ãªãã¦ã·ã³ãã«ã ãã¨ãããã®ããã°ã©ã ã¯æ§æè¦ç´ ãå°ãªãã¦ã·ã³ãã«ã ãã¨ãããªãã ãï¼ãã®ãªãæ©è½ãªãã®ï¼æ°ãå°ãªãæ¹ãã·ã³ãã«ã ãã¨ãã話ã«ãªããã¡ã§ããã¨ããããå®éã«ã¯ããã®ãã¨ãã·ã³ãã«ã«ããã¨ãè¦ç´ ã®æ°ã¯å¤ããªã£ã¦ããã¾ãã
Clojureã¯LISPç³»ã®è¨èªã§ããããã¨ãã°ãä¼çµ±çãªLISPã«ãããæ¬å¼§ã¯ãã·ã³ãã«ã§ãããããLISPã¯æ¬å¼§ã ãã§æ§æããã¦ãããããã·ã³ãã«ãªã®ã§ãããããRichã¯LISPã®æ¬å¼§ã¯ã·ã³ãã«ã§ã¯ãªãã¨ããã¾ãããªããªãLISPã®æ¬å¼§ã«ã¯ãè¤æ°ã®æå³ãããããã§ãã
LISPã§ã¯ãæ¬å¼§ã¯ãé¢æ°å¼ã³åºããã¨ããã®ãã¨ãã°ã«ã¼ãã³ã°ãããã¨ããäºã¤ã®æå³ãããã¾ããletå¼ã§ãã¢ã表ç¾ããããã®ã¿ãã«ã¨ãã¦ã®æ¬å¼§ãé¢æ°å¼ã³åºãã¨ãã¦ã®æ¬å¼§ãã§ãã
ã¤ã¾ãRichã®ãããã·ã³ãã«ãã¨ããã®ã¯ããã²ã¨ã¤ã®ãã®ã«ãè¤æ°ã®ãã¨ãããæ··ãè¾¼ã¾ãªããã¨ãããã¨ãªã®ã§ããLISPã®æ¬å¼§ã«ã¯ããµãã¤ã®äºæãæ··ãè¾¼ã¾ãã¦ããã®ã§ãã·ã³ãã«ã§ã¯ãªãã¨ã
ã·ã³ãã«ã¨ããã®ã¯ãã¾ã£ããã®ç³¸ã®ãããªãã®ã§ãã·ã³ãã«ã§ãªããã®ã¨ããã®ã¯ã糸ã絡ã¾ã£ã¦ããç¶æ ã§ãããé¢æ°å¼ã³åºããã¨ãã°ã«ã¼ãã³ã°ãã¨ããï¼æ¬ã®ã²ããã絡ã¿åã£ã¦ãæ¬å¼§ã¨ãªã£ã¦ããã®ããLISPã®æ¬å¼§ãªããã§ãã
ã ããããã·ã³ãã«ããã¨ããã®ã¯ããªãã¸ã§ã¯ããå°ããå®è£ ã§ãããã¨ãããªãã¸ã§ã¯ãã®è©³ç´°ãã¡ããã¨é è½ããã¦ãããã¨ããã話ã¨ãé¢ä¿ãããã¾ããããããã¯ã³ã¼ãã£ã³ã°ä¸ã§ã¯å¤§äºãªãã©ã¯ãã£ã¹ã§ãããã©ããã·ã³ãã«ãã©ãããã¨ãã話ã¨ã¯ãã¬ã¤ã¤ã¼ã®éã話ãªã®ã§ãã
ãã·ã³ãã«ã§ãªããªããã¨ããè¨èã決ããã
ä½ããå ·ä½çã«ã¤ããããã«ã¯ãååãã¤ããã®ã大äºã§ãããã·ã³ãã«ãã®ã»ãã«ã¯ååãã¤ãã¦ãã®ã§ããã®å¯¾ç¾©èªã®æ¹ã«ååãã»ããããã¡ãããåè©ãªããè¤é(complication)ãã¨ããã°ãããããããªãã§ããã§ãã§ããã°ãã·ã³ãã«ã§ãªããã®ãä½ããã¨ãã¦ãã¨ãã«ããããããã¯ââãã¦ãï¼ã·ã³ãã«ãããªããã¦ãï¼ããã¨è¨ããã°ãã·ã³ãã«ããä¿ã¤å½¹ã«ç«ã¡ããã§ãã
ããã§Richã¯ãã³ã³ãã¬ã¯ã(complect)ãã¨ããè±èªï¼èªåè©ï¼ãææ¡ãã¦ãã¾ããä½ããã³ã³ãã¬ã¯ããã¦ããããããã¤ã¯è¤éã«ãªãã¨ããããã§ããã³ã³ãã¬ã¯ãã¨ã¯ããªã«ãè¤æ°ã®ãã®ãã絡ã¿åããããåé¢ã§ããªããããã«çµã³ã¤ãã¦ãã¾ããã¨ã§ãã
ã³ã³ãã¬ã¯ããã¦ããã®ãæ¢ãã
è¨èãã§ããã¨ãããã¯ã³ã³ãã¬ã¯ããã¦ãããã¨ãããã¨ãã§ããããã«ãªãã¾ããããã°ã©ãã³ã°ã®ä¸çã«ã¯ã身è¿ã«ãã£ã¦ã³ã³ãã¬ã¯ããã¦ãããã®ãããããããã¾ããRichã¯Simple Made Easyã®ä¸ã§ãããããã®ãã³ã³ãã¬ã¯ããã¦ããä¾ãæãã¦ãã¾ãã
対象 | ä½ãã³ã³ãã¬ã¯ããã¦ããï¼ |
---|---|
ç¶æ (state) | ç¶æ ãå¤æ´ãããã¹ã¦ã®ãã® |
ãªãã¸ã§ã¯ã | ç¶æ ã¨ä¸ææ§ã¨å¤ |
ã¡ã½ãã | é¢æ°ã¨ç¶æ ã¨åå空é |
ç¶æ¿ | è¤æ°ã®å |
å¤æ° | ç¶æ ã¨æé |
ã¢ã¯ã¿ã¼ | ãä½ããã¨ã誰ãã |
switchæ/matchæ | ãä½ããã¨ã誰ããã¨ã®ãã¢ãè¤æ°åæ··ãã£ã¦ãã |
ç§ã¯ãã®ãªã¹ããè¦ãã¨ãã«ããªãã»ã©ãå¤æ°ã¨ããã®ã¯ãç¶æ ãã¨ãæéããã³ã³ãã¬ã¯ããã¦ãã®ãããªãã»ã©ï¼ã¨æãã¾ãããè¨èãå®ç¾©ããã¨ãããããªãã®ããç°¡åã«è¡¨ããããã«ãªããç解ãããããªãã¾ãã
ãã®ãã¨ã絡ã¿åãããªã
ã³ã³ãã¬ã¯ããã¦ãããã®ã¯ãè¤æ°ã®è¦ç´ ãããã¯ãåãé¢ããªãã¬ãã«ã§çµåãã¦ãã¾ã£ã¦ãã¾ãããã®ãåãé¢ããªããã¨ããäºå®ããè¤éãã®ç¾ããã¨ãããªã®ã§ãã
ã·ã³ãã«ãªãã®ã¯éãã¾ããã·ã³ãã«ãªãã®ã¯ãçµã¿åããããã¨ãã§ãã¾ããçµã¿åããããã¨ã§ãã³ã³ãã¬ã¯ããããã®ã¨åããã¨å®ç¾ã§ããã§ããããããã«ãç°¡åã«åé¢ã§ãã¾ããã ããåä½ãããããåé¢ãã¦ã«ã¹ã¿ãã¤ãºããããç°¡åã«ã§ãã¾ããã·ã³ãã«ãªãã®ã¯ã絡ã¿åã£ã¦ããªãããããç°¡åã«ãå¤æ´ã§ããã®ã§ãã
ã·ã³ãã«ãããç°¡åããä½ãã®ã§ãã
åãåãä½ãã«ãã¦ãâ¦
ãã®å³ãè¦ã¦ãã ãããããã¯å®éã«ãSimple Made Easyãã§ä½¿ãããåçã§ããå·¦å´ã¯æ¯ç³¸ç´°å·¥ã§ãæ¯ç³¸ãç·¨ãã ã縫ã£ãããã¦ä½ãåã§ããå³å´ã¯LEGOãããã¯ã§ä½ã£ãåã§ãã
æ¯ç³¸ç´°å·¥ã¯ããã¿ã¼ã³ãããã£ã¦ããå ´åãç¹ãæ©ã使ãã°ç°¡åã«ã§ãã¦é¢ç½ããããã§ãã馴æã¿ããªããªãããã©ã¢ãã«ã¨ãã«ç½®ãæãã¦èããã¨ããããããã¾ããã
æ¯ç³¸ã®åã¨ãLEGOãããã¯ã®åã¨ã§ã¯ããã¼ã«ãããåæã«ç«ã¦ã°ãã©ã¡ããç°¡åã«ä½ãããã®ã§ããã§ããä¸åº¦ä½ã£ãå¾ã«å¤æ´ãããã¨æã£ããå¥ã§ããããã¯éè¦ãªè¦ç¹ã§ãã次ã®æè¨ããã£ããèãã¦ã¿ã¦ãã ããã
ãã¹ãã¹ã¤ã¼ãã¨ãªãã¡ã¯ã¿ãªã³ã°ãã¼ã«ãããã°ãæ¯ç³¸ã®åãLEGOãããã¯ã®åãããç°¡åã«å¤æ´ã§ãããã§ããããï¼
å¼·åãªãªãã¡ã¯ã¿ãªã³ã°ãã¼ã«ã¯è¤éãªãã®ãå®å ¨ã«æ¹å¤ãããã¨ããµãã¼ããã¦ããã¾ãããããã¯ãLEGOãããã¯ã®ãããªæ§é ã®ããã°ã©ã ã¨æ¯ã¹ã¦ã©ããªãã§ããããï¼ãããã¯ãLEGOãããã¯ã®ãããªæ§é ã®ããã°ã©ã ã«ãªãã¡ã¯ã¿ãªã³ã°ãã¼ã«ã使ã£ãå ´åã¨æ¯ã¹ã¦ã©ããªãã§ããããï¼
ãã¹ãã¹ã¤ã¼ãã¨ãªãã¡ã¯ã¿ãªã³ã°ãã¼ã«ã¯ãããã¾ã§ããã¬ã¼ãã¬ã¼ã«ãã§ãã£ã¦ãã¬ã¼ãã¬ã¼ã«ãªãã§ãç°¡åã«å¤æ´ã§ããããã¨ãã¨ã·ã³ãã«ãªãã®ã®ä»£ç¨ã«ã¯ãªãå¾ãªããã§ãã
ãã·ã³ãã«ã§ãããã¨ãã¯ãããªãã®é¸æã
ç§ãã¡ã«ã¯ãè¤éæ§ã®æåãããã¾ããæ¾ã£ã¦ããã¨ããªãã§ããããããããããã¿ãããã³ã³ãã¬ã¯ããã¦ããã®ã§ãããããªä¸çã®ä¸ã§ã¯ãã·ã³ãã«ã¨ããã®ã¯ãæå³çã«é¸ã¶é¸æãªã®ã§ãã
ãããã·ã³ãã«ãªã·ã¹ãã ãæã¦ã¦ãªããªããã·ã³ãã«ã§ãããã¨ãé¸æããªãã£ãèªåã®ããã«ãªãã®ã§ãã
ãã¹ããåã·ã¹ãã ãå¼·åãªãªãã¡ã¯ã¿ãªã³ã°ã¯ãå®å ¨æ§ãé«ãã¦ãããã§ãããããããããããã¯å¼·åãªã¬ã¼ãã¬ã¼ã«ã§ã¯ãã£ã¦ããã·ã³ãã«ããä¿è¨¼ãã¦ã¯ããã¾ãããã·ã³ãã«ãã¨ããã®ãã¨ãã³ã³ãã¬ã¯ããã¦ãããã¨ã®åé¡ã解決ãã¦ã¯ããã¾ãããã ãããã·ã³ãã«ãã¨ããã®ã¯ã常ã«èªåã®é¸æãªãã ãã¨Richã¯ãã¬ã¼ã³ãã¼ã·ã§ã³ã§ä¸»å¼µãã¦ãã¾ãã
ç§ãã¡ã¯ããã«ã³ã³ãã¬ã¯ããã¦ãã¾ãã®ã§ã常ã«ãã³ã³ãã¬ã¯ãã¬ã¼ãã¼ããåããã¦ç£è¦ããªãã¡ããããªãã ãã³ã³ãã¬ã¯ããã¨ããã¯ã¼ããå®ç¾©ãããã¨èªä½ãããã®ã¬ã¼ãã¼ã¨ãã¦å½¹ã«ç«ã¤ã¯ãã§ãã
ããã°ã©ã ãã·ã³ãã«ã«ããã«ã¯æ½è±¡åããªããã°ãããªã
ããã°ã©ã ãã·ã¹ãã å ¨ä½ãã·ã³ãã«ã«ããããã«ã¯ããã®ãã¨ããã³ã³ãã¬ã¯ãããªãå½¢ã§çµåãããåé¢ãããã§ããããã«ããªããã°ããã¾ããããã£ã¡ã¨ãã£ã¡ã®å ±éé ã決ãã¦ãLEGOãããã¯ã®ããã«ãã¤ãªãããã¯ããããã§ããªããã°ããã¾ããããã®ããã«ã¯ãç©äºãæ½è±¡åããªããã°ããã¾ããã
æ½è±¡åã¨ããã®ã¯ããè¤éããé ãããã¨ã§ã¯ããã¾ããã
ãã®ãã¨ãããå®è£ ã®è©³ç´°ãåãé¤ããã¨ã§ãã
ãããããã¨ã§ããã®ãã¨ã¯çµã¿åããå¯è½ã«ãªã£ã¦ãããããã®ãã®ããå ±éã®æ¹æ³ã§æ±ããããã«ãªãã¾ããLEGOãããã¯ã«ãªãã®ã§ãã
RDBã¯ããéåãã¨ããæ½è±¡åã使ã£ã¦ãã¾ããã§ããããããã¼ãã«ããµãã¯ã¨ãªããéåãã¨ãã¦å ±éã®æ±ããã§ããåãããã«JOINãããWHEREã§ãã£ã«ã¿ãããã§ãã¾ãã
Clojureã¯ãè¨èªã貫ãå ±éã®æ½è±¡ãã¼ã¿æ§é ãå®ç¾©ãã¦ãã¦ããããã§ããrecordã§ããããããã¯ç¬èªã«å®ç¾©ããä½ããã®åã§ãããAssociativeã¨ãã¦æ±ããã¨ã§ããã¾ãã¾ãªãã®ãå ±éã®æ¹æ³ã§æ±ããããã«ãã¦ãã¾ãã
ãã¼ã¿ã«æ½è±¡æ§é ãè¦ãã ãã¦ããã¹ã¦ãããã«éç´ãã¦ããå¿ è¦ãåºã¦ãã¾ããLEGOãããã¯åããããã§ããããã¯ã¤ã³ã¿ãã§ã¼ã¹ãå®ç¾©ãããã¨ãããããªããããã£ã¨å¤§ããªã·ã¹ãã ã§ããã°ããµã¼ãã¼éã®é¢ä¿ãã©ãæãããï¼ã¾ã§åºããããããã¾ããã
ã·ã³ãã«ã¯é¸æã ãããã·ã³ãã«ãªã·ã¹ãã ãã»ããã®ã§ããã°ãã·ã¹ãã å ¨ä½ããã³ã³ãã¬ã¯ããã¦ããªãåä½ã«åå²ã§ãããèãã¦ãããã°ãªãã¾ããã
ãããã¦ã³ã³ãã¬ã¯ããã¦ããªãåä½ã«ãªããæ½è±¡æ§é ã§æ¥ç¶ãããã·ã¹ãã ã¯ãããããã¯ãç°¡åãã«å¤æ´ã§ããã§ãããã
ã¾ããã Simple Made Easy ãªããã§ãã
ã¨ã¯ãããç¾å®ã®ä¸çã§ãå®å ¨ã«ã·ã³ãã«ãã¨ãããã®ã®å®ç¾ã¯é£ããã£ããããã¾ããClojureã ã£ã¦ãã°ã«ã¼ãåã¨ãã¦ã®æ¬å¼§ã«ã¯ãã¯ã¿ãªãããããªãã使ããã¨ã§ã丸æ¬å¼§ã¯ãããããé¢æ°å¼ã³åºããã¨è¦ãªãã¦ã大ä¸å¤«ã§ããã丸æ¬å¼§ããªã¹ãã¨ãã¦ä½¿ããªãããã§ã¯ããã¾ãããï¼ã§ãªãã¨ãã¯ããæ¸ããªãã®ã§ï¼ã
ã ããç¾å®ã«ã¯ãã¬ã¼ããªããåå¨ããã§ããããããã®ãã¬ã¼ããªãããããé¸æãªããã§ããããã°ã©ã ãã·ã¹ãã ãã·ã³ãã«ã«ããã®ã¯ããã¤ããç§ãã¡ã®é¸æãªãã§ãã
ãã®ãSimple Made Easyãã¨ãããã¬ã¼ã³ãã¼ã·ã§ã³ã§ãRichã¯Clojureã®è©±ãã»ã¨ãã©åºããªãã®ã§ãå ·ä½çã«ã©ã®é¨åã«å½±é¿ããã¨ãã¯èªããã¦ã¾ãããããããClojureã®ä¸¦ååã©ã¤ãã©ãª core.async ã使ã£ã¦ä½ã£ãããã°ã©ã ãããé¢æ°ãã¨ããã£ãã«ãã¨ããããããã·ã³ãã«ãªæ§é ããtransducerãpipelineã使ã£ã¦çµã¿åãããå½¢ã§ä½ãããã¨ããã«ãããã®çºæ³ãç¾ãã¦ãããã ã¨ç§ã¯æã£ã¦ãã¾ãã
ã·ã³ãã«ã«ãããã¨ã¯ãã£ã¬ã³ã¸ã§ãããã®ã§ããã¾ããã£ããã®ãããã§ãªããã®ãããã§ããããããã®èãæ¹ã¯ãClojureã®ããããªé¨åã«æ¯ã¥ãã¦ããããã«æãã¾ãã
ä»åã¯ããSimple Made Easyãã¨ããRich Hickeyã®ãã¬ã¼ã³ãã¼ã·ã§ã³ãéãã¦ãClojureã«ãããã·ã³ãã«ãã®èãæ¹ã«ã¤ãã¦æ¸ãã¦ã¿ã¾ããã
次ã«ä½æ¸ããã¯æªå®ã§ããã
Clojureã®ä¸ç観
ããã°ãæ¸ãã®ã¯ä¹
ã
ã§ãã
京é½ã§å°ããªä¼ç¤¾ããã£ã¦ãã¦ãèªç¤¾éçºã§Clojureã¨ClojureScriptã使ç¨ãç¶ãã¦ãæ¦ãï¼å¹´ããã使ãç¶ãã¦ãã¾ãããã®éç¨ã§ãClojureèªä½ã«ãå°ãããªããã½ã¼ã¹ã¬ãã«ã®è²¢ç®ãã§ããããã¦ããªã¼ãã³ã½ã¼ã¹ããã¸ã§ã¯ãã¨ãã¦ãé¢ç½ãã£ãã®ã§ããããã¨ãã¨ãªãã¸ã§ã¯ãæåè¨èªã°ãããã£ã¦ããã¨ãããããClojureã¨ãããã¾ã£ãããªãã¸ã§ã¯ãæåè¨èªã§ã¯ãªãè¨èªã«é£ã³è¾¼ãã çµé¨ãèãããã¨ãªããããããã°ã«ã¹ããã¯ããã¨ãä½ãä»ã®äººã«ãå½¹ç«ã¤ãã¨ããããã¨æã£ã¦ãããã°ã«æ¸ããã¨ã«ãã¾ããã
ãã®ã¨ãããã£ã¨ãèªç¤¾ã®ä»äºã¨ã¯å¥ã«ãæµæ¯å¯¿ã«ãã æ ªå¼ä¼ç¤¾ã¦ã¼ã¶ãã¼ã¹ ããã®ãä»äºã«åå ãã¦ãã¾ãï¼ç§ãæ³äººãä½ãåãããªã®ã§ãããï¼ãï¼å¹´ãããã«ãªãã¾ãï¼ããã¡ãã®æ¹ã§ãClojureãã·ã¹ãã è¨è¨ã®è©±ï¼ãã¬ã¼ã³ãªã©ï¼ãªã©ãä½åº¦ãããã¦ããã£ãããããåå¹´ãããã¯ãã¦ã¼ã¶ãã¼ã¹ããã§ãClojureãå®éçºã¸æå
¥ãå§ãããããéçºæ¯æ´ã¨ãã¦æºããã¾ããï¼Clojureã®ã·ã¹ãã ã¯ç¾å¨ãéæéçºä¸ã§ããã¶ã£ã¡ããClojureéçºè
åéä¸ã§ãï¼ã
ã¦ã¼ã¶ãã¼ã¹ããã®ã·ã¹ãã ã«ããã¦ããClojureã§go-blockãå®ç¾ãã並è¡å¦çã©ã¤ãã©ãª core.async ã使ã£ã¦ä¸¦è¡å¦çã·ã¹ãã ãä½ã£ãããã¦ããã®ã§ãããã§å¾ããããClojure+core.asyncã§ã®ä¸¦è¡ããã°ã©ãã³ã°ã®ç¥è¦ãªãããæ¸ãã¦ããããããããããã°ãããä¸å®æã§Clojureã«ã¤ãã¦ããã°ãæ¸ãã¦ããã¤ããã§ããæ°åãç¶ãã°ã
ä»åã¯ãClojureã使ããã¨ã«ãã£ã¦ãClojureãåæã¨ãã¦ããä¸ç観ããèªåã空æ°ã®ããã«åæã¨ãã¦ãããã®ã¨ç°ãªã£ã¦ãã¨ããã¨ãã¦ãClojureã«ãããæ½è±¡ãã¼ã¿æ§é ã¨ãããªã¢ãã£ãºã ã®ä»çµã¿ã«ã¤ãã¦æ¸ãã¦ã¿ã¾ãã
å°ãªãæ½è±¡ãã¼ã¿æ§é ã¨ãããããã®é¢æ°
Clojureã§ã¯ããªãã¸ã§ã¯ãæåè¨èªã¨ç°ãªããé¢æ°ã¨ãã¼ã¿ã¯ããããå®å ¨ã«åé¢ãã¦ãã¾ãããªãã¸ã§ã¯ãæåè¨èªã§ãªãã®ã ãããããªã®ã ããã£ã¦ãã¨ã¯çãç¥ã£ã¦ã¯ããã®ã ãããã©ããé¢æ°ï¼ã¡ã½ããï¼ããã¼ã¿ã¨çµã³ã¤ãã¦èãã¦ãã¾ãã¨ããã®ã¯ããªãã¸ã§ã¯ãæåè¨èªã«æ £ãã人ã®çã¿ãããªãã®ã¨ãã¦ãæã¿ã¤ãã¦ããã¨ããã®ããã«ãæãã¾ãã
Javaçãªãã¯ã©ã¹ãã¼ã¹ã®ãªãã¸ã§ã¯ãæåè¨èªã®å ´åãã¡ã½ãããä½ãã«ã¯ã¯ã©ã¹ãå®ç¾©ãã¦ããã«ã¡ã½ããã足ããããªã®ã§ãã¡ã½ããï¼é¢æ°ï¼ã¯ãããã¼ã¿ã®éã¾ãï¼ãªãã¸ã§ã¯ãï¼ãæä½ããå°ç¨ã®é¢æ°ã¨ãã¦å®ç¾©ããã¡ã§ããããããããã®ãªãã¸ã§ã¯ããæä½ããããã®ã¡ã½ããããªã®ã ããå½ããåã§ãã
ä¸æ¹ããã¼ã¿ã¨é¢æ°ãåé¢ãã¦ããå ´åã¯ãé¢æ°ãç¹å®ã®ã¯ã©ã¹ããªãã¸ã§ã¯ãã«çµã³ã¤ããæå³ã¯ãªãã§ãããéã«ãããé¢æ°ã®ããã«å°ç¨ã®ã¯ã©ã¹ãä½ãæå³ããªãã極端ã«èããã°ããã¹ã¦ã®é¢æ°ãå ±éã®ãã¼ã¿æ§é ãå¦çããããã«ããæ¹ããå¤æ§ãªé¢æ°ãæè»ã«æ´»ç¨ã§ããããã«ãªãã
ã¨ãããããããªãã¸ã§ã¯ãã«é¢æ°ãçµã³ã¤ãã¦ããããããããã®ã¡ã½ããã¯ãã®ãªãã¸ã§ã¯ãæ§é ãå¦çããããã®ãã®ã ï¼ä»ã®ç¨éã«ã¯ä½¿ããªãï¼ãã¨ãã風ã«å°éåã§ãã¦ãããã§ãã£ã¦ããã¼ã¿ã¨é¢æ°ãåå¥ã®ãã®ã¨æ±ã以ä¸ã¯ãããã®é¢æ°ã¯ãã®ãªãã¸ã§ã¯ãã ããæ±ããã¨ããåæãç½®ããªãã®ã§ãï¼å½ããåã§ãï¼ããããªãã¸ã§ã¯ãã¨å¥ã®ãªãã¸ã§ã¯ãããåã§ãã£ããã¯ã©ã¹ã§ãã£ãããç°ãªã£ãã¨ãã¦ããé¢æ°ã¯ããã®ãªãã¸ã§ã¯ãããé¢æ°ã®å¦çã§ããæ§é ã§ããã°ãå¦çã§ããã¹ããªãã§ããé¢æ°ã¨ãªãã¸ã§ã¯ããç¬ç«ãã¦ããã¨ããã®ã¯ããããæå³ã§ããã¹ãã§ããã§ããã°ããã¹ã¦ã®é¢æ°ã«ã¾ããããããªãå ±éã®æ±ç¨ãã¼ã¿æ§é ããã£ã¦ããã¹ã¦ã®ãã¼ã¿ã¯ãã®æ±ç¨æ§ãæ ä¿ãã¦ãã»ããããã
ãã¡ãããã縦ãã¨ã横ãã¨ããæ å ±ãæã£ããã¼ã¿ã使ã£ã¦ãé¢ç©ããæ±ããé¢æ°ã¯ããã¼ã¿ãã縦ãã¨ã横ãã¨ããæ å ±ãæã£ã¦ãããã¨ãæ±ããã ãããã©ããRectangleã ã¨ãTableã ã¨ãã®ç¹å®ã®ã¯ã©ã¹ã«ãã¤ã¬ã¯ãã«çµã³ã¤ãã¹ãã§ã¯ãªãã
ãã®èª²é¡ã«ã¯ããããªã¢ããã¼ãããããã§ããããï¼Structural Typeã¨ãï¼ï¼ãClojureã®å ´åã¯ãè¨èªå
¨ä½ãåæã¨ããæ½è±¡ãã¼ã¿æ§é ãããã¾ãããªã¹ãç¶ã®ãã®ã¯Seqã¨å¼ã°ããæ½è±¡ãã¼ã¿ï¼ä»£è¡¨ä¾ã¯é
åï¼ã¨ãã¦ããããç¶ã®ãã®ã¯Associativeã¨å¼ã°ããæ½è±¡ãã¼ã¿ï¼ä»£è¡¨ä¾ã¯ãããï¼ã¨ãã¦æ±ãã¾ããäºå®ä¸ã»ã¨ãã©ã®ãã¼ã¿ããã®ï¼ã¤ã§è¡¨ç¾ããã¦ãã¦ãå¤ãã®é¢æ°ããå¼æ°ã¨ãã¦Seqã¾ãã¯Associativeãåãåãï¼ãããã¯å
é¨ã§èªåã§å¤æããï¼ããSeqã¾ãã¯Associativeãåºåãã¾ãã
èªåãé¢æ°ãæ¸ãã¨ãã«ããç¬èªã®ãã¼ã¿åã§ã¯ãªããSeqãAssociativeãåæã¨ãã¦æ¸ãã®ããªã¹ã¹ã¡ã§ãããããããã¨ã§ãé¢æ°ã¯ä»ã®é¢æ°ã®ã¤ã³ãããã«ãªããã¾ãããä»ã®é¢æ°ã®åºåãå
¥åã§ãã¾ãï¼åé¢æ°ã®å
¥åã¨åºåãåãæ½è±¡ãã¼ã¿æ§é ã ããï¼ã
ãã®æ½è±¡åã¯å¾¹åºãã¦ãã¦ãä¾ãã°ãClojureã«ã¯defrecordããããããã使ãã°ã ã¬ã³ã¼ãã¨å¼ã°ãããç¬èªã®åã¨ãã£ã¼ã«ããæã£ããã¼ã¿æ§é ãä½ãåºããã¨ãã§ãã¾ããããã«ãã¬ã³ã¼ãã«å¯¾ãã¦ãããã³ã«ãå®è£ ãããã¨ã§ãJavaã«ãããã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ãããããªæãã®ã³ã¼ããæ¸ããã¨ãã§ãã¾ãã
(defrecord User [name age mail-address] IAuthenticate (auth [this param] (something-great param)))
ããã ãè¦ãã¨ãã¾ãã§ã¯ã©ã¹ãå®ç¾©ã§ãããã®ããã«æãã¾ããã¨ããããã®ã¬ã³ã¼ãã¯ãã¹ã¦Associativeã§ãããã¾ããã¤ã¾ãããã¹ã¦ã®ã¬ã³ã¼ãã¯Associativeãå¦çããé¢æ°ã«æ¸¡ããã¨ãå¯è½ã§ããã¾ãããã®ãã¼ã¿ã使ãå´ã¯ããã¼ã¿ãå®ã¯ã¬ã³ã¼ãã§ããã¨ãããã¨ãæ°ã«ããå¿ è¦ãï¼ååã¨ãã¦ã¯ï¼ããã¾ãããããã¯Associativeã ã¨ãããã¨ãããããã°ãããå®éãããã©ã¤ãã©ãªã®ããé¢æ°ã®æ»ãå¤ãããããã¼ã¸ã§ã³ã¾ã§ãããï¼å ¸åçãªAssociativeãã¼ã¿ï¼ã§ãã£ããã®ãã次ã®ãã¼ã¸ã§ã³ããã¬ã³ã¼ãã«å¤ãã£ã¦ããã¨ãã¦ããç¹ã«å½±é¿ã¯ãªãã¯ãã§ãã
;; ããã (def data1 {:name "t_yano"}) ;; ã¬ã³ã¼ã (defrecord User [name]) (def data2 (->User "t_yano")) ;; ã©ã¡ããAssociativeãªã®ã§ã:nameé¢æ°ã§:nameã®å¤ãåãåºãã (:name data1) ;=> "t_yano" (:name data2) ;=> "t_yano"
ãã®ãããªæ§é ã¯Javaã®ã¤ã³ã¿ãã§ã¼ã¹ã®ãããªãã®ãããã°ãä»ã§ãå®ç¾ã§ããã¨æãã ãããã©ãï¼å®éãAssociative㨠Seqã¯ãJavaã®ã¤ã³ã¿ãã§ã¼ã¹ã¨ãã¦å®ç¾©ããã¦ãã¾ãï¼ãããã¯ã注ææ·±ãè¨è¨ããã°ãã®ã©ã¤ãã©ãªå ã§ã¯ããã§ãããã¨ãã話ã§ãã£ã¦ãè¨èªã¨ãã¦æ¨æºã®æ½è±¡ãã¼ã¿ãå®ç¾©ãã¦ããã¹ã¦ãããã«éç´ãããããã¨ããä¸çã§ã¯ãä»ã®è¨èªæ©è½ãããã¹ã¦ããã®ãããªä»çµã¿ãæ¯æ´ããããã«ä½ããã¦ãã¾ããè¨èªã¨ãã¦ã®åæã§ããããã§ãããã¨ãã°ãJavaã§ãã¹ã¦ã®ãã¼ã¿ãMapã§ä½ã£ã¦ããè¦ããã ãã§å©ç¹ãªã©ãªãã§ããããããããåæã§è¨èªãä½ããã¦ããªãããã§ãã
ãã®ãããªæ½è±¡ãã¼ã¿æ§é ããããããããé¢æ°ã¨ãã¼ã¿ãåé¢ã§ããããã§ããé¢æ°ã¯å ±éã®æ½è±¡ãã¼ã¿æ§é ããè¦ã¦ããªããããããå®éã®ã¯ã©ã¹ã¨ã¯çµã³ã¤ãå¿ è¦ããªãã®ã§ãã
ã10種é¡ã®ãã¼ã¿æ§é ã«ãããããæ±ã10åã®é¢æ°ãããããããã²ã¨ã¤ã®ãã¼ã¿æ§é ãæ±ã100åã®é¢æ°ãããæ¹ãè¯ã (It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures)ãã¨ããè¨èããã¾ãã
ãã¼ã¿æ§é ã«ããããé¢æ°ããã
ä¸ã¤ã®ãã¼ã¿æ§é ãæ±ã100åã®é¢æ°
ãã®ä¸æã«è³æã®äººãå対ã®äººãããã§ãããããClojureã¯æ確ã«ãã²ã¨ã¤ã®ãã¼ã¿æ§é ãæ±ã100åã®é¢æ°ãããããããªä¸çã®æ¹ããããã¨ããåæã§ä½ããã¦ããã®ã§ãã
ã¢ãããã¯ãªå¤æ ï¼ããªã¢ãã£ãºã ï¼
ãã¦ãå°ãªãæ½è±¡ãã¼ã¿æ§é ã¨ããããã®é¢æ°ãã¨ããçå±ã¯ããã£ãã¨ãã¦ããªãã¸ã§ã¯ãã«çµã³ã¤ãã¦ãªãé¢æ°ã«ããããå¤æ
ï¼ããªã¢ãã£ãºã ï¼ã¯ã©ããªããã§ãããããç¨éãã¨ã«ç°ãªãé¢æ°ãç¨æããã°ããã£ã¦ãã¨ãªãã§ããããã
ãã¡ãããå®éã®éçºã«ã¯å¤æ
ã¯å¿
è¦ã§ããå¤æ
ãªãã§ãMySQLã¨PostgreSQLã§ç°ãªãåããããconnecté¢æ°ãã©ããã£ã¦å®ç¾©ããããããã§ãããã mysql-connect 㨠psql-connect ã使ãåãããã¨ãããããªãã¨ãé¿ãããã¨ããã§ãã
ã§ããããClojureã«ãå¤æ é¢æ°ãå®ç¾©ããä»çµã¿ãããã¾ããdefrecordã«ãã£ã¦ç¬èªã®åãå®ç¾©ããå¼æ°ã®åã«é¢æ°å®è£ ãç´ã¥ãããã¨ãã§ãã¾ãããããã¯defmulti / defmethod ã使ã£ã¦ãã«ãã¡ã½ãããå®ç¾©ãããã¨ã§ããã¼ã¿ã®å¤ï¼å®éã«ã¯å¼ã®çµæã§ããï¼ã«ãã£ã¦é¢æ°å®è£ ãåãæ¿ãããã¨ãã§ãã¾ããä¾ãã°ãå¼æ°ã¨ãã¦æ¸¡ãããDBæ¥ç¶å®ç¾©ã®ãã©ã¤ãåã«åºã¥ãã¦ãconnecté¢æ°ã®å®è£ ãåãæ¿ãããã¨ãã£ã使ãæ¹ãã§ãã¾ãã
é¢æ°ï¼ã¡ã½ããï¼ãå¤æ ã«ããä»çµã¿ã«ã¤ãã¦ã¯JavaScriptã¿ãããªã¢ããã¼ãããå¼æ°ã®åã®çµã¿åããã«ãã£ã¦åãæ¿ãããã«ããã«ãã£ã¹ãããããã£ãããä¸ã®ä¸ã«ã¯ãã§ã«è²ã ãªãã®ãããã®ã§ãClojureã®å¤æ ã®ä»çµã¿ãããã»ã©ç¬èªã®ãã®ã ã¨ããããã§ã¯ãªãã§ããããå¼·ãã¦ããã°ãClojureã®ãã«ãã¡ã½ããã§è¿½å ããé¢æ°ã¯ãåçã«ç´ä»ãã追å ãããåãé¢ãããã§ããã®ãé¢ç½ãã¨ããã§ãããããèªä½ããä»ã®è¨èªï¼ç¹ã«åçãªè¨èªï¼ã§ã§ããªãã¨ãããã®ã§ãããã¾ããã
å¤æ
ãå®ç¾ããä»çµã¿ããããClojureã®ãå¤æ
ã«å¯¾ããæ
度ã¨ããããèãæ¹ã®æ¹ããé¢ç½ãã®ã§ã¯ãªããã¨æãã¾ãã
Clojureã§ã¯ãClojureã®å¤æ
ã®ä»çµã¿ã®ãã¨ãAd-hoc Polymophismã¨å¼ãã§ã¾ãããã®ã¯ã¼ãèªä½ã¯ï¼Clojureãããåã«ï¼çµæ§æãããããããªã®ã§ãæ°ããæ¦å¿µã§ã¯ãªãã®ã§ãããããããã«ããå®éã®éçºã¸ã®å½±é¿ãçµæ§é¢ç½ãã
å¤æ
ï¼ããªã¢ãã£ãºã ï¼ã¨ããã®ã¯ããªãã¸ã§ã¯ãæåã®ä¸çã§ã¯ãããããªãã¸ã§ã¯ãã¨å¥ã®ãªãã¸ã§ã¯ããåãã¡ã½ãããæã£ã¦ãããã©ãéãåä½ããããã¨ããéã®è¦ç¹ãããããããªãã¸ã§ã¯ãã¨å¥ã®ãªãã¸ã§ã¯ãã¯ãå®éã«ã¯éãåä½ãããã ããããåãã¡ãã»ã¼ã¸ã«åå¿ããã®ã§åããªãã¸ã§ã¯ãã¨ã¿ãªãããã¨ãã£ãæèã§ä½¿ãããæãããã¾ãããªãã¸ã§ã¯ãæåã®ã¡ãã»ã¼ã¸ã»ããã·ã³ã°ã®èãæ¹ã«ã®ã£ã¨ãã°ããããªãã¸ã§ã¯ãAã¨Bã«åãã¡ãã»ã¼ã¸ãéã£ã¦ããå®éã«åãå¦çï¼ã¡ã½ããï¼ã¯å¥ãããããªããã ãåãã¡ãã»ã¼ã¸ã«å¿çã§ããã®ã ããã両è
ã¯åããªãã¸ã§ã¯ãã¨ã¿ãªãããã¨ããããã§ãã
ã¤ã¾ãããã¤ããªãã¸ã§ã¯ãã¨ã¨ãã«ããªãã¸ã§ã¯ãå士ã®é¢ä¿ï¼åãã¡ãã»ã¼ã¸ã«å¿çããã®ã ããå®è³ªåãã¨ãã¦æ±ãããã¨ãããµãã¿ã¤ãã§ãããã¨ãï¼ã¨ãã¦èªãããå¾åãããã¾ãã
ä¸æ¹ãClojureã«ã¨ã£ã¦å¤æ ã¨ã¯ãé¢æ°ãã£ã¹ãããã®è©±ã¨æãããã¦ãã¾ããé¢æ°ã¯ãã¼ã¿ï¼ãªãã¸ã§ã¯ãï¼ã¨ãã¤ã¬ã¯ãã«ã¯çµã³ã¤ãã¦ãªãã®ã§ãå¤æ ã®èª¬æã¨ãã¦ããªãã¸ã§ã¯ããã¯ã©ã¹ã¨çµã³ã¤ãã¦èªããã¨ã¯ã§ãã¾ãããããé¢æ°ãå¼ãã æã«ãå®éã«å®è¡ãããé¢æ°å®è£ ã¯ã©ããªã®ãï¼ã¨ãããã£ã¹ãããã®åé¡ã«éããªãã®ã§ãã
ãã£ã¹ãããã®åé¡ãã¨ãããã¨ã¯ãå®éã®ã¨ãããé¢æ°ã使ãå´ã«ã¨ã£ã¦ã¯ãå®ã¯é¢æ°ãå¤æ
ã§ãããã©ããã¨ãããã¨ã¯ã使ç¨ä¸ãã¾ãé¢ä¿ããªãã¨ãããã¨ã§ããé¢æ°ã¯é¢æ°ã§ãã£ã¦ããããå¤æ
ã§ãããã¯ã¦ã¼ã¶ã¼ã«ã¯é¢ä¿ããªãã
ä¾ãã°ããã ã®é¢æ°ã¯ããã®é¢æ°ãå¼ã¶ã¨é¢æ°æ¬ä½ã«ç´æ¥ãã£ã¹ãããããã¾ãããããé¢æ°ãã£ã¹ãããã®ã²ã¨ã¤ã®å½¢ã§ãã
ããããã«ãã¡ã½ããã§ããã°ãå¼æ°ã®å¤ï¼å®éã«ã¯å¤ãè¨ç®ããçµæï¼ã«ãã£ã¦å®éã«ä½¿ãé¢æ°å®è£
ãæ¢ãããå¾ã«å¼ã³åºããã¾ããdefrecord / defprotocol ã«ãããã£ã¹ãããã§ã¯ãå¼æ°ã®åã«ãã£ã¦ãã£ã¹ãããããã¾ããããã¯å®è£
ã®è©³ç´°ã§ãã£ã¦ãé¢æ°ã使ãå´ã«ã¨ã£ã¦ã¯ãé¢æ°ãå¼ã¹ã°é¢æ°ãå®è¡ãããã°ããã®ã§ãã
ããããå¥ã®äººã®ä½ã£ãé¢æ°å®è£ ããå é¨ã§ããã°ã©ã ã¨ãã¦ifæã使ã£ã¦å¥ã®é¢æ°ã«å¦çããã£ã¹ããããã¦ããã¨ãã¦ãã使ãå´ã«ã¨ã£ã¦ã¯é¢ä¿ãªãã®ã¨åãã§ããifæã§ã®åå²ã¯ãæåã®é¢æ°ãã£ã¹ãããã¨èããã°ããã«ãã¡ã½ããã¨åããé¢æ°ãã£ã¹ãããã ã¨è¨ãã¾ããã
使ãå´ã«ã¨ã£ã¦ã¯ãããã«ãããã ã®é¢æ°ã«è¦ããã®ã§ããããClojureã«ããã¦ãé¢æ°ã¯ãã¨ã§ãã¤ã§ãå¤æ ã«åãæ¿ããããåå¨ãªããã§ãã
éå»ã«ç§ãDBæä½ã©ã¤ãã©ãªã®ä¸ã¤ Korma ã«éã£ããããã§ã¯ãååãã¯ãªã¼ãããå¦çãMySQLã¨PostgreSQLã¨ã§åããå¿ è¦ã«å¯¾å¿ãã¾ããã対å¿ã¯ç°¡åã§ãã¯ãªã¼ãããé¢æ°ããã«ãã¡ã½ããã«å¤æ´ããå¼æ°ã¨ãã¦æ¸¡ã£ã¦ããDBæ¥ç¶å®ç¾©ã®æ¥ç¶URLã使ã£ã¦é©åãªã¯ãªã¼ãå¦çã«ãã£ã¹ãããããã ãã§ããé¢æ°ããã«ãã¡ã½ããã«å¤ãã£ãããã§ãããé¢æ°ãå¼ã³åºãå´ããè¦ãã¨ããã¯ããã ã®é¢æ°ã«è¦ãã¾ãã®ã§ãä»ã®é¨åã«ã¯ã¾ã£ããå½±é¿ãã¾ããã
ã¤ã¾ããã³ã¼ããæ¸ãã¦ããæã«ãããé¢æ°ãå¤æ ã«ãããã©ããã¨ããã®ã¯å¾ããèãã¦ã大ä¸å¤«ãªä»çµã¿ãªããã§ãããã¡ãããä½ã£ã¦ã段éã§ãè¨è¨ã¨ãã¦ãããã®é¢æ°ã¯å¤ããæ¡å¼µã§ããããã«ãããããããã«ãã¡ã½ããã«ãã¦ããããã¨ããããã¯ã¦ã¼ã¶ã¼å©ä¾¿æ§ãèãã¦ãããã³ã«ãå®ç¾©ãã¦ããããã¨ãããã¨ã¯ããã¾ãããããã§ãªãã¨ãããå¾ãããã«ãã¡ã½ããããããã³ã«é¢æ°åãããã¨ããçµæ§ç°¡åã«è¡ããã®ã§ãã
ã ããAd-hocï¼å ´å½ããçãªï¼ããªã¢ãã£ãºã ã¨å¼ã¶ããã§ãããã¡ãã注æãã¹ããã¨ã¯ãã£ã¦ã対象ã®å¦çãé¢æ°ã«åé¢ããã¦ãªããã°ãå¾ã§å¤æ é¢æ°åãããã¨ãã§ãã¾ãããããã§ããã°é¢æ°ã¯ç´°ããåãã¦ãããæ¹ããå¾ãã対å¦ããããã¨æãã¾ãããã®ãããªæ³¨æç¹ããã¯ãªã¢ãã¦ããã°ãæè»ã«å¾ããã³ã¼ãå¤æ´å¯è½ã ãã¨ããã®ããClojureã®å©ç¹ã®ä¸ã¤ã§ãã
ä»ã®æåãç¡çããæã¡è¾¼ã¾ãªãã®å¤§äº
ããã°ã©ãã³ã°è¨èªã«ã¯ãè¨èªãã¨ã«æåã¨ãããã大äºã«ãã¦ããèãæ¹ããããã®ã§ããClojureã«ã¯Clojureã®å¤§äºã«ãã¦ãããã®ããã£ã¦ãè¨èªä»æ§èªä½ãããã®å¤§äºã«ãã¦ãããã®ãåæã«è¨è¨ããã¦ããã¯ãã§ããä¸ã«ç´¹ä»ãããã®ããClojureã¨ããè¨èªã«æå³çã«çµã¿è¾¼ã¾ããä»æ§ãªè¨³ã§ãã
ä»ã®è¨èªããæ°ããè¨èªã«ç§»ã£ã¦ããã¨ãæåã¯ãä»ã¾ã§é¦´æãã§ããè¨èªã®æåã¨ãæ°ããè¨èªã®ããæ¹ã¨ããã¾ã£ããç°ãªã£ã¦ãããã¨ã«æ··ä¹±ãã¦ãèªåã®é¦´æãã§ããæåã¨åãã«ãããã¨ãã¦ãã¾ããã¡ã§ããããããè¨èªä»æ§ã¨ãã®è¨èªã®æåã¯å¼·ãã¤ãªãã£ã¦ããã®ãªã®ã§ãæåãç¡è¦ãã¦å¥ã®æåã§æ¸ããã¨ãã¦ãè¦ããã ãã§ãã
ãã®ããã«ã¯ããã¯ãããã®è¨èªã大äºã«ãã¦ãããã®ã¯ãªããªã®ããã©ãããæå³ã§ãã©ããããã¨ãå®ç¾ãããã¦ããããè¨èªãã¶ã¤ã³ã«ãªã£ã¦ããã®ãããç¥ãã®ã大äºã ã¨æãã®ã§ããæå³ããããã°ã馴æããªãã£ããã®ã«ãæ¥ã«ããªãã»ã©ããããããã¨ããã¨ç´å¾æãå¾ããããã®ã§ããæ½è±¡ãã¼ã¿æ§é ãå¤æ ã®ä»çµã¿ãªãããããã®ãããªä¾ã®ä¸ã¤ã§ãã
Clojureã¯Javaã¿ãããªåãã¼ã¹ã®ãªãã¸ã§ã¯ãæåè¨èªã¨ã¯ãããªãéãè¨èªãªã®ã§ãããä¸è¦ãããã£ã¦Javaã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¨åãããã¨ããããã£ã¦Lombokã§@Valueã§ã¯ã©ã¹å®ç¾©ãããããªãã®ï¼ãã¨ãæãã¦ãã¾ãæ©è½ããã£ãããã¾ããããããã¡ããããããã¯ã¤ã³ã¼ã«ã§ã¯ãªãããæå³ãã¦ããã¨ãç°ãªã£ã¦ããã¨ãããã¾ãã
ä»ã®è¨èªãã移ã£ã¦ããæã«ã¯ãããªãã§ããããä»çµã¿ã«ãªã£ã¦ããã®ãï¼ãã®èæ¯ã¯ãªããªã®ãï¼ããææ¡ããã®ãã¨ã¦ã大äºã ã¨æãã¾ããæå³ããããã£ã¦ãã¾ãã°ãã¨ã¦ãç°¡æ½ã§æ¸ããããè¨èªã§ãããã
æ½è±¡ãã¼ã¿æ§é ãAd-hocå¤æ 以å¤ã«ããClojureã«ã¯ãã·ã³ãã«ã§æ§é åããããè¨èªãä½ãããã«ãããããªã¢ã¤ãã¢ãåãè¾¼ã¾ãã¦ãã¦é¢ç½ãã®ã§ãä»å¾ããç解ã§ããç¯å²ã§æ¸ãã¦ããããã¨ããã§ãã