9.1 Hy

初步了解抽象语法树之后,可以畅想一下为Python创建一种新的语法,并将其解析并编译成标准的Python抽象语法树。Hy编程语言(http://docs.hylang.org/en/latest/)做的正是这件事。它是Lisp的一个变种,可以解析类Lisp语言并将其转换为标准的Python抽象语法树。因此它同Python生态系统完全兼容。可以将其与Clojure(http://clojure.org/)同Java的关系类比。Hy完全可以单独写本书来讲,所以本节只是稍作介绍。

如果你已经写过Lisp代码1,Hy语法和它看起来非常类似。安装之后,运行hy解释器将给出一个标准的REPL(Read-Eval-Print Loop)提示符,从这里可以同解释器进行交互。

广告:个人专属 VPN,独立 IP,流量大,速度快,连接稳定,多机房切换,每月最低仅 10 美元

% hy
hy 0.9.10
=> (+ 1 1)
2

在Lisp语法中,圆括号表示一个列表,第一个元素是一个函数,其余元素是该函数的参数。因此,上面的代码相当于Python中的1+1

大多数结构都是从Python直接映射过来的,如函数定义。变量的设置则依赖于setv函数。

=> (defn hello [name]
... (print "Hello world!")
... (print (% "Nice to meet you %s" name)))
=> (hello "jd")
Hello world!
Nice to meet you jd

在内部,Hy对提供的代码进行解析并编译成Python抽象语法树。幸运的是,Lisp比较容易解析成树,因为每一对圆括号都可以表示成列表树的一个节点。需要做的仅仅是将Lisp树转换为Python抽象语法树。

通过defclass结构可以支持类定义,这是从CLOS(Common Lisp ObjectSystem)获得的启发。

(defclass A [object]
 [[x 42]
  [y (fn [self value]
    (+ self.x value))]])

上面的代码定义了一个名为A的类,继承自object,包括一个值为42的类属性x,以及用来返回传入参数和x的和的一个方法。

最棒的是,你可以直接导入任何Python库到Hy中并随意使用。

=> (import uuid)
=> (uuid.uuid4)
UUID('f823a749-a65a-4a62-b853-2687c69d0e1e')
=> (str (uuid.uuid4))
'4efa60f2-23a4-4fc1-8134-00f5c271f809'

Hy还包括更多高级结构和宏。如果想在Python中拥有caseswitch语句,可以欣赏一下cond是怎么做的。

(cond
((> somevar 50)
 (print "That variable is too big!"))
((< somevar 10)
 (print "That variable is too small!"))
(true
 (print "That variable is jusssst right!")))

Hy是 一个非常不错的项目,因为它允许你进入Lisp的世界又不用离开你熟悉的领域,因为你仍然在写Python。hy2py工具甚至能够显示Hy代码转换成Python之后的样子。2