python + lisp hy的新手註記2 eval, HyModel and python AST

來自我在Stack Overflow上的提問,https://stackoverflow.com/questions/51675355/how-to-eval-a-cond-case-and-return-function-object前端

(hy做者回復真及時,可是以前在github issue裏提問就被拒了 哈哈哈)python

個人問題是,我須要本身組裝 帶有條件表達式(cond [p  e]) 。git

p多變,而e基本不變。所以但願和gcc編譯到中間語言RTL同樣,在RTL層作點優化,部分求值。github

準確的說,先把e求值求出來,個人e語句的求值結果是function object函數

而後在時節1裝入 條件語句p優化

在時節2 對(cond [p  e]) 用eval求值,就直接獲得 想要的函數對象了spa

代碼大概這樣code

;a fn object
(setv a_fn (fn [x] (+ 1 x)))
;a mock predicator
(setv predicator True)
;inject predicator and a_fn into a (cond ..)
(setv cond_expr `(cond [(~predicator) [~a_fn]]))
;eval at another place 
(eval cond_expr)

可是這樣是報錯的:對象

got TypeError: Don't know how to wrap <class 'function'>: <function test_cond_list_fn.<locals>.<lambda> at 0x000001B879FD3D08>blog

 

做者的解釋說

 

hy的eval是 首先要編譯到python的ast。(相似gcc前端語言 編譯到 RTL的AST)

但「雖然能夠把抽象對象放進hyExpression,但無法compile it」

一方面   Hy的compiler 只接受 HyModel  (hyExpression  HyList  HySymbol 還有基本類型HyInt HyString 等等),

另外一方面:在 Python ast裏,function object 沒有顯式的表示法, 因此就沒有對應的HyModel  (同理可知,其餘自定義的pyObejct也都這樣了)

 

——但,不是徹底無解。

做者的給出的解決方案是,不要eval 含有function object  的hyExpression 但能夠有 函數的 定義

 1 compile a function definition.

=> (setv a-fn '(fn [x] (+ 1 x)))
=> (setv cond-expr `(cond [True ~a-fn]))
=> (eval cond-expr)
<function <lambda> at 0x0000020635231598>

注意第一行是普通單引號',不是反引號`

 

2 Or a function's symbol.

=> (defn b-fn [x] (- x 1))
=> (setv cond-expr2 `(cond [True b-fn]))
=> (eval cond-expr)
<function <lambda> at 0x0000020635208378>

 

Mmmm~  到了AST這個層次,還真是有點subtle 啊

我還得消化一下。。 

相關文章
相關標籤/搜索