JavaScript勉強会

JavaScriptの学習日記

Ramda.jsのLensとは?

JavaScript関数型プログラミング」を読んでいたら、意味がよく分からない用語が出てきたのでメモ。

 

jsstudy.hatenablog.com

 

レンズ

(p.48)

レンズ(Lenses)と呼ばれる関数型のアプローチ

レンズは、オブジェクトの変更を普遍的に一括管理する最良の選択肢です。

 

(純粋な)関数参照とも呼ばれるレンズは、状態を持つデータ型の属性を不変的にアクセスし操作できる関数型プログラミングのソリューションです。

レンズの内部的な動作はコピーオンライトに似ており、状態の管理と複製を適切に処理できる内部ストレージコンポーネントを利用しています。

しかし、レンズを自分で実装する必要はありません。

関数型JavaScriptライブラリRamdaの実装を利用できます。

 

JavaScriptでデータを可変ではなく不変で扱いたい場合、Ramda.jsという関数型ライブラリーのLensという機能を使えば便利らしいです。

しかし、本書の説明では意味がいまいちよく分かりませんでした。

 

とりあえず、後で復習するために、調べた資料をメモしておきます。

(また後で見直してみます。)

 

Ramda.jsのレンズ

https://ramdajs.com/docs/#lens

Returns a lens for the given getter and setter functions.

The getter "gets" the value of the focus; the setter "sets" the value of the focus.

The setter should not mutate the data structure

 

qiita.com

 

#01. 不変性

JavaScriptでは ある程度不変性を意識して書ける。

ただ、どうしても冗長な書き方になるうえ、うっかりするとすぐにシャロ―コピーになってしまう。JavaScript で不変性を志向した書き方をするのは難しいといわざるを得ない。

 

解決策の方向性は二つある。

生のArray, Objectのまま頑張る Ramda.js 方式と、類似の新たなデータ構造で頑張る Immutable.js 方式。

Ramda 方式では、ライブラリとして、Array, Object に対するディープコピー機を提供するだけでなく、レンズ機能を提供する。

 

いくつかレンズの機能を紐解くキーワードが出てきました。

  • シャローコピー
  • ディープコピー
  • レンズ

 

www.webprofessional.jp

 

lens関数は、オブジェクトや配列とともに特定のRamda.js関数に送られる特別なオブジェクトです。

lens関数は、それぞれのオブジェクトまたは配列の特定のプロパティまたはインデックスからデータを取得したり変換することができます。

 

getter関数やsetter関数のメソッドでオブジェクトをラッピングするのではなく、対象のプロパティに「焦点をあてる」レンズのような関数を作れます。

Ramda.jsからの関数を使って、lens関数によって定義されたプロパティにアクセスできます。

 

Haskellのレンズ

「レンズ」という考え方は、元々はHaskellのLensパッケージに由来しているものだそうです。

 

tech.recruit-mp.co.jp

 

lens とは?

端的に言うと、 getter や setter を関数型プログラミング的に抽象化したものです。対象となるオブジェクトや配列の特定のプロパティやインデックスからデータを取得したり変換することが出来ます。と、これだけ聞くと何の凄さも伝わってきませんが、ネストの激しい複雑なデータ構造に対して不変性を保ちつつアクセスできるというのが一番の特徴として挙げられます。

元々は Haskell に lens というパッケージがあり、これを Ramda.js の API として実装したものだと思っていただければ OK です。

 

matrix.ai

 

f:id:jsstudy:20190430235118p:plain

 

The definition of a Lens basically describes this bidirectional transformation concept via 2 primitives, a get and a set. We have 2 state locations, the first is called Source, the second Target. Target' is the new updated target after a transformation, and the Source' is the new updated source after transformation. The source transformation only occurs after the target gets transformed.

 

The name Lens comes from Benjamin Pierce's work on bidirectional transformations.

 

レンズの定義は、基本的に、getとsetの2つのプリミティブを介した双方向変換の概念を記述します。2つの状態の場所があり、最初のものはソース、2番目のものはターゲットと呼ばれます。ターゲット’は変換後の新しい更新済ターゲットで、ソース’は変換後の新しい更新済ソースです。ソース変換は、ターゲットが変換された後にのみ行われます。

 

Lensという名前は、Benjamin Pierceによる双方向変換に関する研究に由来します。

 

The Weird World of Bi-Directional Programming - Benjamin C. Pierce

http://www.cis.upenn.edu/~bcpierce/papers/lenses-etapsslides.pdf

 

f:id:jsstudy:20190501001230p:plain

 

f:id:jsstudy:20190501001243p:plain

 

図解のおかげで、何となくレンズのイメージが伝わってきますが、実際のコードで動作を確認してみないと、やっぱよく分かりませんね。

 

後で動作を確認してみたいと思います。

 

 

 

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ (impress top gear)