LoginSignup
5
1

More than 3 years have passed since last update.

hyclb:hyとCommon Lispの混合環境

Last updated at Posted at 2020-03-04

hylangからcommon-lisp(sbcl)を呼びだして,common lispの機能を使えるようにした

これは,もともと

で公開されていた hycl というcommon-lispと似た環境をhy上に作るlibraryのフォークで,
これにcommon-lisp(sbcl)をpythonから呼びだす cl4py の機能をclisp.eval_qexprという関数名にして導入した.

このlibraryの目玉はdefunマクロで,

(defmacro defun [name arg &rest code]
 `(defn ~name [~@arg]
     codesbcl上のmacroexpandで展開
     展開したcodehy上のcommon-lisp互換関数で実行
))

することで optima などをのマクロをhyから使えるようになっている.

defunの中でcommon-lispはマクロ展開の時のみに呼びだされるのでnumpyとの混合などもできる.

(clisp.eval_qexpr '(ql:quickload "anaphora"))
(clisp.eval_qexpr '(rename-package 'anaphora 'ap) )

(import numpy)
(defun test_alet2 (x y)
   (setq y (+ 10 y))
   (numpy.sin
      (* 
        (ap:alet (+ x y)  (+ 1 ap:it))
        (/ numpy.pi 180)))
    )

(test_alet2 49 30)
==>    1.0

clisp.eval_qexprでsbclを直接呼ぶこともできる.

パターンマッチマクロをpython(hy)で使う.

common lispでパターンマッチマクロを実装した optima の主要な機能をhyから使えるようにした.pythonのパターンマッチマクロで pampy というのがあるようだが,それよりも強力.ただしsbclを利用している関係で大文字が小文字に全部変換される制限がある.

(import numpy)
(defun testom4 (u)
    (setq p numpy.pi)
    (om:match
      u
      (`(,x 5 ,z)  (list x y z))
      (`(,x ,p ,z) (list x 2 z)))
    )

(testom4 (list/cl  1 numpy.pi  3) ) 
==> '(1 2 3)

classのプロパティのパターンマッチもできる

(clisp.eval_qexpr `(defstruct numpy.ndarray  shape ndim)) 

とすることでclassのプロパティをSBCLに認識させると,こんなこともできる

(defun testom6 (z)
    (om:match
      z
      ((numpy.ndarray shape ndim ) (list shape ndim )))
    )

(testom6 (numpy.array [1 2 3]))
==>    '( (, 3) 1)

(dir (numpy.array [1 2 3])) で見れる全プロパティをSBCLに認識させる以下の関数も用意した

(cl_struct_import_obj (numpy.array [1 2 3 ]))

実装

この実装の肝はhyに付属している hy-repr 関数で

sbcl.stdin << (hy-repr code)

ということをするために,cl互換関数をhy上に用意したり, hy-repr 関数の出力をhy-repr-registerでいじったりしている.

制限

  • 大文字が全て小文字に変換されるので class MyClassみたいのは class myclassに強制変換される
  • common-lisp互換関数で実装していない関数が多数
  • optima は動かせたが trivia はちゃんとテストしていないので,できるだけoptimaを使ってほしい.
  • hyの評価順序の関係で (ql:quickload "optima") などをライブラリの中(hyclb.cl4hy.hyの真ん中あたり) で実行している.これをしないとtestで失敗する.しかしemacs hy-modeからだと後からql:quickload しても動く.謎な挙動
  • pythonのlist => clのvector, pythonのtuple => clのlistとして扱っているが,hyのバグなのかtupleが途中でlistに変換されてしまうことがある.この関係でvectorとlistの区別がちゃんとされていない
  • dict = consのlist の扱いが適当になってるので何か統一的な扱いができる方法がいるが思いつかない
  • tagbodyの互換関数が変数のスコープの扱いに不安のある実装になっているので,om:matchの中で変数を新しく宣言するのはやめた方が良い.ちゃんとしたtagbodyのhyでの実装を誰か作ってくれないかなあ
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1