$letを実装しました

github.com

昨日話題にだけだしていて未実装だった$letという記法を実装しました。夢物語的な皮算用ではなくなりました。 予想通り以下が必要になりました。

  • scope
  • 関数呼び出しとは異なる評価順序の特殊構文

以下の様なコードが動くようになります。

data.yaml

$let:
  withPlus:
    {$partial: $prefix, prefix: +}
person:
  name: {$withPlus: foo}
  age:
    $let:
      withPlus: {$partial: $add, v: 10}
    body:
      $withPlus: 10
friends:
  - name: {$withPlus: bar}

ここで

$ zenmai -m ./add.py data.yaml
person:
  name: +foo
  age: 20
friends:
- name: +bar

この時以下のようなactionが定義されているとする(add.py)。

from zenmai.actions import partial  # NOQA


def prefix(d, prefix=":"):
    return prefix + d


def add(n, v=1):
    return n + v

以下詳細。

scope

scopeを実装しました。scopeは以下の2つの箇所で新しく生成されます。

  • $loadを呼んだとき
  • $letでscopeを作ったとき

これに伴い、$importや$fromによるimportも現在のscopeに対して束縛するようになりました。

関数呼び出しとは異なる評価順序の特殊構文

今までは、以下のような記述を書いたときには、<d> を評価する前に <val0><val1> が評価されていました。

<fn>: <d>
<kw0>: <val0>
<kw1>: <val1>

一方let-syntaxは以下の形式なので

$let:
  var0: val0
  var1: val1
  ...
body: <d>

通常の評価順序の場合、先にbodyの部分が評価されてしまいます。これは良くありません。仕方がないのでとりあえず今回は$letだけ特別に評価順序を変えてサポートしました。

そろそろ

そろそろ、またドキュメント(readmeやexamplesを含む)が実装に追いつかなくなってきた。あと例を真面目なものにしたい。