Open10

hylang (hyrule)のマクロ

atledatled

hylangの各種マクロの動作を一々調べるのも億劫なので備忘。
使ったものしか反映しないので網羅性はないです。

atledatled

hylang: https://docs.hylang.org/en/master/api.html?highlight=match
hyrule: https://hyrule.readthedocs.io/en/master/

hylangは1.0+a4から0.24にバージョンアップし、構文がいくつか変更されました。

  • タプルが(, x)から#(x)になった。
  • if test a bが必ずTrueの場合とFalseの場合の値を与えなければならなくなった。
  • cond [x y]cond a bになった。
  • タグマクロは廃止され、リーダーマクロとその定義マクロdefreaderが追加された。
    • リーダーマクロは(require hyrule :readers [%])のように:readersの後にシンボルのリストかキーワード*によって導入する。

もしかしたらごちゃごちゃになっているかもしれませんがご容赦ください。

atledatled

. #* args
hylangのマクロ
argsのもつメソッドやプロパティに逐次的にアクセスする。

例えばPythonで下のように書ける場合、

text = "      Hello    World        "
text.strip().split()

['Hello', 'World']

hylangでは.を利用して、

(setv text "      Hello    World        ")
(. text (strip) (split))

['Hello', 'World']

と書ける。
いわゆるメソッドチェーン。

評価後の値を次の評価に使うので、状態変化後に値を返さない(Noneが返る)メソッドはこれを使った連続は行えない。

atledatled

-> head #* body
hyruleのマクロ
headを最初にとってbodyの第一引数に入れ...を繰り返す。
hylangではメソッド呼び出しを関数と同様の語順で書けるので、.を関数呼び出しに対応させたような感じ。

上記の(. text (strip) (split))を最終的にprintするように書き直す。

(setv text "      Hello    World        ")
(-> text (.strip) (.split) (print))

['Hello', 'World']

->では次に来る値が必ず第一引数になるので、それまでの操作を任意の場所に入れるにはas->を用いる。

atledatled

as-> head name #* rest
hyruleのマクロ
nameに今持っている結果の値を入れていく。

(require hyrule ["as->"])

(setv text "      Hello    World        ")
(as-> text it 
         (.strip it)
         (.split it)
         (print "this code returned" it))


this code returned ['Hello' 'World']
atledatled

ncut seq key1 #* keys
hyruleのマクロ
複数のスライスを一度に渡すことのできるマクロ。

例えばnumpyの多次元配列の一部をスライスで取るとき、スライスを2つ渡す。

import numpy as np

m = np.arange(9).reshape(3,3)

array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])


m[1:3, 1:3]
array([[4, 5],
       [7, 8]])

ところがcutはこのような操作を行うことができない。

(import numpy :as np)
(require hyrule [->])

(setv m (. (np.arange 9) (reshape 3 3)))

array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])


(-> m (cut 1 3) (cut 1 3))

array([[6, 7, 8]])
# m[1:3][1:3] と等価

これを解決したいときにncutをつかう。

(ncut m 1:3 (: 1 3))

array([[4, 5],
       [7, 8]])

アクセスする引数にはスライス・タプル・単なる値が使える。

atledatled

ap-when test-form #* body
hyruleのマクロ
test-formをキーワードitで呼び出せる

(ap-when 1
  f"ok {it}")

"ok 1"
atledatled

doto form #* expressions
hyruleのマクロ
formの評価値を各expressionsの第一引数に入れてexpressionsを順次実行する。
formを返す。

(require hyrule [doto])

(setv a (doto [1 2 3]
          (.append 4)
          (print "is inter")
          (.extend [5 6])))
(print "a:" a)
[1, 2, 3, 4] is inter
a: [1, 2, 3, 4, 5, 6]

pythonにありがちな状態変更メソッドをまとめるのに便利。

atledatled

%
hyruleのリーダーマクロ
次のシンボルにある%nをその位置に引数を入れる関数に変更する。
nは数値。

#% (a %1 b)

は、

(fn [n1] (a n1 b))

と等価。

nは歯抜けでもよく、その場合抜かされた値は使われない。

%nがなくても関数オブジェクトになるので、threading.Threadのような関数オブジェクトを引数に取るものに式を渡すのにも使える。

atledatled

py string
hylangのマクロ。
pythonの式であるstringをhyのコンパイル時に埋め込む。
式の値が返ってくる

状態を持つような場合はpysを使う。
pysは中身に関わらずNoneを返す