英语法语西班牙语

Ad


OnWorks 网站图标

hy - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管服务提供商中运行 hy

这是可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行的命令 hy,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器

程序:

您的姓名


hy - hy 文档 [图片:Hy] [图片]

尝试 Hy https://try-hy.appspot.com

的PyPI https://pypi.python.org/pypi/hy

来源 https://github.com/hylang/hy

清单 hylang-讨论

体育馆 #hy 在 Freenode 上

建立 状态
特拉维斯 CI.取消缩进

Hy 是嵌入在 Python 中的一种美妙的 Lisp 方言。

由于 Hy 将其 Lisp 代码转换为 Python 抽象语法树,因此您有
整个美丽的 Python 世界触手可及,以 Lisp 形式呈现!

内容:

快速开始


[图片:凯伦拉斯塔德的拥抱] [图片]

(感谢 Karen Rustad 的拥抱!)

如何 TO 的GET HY REAL 高效率:

1。 创建一个 在线会议 蟒蛇 环境.

2. 激活您的虚拟 Python 环境。

3。 安装 hy 的PyPI 点子 安装 hy.

4. 启动 REPL hy.

5. 在 REPL 中输入内容:

=>(打印“Hy!”)
海兰!
=> (defn salutationsnm [name] (print (+ "Hy " name "!")))
=> (salutationsnm "你的名字")
你的名字!



6. 完成后按 CTRL-D。

OMG! 这是 惊人! I a Hy 程序。

7.打开精英编程编辑器并输入:

(打印“我打算用 Python 语法编写代码,但后来我得到了 Hy。”)

8.另存为 真棒.hy.

9. 运行你的第一个 Hy 程序:

hy真棒.hy

10.
深呼吸,以免过度换气。

11.
邪恶地微笑,偷偷溜到你的海德威,做一些不可描述的事情。

在线课程


欢迎来到 Hy 教程!

简而言之,Hy 是一种 Lisp 方言,但将其结构转换为 Python 的一种方言......
字面意思是转换为 Python 的抽象语法树! (或者把它放在更粗糙的地方
术语,Hy 是 Python 上的 lisp-stick!)

这很酷,因为这意味着 Hy 是几件事:

· 一个感觉非常 Pythonic 的 Lisp

· 对于 Lispers 来说,这是一种使用 Lisp 疯狂能力的好方法,但在 Python 的广阔世界中
库(为什么是的,您现在可以在 Lisp 中编写 Django 应用程序!)

· 对于 Pythonistas 来说,这是从舒适的 Python 开始探索 Lisp 的好方法!

· 适合所有人:令人愉快的语言,有很多巧妙的想法!

基础 简介 口齿不清 巨蟒达人
好吧,也许您以前从未使用过 Lisp,但您使用过 Python!

Hy 中的“hello world”程序实际上非常简单。 让我们试试看:

(打印“你好世界”)

看? 简单! 您可能已经猜到了,这与 Python 版本相同:

打印“你好世界”

要添加一些超级简单的数学,我们可以这样做:

(+ 1 3)

这将返回 4 并且相当于:

1 + 3

你会注意到列表中的第一项是被调用的函数,
其余的参数是传入的参数。事实上,在 Hy(与大多数
Lisps)我们可以将多个参数传递给加号运算符:

(+ 1 3 55)

这将返回 59。

也许您以前听说过 Lisp,但对它了解不多。 Lisp 没有你那么难
可能会想,而且 Hy 继承自 Python,所以 Hy 是开始学习 Lisp 的好方法。
Lisp 最明显的一点是有很多括号。 这有可能
乍一看似乎令人困惑,但并不难。 让我们看一些简单的数学
包裹在一堆括号中,我们可以输入到 Hy 解释器中:

(setv 结果 (- (/ (+ 1 3 88) 2) 8))

这将返回 38。但为什么呢? 好吧,我们可以看看等价的表达式
Python:

结果 = ((1 + 3 + 88) / 2) - 8

如果你想弄清楚上面是如何在 python 中工作的,你当然会
通过求解每个内括号来计算结果。 这是相同的基本思想
嗨。 让我们先用 Python 试试这个练习:

结果 = ((1 + 3 + 88) / 2) - 8
# 简化为...
结果 = (92 / 2) - 8
# 简化为...
结果 = 46 - 8
# 简化为...
结果= 38

现在让我们在 Hy 中尝试同样的事情:

(setv 结果 (- (/ (+ 1 3 88) 2) 8))
; 简化为...
(setv 结果 (- (/ 92 2) 8))
; 简化为...
(setv 结果 (- 46 8))
; 简化为...
(setv 结果 38)

正如你可能猜到的,最后一个表达式是 设置 意味着分配变量
“结果”到 38。

看? 不是太难!

这是 Lisp 的基本前提。 Lisp 代表“列表处理”; 这意味着
程序的结构实际上是列表的列表。 (如果你熟悉 Python
列表,想象一下与上面完全相同的结构,但用方括号代替,任何
你将能够看到上面的结构既是程序又是数据结构。)这是
用更多的例子更容易理解,所以让我们写一个简单的Python程序,测试一下,
然后显示等效的 Hy 程序:

def simple_conversation():
打印“你好!我想认识你。介绍一下你自己吧!”
name = raw_input("你叫什么名字?")
age = raw_input("你的年龄是多少?")
打印“你好”+名字+“!我看你是“+年龄+”岁。

简单对话()

如果我们运行这个程序,它可能是这样的:

你好! 我想认识你。 说说你自己!
你叫什么名字? 加里
你几岁? 38
你好加里! 我看你已经38岁了。

现在让我们看看等效的 Hy 程序:

(defn 简单对话 []
(打印“你好!我想认识你。告诉我你自己!”)
(setv name (raw-input "What is your name?"))
(setv age (原始输入“你的年龄是多少?”))
(打印(+“你好”名字“!我看你是“
年龄“岁。”)))

(简单对话)

如果你看上面的程序,只要你记住每个元素的第一个元素
程序的列表是被调用的函数(或宏……我们稍后会谈到那些)
其余的都是参数,很容易弄清楚这一切意味着什么。
(你可能也猜到了, 定义 是定义方法的 Hy 方法。)

尽管如此,很多人一开始觉得这很令人困惑,因为括号太多了,
但是有很多事情可以帮助使这变得更容易:保持缩进良好并且
使用带有括号匹配的编辑器(这将帮助您弄清楚每个
括号与) 配对,事情就会开始变得舒服。

拥有一个实际上是一个非常简单的数据的代码结构有一些优点
作为 Lisp 的核心的结构是基于。 一方面,这意味着您的程序是
易于解析,并且程序的整个实际结构非常清晰
给你。 (在 hy 中有一个额外的步骤,您看到的结构被转换为 Python 的
自己的表示……在“更纯”的 Lisps 中,例如 Common Lisp 或 Emacs Lisp,数据
您在代码中看到的结构和执行的数据结构要多得多
字面上接近。)

另一个含义是宏:如果程序的结构是一个简单的数据
结构,这意味着您可以编写可以非常轻松地编写代码的代码,这意味着
实现全新的语言功能可以非常快。 在 Hy 之前,这不是
对于 Python 程序员来说很有可能......现在你也可以使用宏的不可思议的
力量(只是小心不要将他们瞄准脚下)!

Hy is a 口齿不清的 蟒蛇
Hy 转换为 Python 自己的抽象语法树,因此您很快就会发现所有
熟悉的蟒蛇力量触手可及。

您可以在 Hy 中完全访问 Python 的数据类型和标准库。 让我们实验
在 hy 解释器中使用这个:

=> [1 2 3]
[1,2,3]
=> {“狗”“吠”
...“猫”“喵”}
...
{'狗':'吠','猫':'喵'}
=> (, 1 2 3)
(1,2,3)

如果您熟悉其他 Lisp,您可能会对 Hy 支持 Common
Lisp 引用方法:

=> '(1 2 3)
(1公升 2公升 3公升)

您还可以访问所有内置类型的好方法:

=> (.strip "fooooo")
“噗”

这是什么? 是的,这与以下内容完全相同:

“fooooo”.strip()

没错---带有点符号的Lisp! 如果我们将此字符串分配为变量,我们
还可以执行以下操作:

(setv this-string "fooooo")
(这个字符串.strip)

条件句呢?:

(如果(尝试某事)
(打印“这是真的”)
(打印“这是假的”))

正如你在上面所说的,第一个参数 if 是真值测试,第二个参数是
正文如果为真,第三个参数(可选!)如果为假(即。 其他).

如果你需要做更复杂的条件,你会发现你没有 ELIF
在 Hy 中可用。 相反,您应该使用称为 COND. 在 Python 中,你可能会这样做
就像是:

一些变量 = 33
如果 somevar > 50:
打印“那个变量太大了!”
elif somevar < 10:
打印“那个变量太小了!”
其他:
打印“那个变量是对的!”

在 Hy,你会这样做:

(条件
[(> somevar 50)
(打印“那个变量太大了!”)]
[(<somevar 10)
(打印“那个变量太小了!”)]
[真的
(打印“那个变量是对的!”)])

你会注意到的是 COND 在执行的某个语句和
有条件地检查真假,然后在它变成时执行一些代码
出来是真的。 您还会注意到 其他 最后简单地通过
检查 true - 那是因为 true 永远是真的,所以如果我们走到这一步,我们会
总是运行那个!

您可能会注意到,如果您有以下代码:

(如果某些条件
(身体-如果-真)
(如果为假则为正文))

可是等等! 如果您想在其中之一的主体中执行多个语句怎么办
这些?

您可以执行以下操作:

(如果(尝试某事)
(做
(打印“这是真的”)
(打印“为什么不呢,让我们继续讨论它是多么真实!))
(打印“这个仍然只是假的”))

你可以看到我们使用了 do 包装多个语句。 如果你熟悉其他
Lisps,这相当于 程序 别处。

注释以分号开头:

(打印“这将运行”)
; (打印“但这不会”)
(+ 1 2 3) ; 我们将执行添加,但不执行此评论!

循环并不难,但有一种特殊的结构。 在 Python 中,我们可能会这样做:

因为我在 范围(10):
打印 "'i' 现在在 " + str(i)

Hy 中的等价物是:

(对于 [i(范围 10)]
(打印 (+ "'i' 现在在 " (str i))))

您还可以导入和使用各种 Python 库。 例如:

(进口操作系统)

(如果(os.path.isdir“/tmp/somedir”)
(os.mkdir "/tmp/somedir/anotherdir")
(打印“嘿,那条路不存在!”))

Python 的上下文管理器 ( 语句)是这样使用的:

(用 [[f(打开“/tmp/data.in”)]]
(打印 (.read f)))

这相当于:

with open("/tmp/data.in") as f:
打印 f.read()

是的,我们确实有列表推导式! 在 Python 中,你可能会这样做:

赔率平方 = [
战俘(数量,2)
对于 num in 范围(100)
如果数量 % 2 == 1]

在 Hy,你可以这样做:

(setv 赔率平方
(列表组合
(战俘编号 2)
(数量(范围 100))
(= (% 数字 2) 1)))

; 并且,一个从 Clojure 页面无耻地窃取的示例:
; 让我们列出棋盘的所有块:

(列表组合
(, xy)
(x (范围 8)
y "ABCDEFGH"))

; [(0, 'A'), (0, 'B'), (0, 'C'), (0, 'D'), (0, 'E'), (0, 'F'), ( 0, 'G'), (0, 'H'),
; (1, 'A'), (1, 'B'), (1, 'C'), (1, 'D'), (1, 'E'), (1, 'F'), (1 , 'G'), (1, 'H'),
; (2, 'A'), (2, 'B'), (2, 'C'), (2, 'D'), (2, 'E'), (2, 'F'), (2 , 'G'), (2, 'H'),
; (3, 'A'), (3, 'B'), (3, 'C'), (3, 'D'), (3, 'E'), (3, 'F'), (3 , 'G'), (3, 'H'),
; (4, 'A'), (4, 'B'), (4, 'C'), (4, 'D'), (4, 'E'), (4, 'F'), (4 , 'G'), (4, 'H'),
; (5, 'A'), (5, 'B'), (5, 'C'), (5, 'D'), (5, 'E'), (5, 'F'), (5 , 'G'), (5, 'H'),
; (6, 'A'), (6, 'B'), (6, 'C'), (6, 'D'), (6, 'E'), (6, 'F'), (6 , 'G'), (6, 'H'),
; (7, 'A'), (7, 'B'), (7, 'C'), (7, 'D'), (7, 'E'), (7, 'F'), (7 , 'G'), (7, 'H')]

Python 支持各种花哨的参数和关键字参数。 在 Python 中,我们可能
看到:

>>> def optional_arg(pos1, pos2, keyword1=None, keyword2=42):
...返回[pos1,pos2,keyword1,keyword2]
...
>>> optional_arg(1, 2)
[1, 2, 无, 42]
>>> optional_arg(1, 2, 3, 4)
[1,2,3,4]
>>> optional_arg(keyword1=1, pos2=2, pos1=3, keyword2=4)
[3,2,1,4]

Hy 中同样的事情:

=> (defn optional-arg [pos1 pos2 &optional keyword1 [keyword2 42]]
... [pos1 pos2 关键字1 关键字2])
=>(可选参数 1 2)
[1 2 无 42]
=>(可选参数 1 2 3 4)
[1 2 3 4]

如果您运行的是 0.10.1 之后的 Hy 版本(例如 git master),那么还有一个不错的新版本
关键字参数语法:

=> (可选参数 :keyword1 1
...:pos2 2
...:pos1 3
...:关键字 2 4)
[3,2,1,4]

否则,您始终可以使用 应用. 但什么是 应用?

你熟悉传入吗 *参数**夸克 在 Python 中?:

>>> 参数 = [1 2]
>>> kwargs = {"keyword2": 3
...“关键字1”:4}
>>> optional_arg(*args, **kwargs)

我们可以用 应用:

=> (setv args [1 2])
=> (setv kwargs {"keyword2" 3
...“关键字1” 4})
=>(应用 optional-arg args kwargs)
[1,2,4,3]

还有一个字典样式的关键字参数构造,如下所示:

(定义另一种风格的 [&key {"key1" "val1" "key2" "val2"}]
[键1键2])

这里的区别在于,因为它是一本字典,所以你不能依赖任何特定的
对参数进行排序。

Hy也支持 *参数**夸克. 在 Python 中:

def some_func(foo, bar, *args, **kwargs):
导入打印
pprint.pprint((foo, bar, args, kwargs))

Hy 等价物:

(defn some-func [foo bar &rest args &kwargs kwargs]
(进口印刷品)
(pprint.pprint(, foo bar args kwargs)))

最后,我们当然需要课程! 在 Python 中,我们可能有一个类:

类 FooBar(对象):
“”“
另一个示例类
“”“
def __init__(自我,x):
自我.x = x

def get_x(自我):
“”“
返回我们的 x 副本
“”“
返回 self.x

在海:

(defclass FooBar [对象]
“另一个示例类”
[[ - 在里面 -
(fn [自我 x]
(setv self.xx)
; 当前需要 --init-- 因为 __init__ 需要 None
; 希望这会消失:)
没有任何)]

[获取-x
(fn [自我]
“返回我们的 x 副本”
自我.x)]])

你也可以做类级别的属性。 在 Python 中:

类客户(模型。模型):
名称 = 模型.CharField(max_length=255)
地址 = 模型.TextField()
笔记 = 模型.TextField()

在海:

(defclass 客户 [models.Model]
[[名称 (models.CharField :max-length 255})]
[地址(models.TextField)]
[注释(models.TextField)]])

Hy <-> 蟒蛇 互操作
通过导入 Hy,你可以直接从 Python 中使用 Hy!

如果您将以下内容保存在 问候.hy:

(defn greet [name] (打印“hello from hy,”name))

然后你可以直接从 python 使用它,通过在导入模块之前导入 hy。 在
Python:

进口高
导入问候语

问候。问候(“Foo”)

你也可以在 python 中声明一个函数(甚至是一个类!)并在 Hy! 中使用它!

如果您将以下内容保存在 问候.py 在Python中:

定义问候(姓名):
打印(“你好,%s”%(姓名))

你可以在 Hy 中使用它:

(进口问候)
(。问候问候“foo”)

要使用关键字参数,您可以使用 in 问候.py:

定义问候(名称,标题=“先生”):
打印(“问候,%s %s”%(标题,姓名))

(进口问候)
(。问候问候“Foo”)
(。问候问候“Foo”“Darth”)
(应用(。问候问候)[“Foo”] {“title”“Lord”})

这将输出:

问候,傅先生

问候,达斯 Foo

你好,傅大人

小贴士!
Hy 还具有称为“线程宏”的功能,这是
Clojure 的。 “线程宏”(写成 ->) 用于避免深度嵌套
表达式。

线程宏将每个表达式插入到下一个表达式的第一个参数中
的地方。

让我们来看看经典:

(循环(打印(评估(读取))))

我们可以这样写,而不是这样写:

(-> (read) (eval) (print) (loop))

现在,使用 蟒蛇-sh,我们可以展示线程宏如何(因为python-sh的设置)
可以像管道一样使用:

=> (导入 [sh [cat grep wc]])
=> (-> (cat "/usr/share/dict/words") (grep "-E" "^hy") (wc "-l"))
210

当然,这扩展到:

(wc (grep (cat "/usr/share/dict/words") "-E" "^hy") "-l")

更具可读性,不是吗? 使用线程宏!

HY 风格 指南


“你知道,部长,我在很多方面都不同意邓布利多的观点……但你不能否认他是
有风格……”——菲尼亚斯·奈杰勒斯·布莱克, 哈利 波特 订购产品 of 凤凰城

Hy 风格指南旨在成为 Hyve 的一套基本规则(是的,Hy 社区
以将 Hy 附加到所有内容而自豪)以编写惯用的 Hy 代码。 Hy 衍生很多
来自 Clojure 和 Common Lisp,同时始终保持 Python 互操作性。

序幕
of Hy
乌蒙问大和尚:“你讲的是什么经?”
“涅槃经。”
“涅槃经有四德,不是吗?”
“有。”
乌蒙拿起一个杯子问道:“这有多少功德?”
“一点也没有,”和尚说。
“可是古人说有,不是吗?” 乌蒙说。
“你觉得他们说的怎么样?”
乌蒙敲了敲杯子,问道:“你明白吗?”
“不,”和尚说。
“那么,”乌蒙说,“你最好继续讲经。”
— (koan) 宏

以下说明了进入制作过程的设计决策的简要列表
HY。

· 看起来像 Lisp; DTRT 与它(例如破折号变成下划线,耳罩变成
全部大写)。

· 我们仍然是 Python。 大多数内部结构以 1:1 的方式转换为 Python 内部结构。

· 到处使用Unicode。

· 尽可能修复 Python 2 中的错误决定(参见 真除法).

· 如有疑问,请使用 Python。

· 如果您仍然不确定,请使用 Clojure。

· 如果您更不确定,请使用 Common Lisp。

· 请记住,我们不是 Clojure。 我们不是 Common Lisp。 我们是 Homoiconic Python,与
有意义的额外位。

布局 & 缩进
· 避免尾随空格。 他们糟透了!

· 缩进应为 2 个空格(无硬制表符),除非匹配
上一行。

;; 好(和首选)
(定义纤维 [n]
(如果(<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2))))))

;; 还好
(定义纤维 [n]
(如果 (<= n 2) n (+ (fib (- n 1)) (fib (- n 2))))))

;; 还好
(定义纤维 [n]
(如果(<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2))))))

;; 歇斯底里的可笑
(定义纤维 [n]
(如果(<= n 2)
;; 是的,我喜欢随意按空格键
(+ (fib (- n 1)) (fib (- n 2))))))

· 括号必须 决不要 独自一人,独自一人,悲伤和孤独。

;; 好(和首选)
(定义纤维 [n]
(如果(<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2))))))

;; 歇斯底里的可笑
(定义纤维 [n]
(如果(<= n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))
)
); GAH,用火烧掉它

· 垂直对齐 块。

(让 [[foo (bar)]
[qux(baz)]]
(foo qux))

· 行内注释距离代码末尾两个空格; 他们必须始终有一个
注释字符和注释开头之间的空格。 另外,尽量不要
评论显而易见。

;; 好的
(setv ind (dec x)) ; 索引从 0 开始

;; 符合风格,但只是陈述明显的
(setv ind (dec x)) ; 将索引设置为 x-1

;; 坏的
(setv ind (dec x));为了好玩而打字

编码 样式
· 作为惯例,尽量不要使用 DEF 对于全局变量以外的任何东西; 用 设置
内部函数、循环等。

;; 好(和首选)
(定义*限制* 400000)

(defn fibs [ab]
(虽然是真的
(产量一)
(setv (, ab) (, b (+ ab)))))

;; 不好(而不是首选)
(defn fibs [ab]
(虽然是真的
(产量一)
(def (, ab) (, b (+ ab))))))

· 不要在要使用向量语法的地方使用 s 表达式语法。 例如,事实
这两个例子中的前者有效只是因为编译器并不过分
严格的。 实际上,在诸如此类的地方正确的语法是后者。

;; 坏(和邪恶)
(defn foo (x) (打印 x))
(富 1)

;; 好(和首选)
(defn foo [x] (打印 x))
(富 1)

· 遇到深度嵌套时使用线程宏或线程尾宏
s 表达式。 但是,在使用它们时要明智。 在清晰和清晰的情况下使用它们
可读性提高; 不要构造复杂的、难以理解的表达式。

;; 首选
(定义*名称*
(用 [f(打开“names.txt”)]
(-> (.read f) (.strip) (.replace "\"" "") (.split ",") (sorted))))

;; 不太好
(定义*名称*
(用 [f(打开“names.txt”)]
(排序 (.split "," (.replace "\"" "" (.strip (.read f))))))))

;; 可能不是一个好主意
(定义正方形?[x]
(->> 2 (pow (int (sqrt x))) (= x)))

· Clojure 风格的点符号优于直接调用对象的方法,
虽然两者都将继续得到支持。

;; 好的
(用 [fd(打开“/ etc / passwd文件")]
(打印 (.readlines fd)))

;; 不太好
(用 [fd(打开“/ etc / passwd文件")]
(打印(fd.readlines)))

结论
“时尚易逝,风格永恒”——伊夫·圣罗兰

本指南只是一组社区准则,显然,社区准则确实如此
没有活跃的社区就没有意义。 欢迎投稿。 加入我们#hy in
freenode,关于它的博客,关于它的推文,最重要的是,和 Hy 一起玩得开心。

谢谢
· 本指南深受启发 @保罗塔格 的博文 Hy 生存 产品指南

· Clojure的 样式 产品指南

文档 指数


内容:

命令 Line 接口
hy
命令 Line 附加选项
-c
执行 Hy 代码 命令.

$ hy -c "(打印 (+ 2 2))"
4

-i
执行 Hy 代码 命令,然后留在 REPL 中。

-m
执行 Hy 代码 模块,包括 定义域 如果定义。

-m 标志终止选项列表,以便之后的所有参数 模块 姓名
传递给模块 系统参数文件.

版本0.10.2中的新功能。

- 间谍 在执行之前打印等效的 Python 代码。 例如:

=> (defn salutationsnm [name] (print (+ "Hy " name "!")))
defsalutationsnm(name):
return print(((u'Hy ' + name) + u'!'))
=> (salutationsnm "你的名字")
称呼nm(u'YourName')
你的名字!
=>

版本0.9.11中的新功能。

--显示回溯
打印 Hy 异常的扩展回溯。

版本0.9.12中的新功能。

-v 打印 Hy 版本号并退出。

c
命令 Line 附加选项
文件[, 文件N]
将 Hy 代码编译为 Python 字节码。 例如,将以下代码保存为
hyname.hy:

(定义 hy-hy [名称]
(打印(+“Hy”名字“!”)))

(hy-hy "Afroman")

然后运行:

$ hyc hyname.hy
$ python hyname.pyc
嗨阿弗曼!

hy2py
版本0.10.1中的新功能。

命令 Line 附加选项
-s

--with-源
显示解析的源结构。

-a

--with-ast
显示生成的 AST。

-例如

--没有-蟒蛇
不要显示从 AST 生成的 Python 代码。

Hy 语)
警告:
这是不完整的; 请考虑为文档工作做出贡献。

理论 of Hy
Hy 保持与 Python 的双向 100% 兼容性
本身。 所有 Hy 代码都遵循一些简单的规则。 记住这个,因为它会进来
电话。

这些规则有助于确保 Hy 代码在两种语言中都是惯用的和可交互的。

· 耳罩中的符号将被转换为该字符串的大写版本。 为了
例, FOO 会变成 FOO.

· UTF-8 实体将使用 小码 并以 嘿_。 例如,
会变成 hy_w7h, 会变成 hy_g6h我♥你 会变成 hy_iu_t0x.

· 包含破折号的符号将被替换为下划线。 例如,
渲染模板 会变成 渲染模板. 这意味着带破折号的符号将
阴影它们的下划线等价物,反之亦然。

内置插件
Hy 具有许多特殊形式,用于帮助生成正确的 Python AST。
以下是“特殊”形式,它们的行为可能有点出乎意料
一些情况。

.
版本0.10.0中的新功能。

. 用于对对象进行属性访问。 它使用一个小的 DSL 来允许快速
访问嵌套数据结构中的属性和项目。

例如,

(.foo bar baz [(+ 1 2)] frob)

编译为:

foo.bar.baz[1 + 2].frob

. 编译它的第一个参数(在这个例子中, FOO) 作为执行操作的对象
属性取消引用。 它使用裸符号作为访问的属性(在示例中, 酒吧,
巴兹, 颤抖),并编译列表的内容(在示例中, [(+ 1 2)]) 用于索引。
其他参数会引发编译错误。

访问未知属性会引发 属性错误. 访问未知密钥会引发
索引错误 (在列表和元组上)或 密钥错误 (在字典上)。

->
-> (或 穿线 ) 用于避免表达式的嵌套。 线程宏
将每个表达式插入下一个表达式的第一个参数位置。 下列
代码演示了这一点:

=>(定义输出[ab](打印ab))
=> (-> (+ 4 6) (输出 5))
10 5

->>
->> (或 穿线 尾巴 ) 类似于 穿线 ,但代替
将每个表达式插入到下一个表达式的第一个参数中,并将其作为
最后一个论点。 以下代码演示了这一点:

=>(定义输出[ab](打印ab))
=> (->> (+ 4 6) (输出 5))
5 10

应用
应用 用于应用可选的参数列表和可选的 kwargs 字典
到一个函数。

用法: (申请 昵称 [参数] [夸格])

例子:

(定义 thunk []
“你在那里”)

(应用 thunk)
;=> "你在那里"

(defn total-purchase [价格金额 & 可选 [费用 1.05] [增值税 1.1]]
(* 价格金额费用增值税))

(申请总购买 [10 15])
;=> 173.25

(应用总购买量 [10 15] {"vat" 1.05})
;=> 165.375

(apply-purchase [] {"price" 10 "amount" 15 "vat" 1.05})
;=> 165.375


用于逻辑表达式。 它至少需要两个参数。 如果所有参数
评估为 ,返回最后一个参数。 在任何其他情况下,第一个假值
将被退回。 用法示例:

=>(和真假)


=>(和真真)


=>(和真1)
1

=>(和真[]假真)
[]

注意:
一旦第一个 false 出现短路并停止评估参数
遭遇。

=>(和假(打印“你好”))


断言
断言 用于在程序运行时验证条件。 如果条件不
遇见,一个 断言错误 被提出。 断言 可以带一两个参数。 首先
参数是要检查的条件,它应该评估为 or 。 该
第二个参数是可选的,是断言的标签,是将要执行的字符串
断言错误。 例如:

(断言(= 变量期望值))

(断言假)
; 断言错误

(断言(= 1 2)“一应等于二”)
; 断言错误:一应等于二

assoc命令
assoc命令 用于将键与字典中的值相关联或设置列表的索引
到一个值。 它至少需要三个参数: data 结构体 要修改,一个
or 指数和一个 折扣值. 如果使用三个以上的参数,它将成对关联。

用法示例:

=>(让[[集合{}]]
...(联合收藏“狗”“树皮”)
...(印刷收藏))
{u'Dog': u'Bark'}

=>(让[[集合{}]]
......(联合收藏“狗”“树皮”“猫”“喵”)
...(印刷收藏))
{u'Cat': u'Meow', u'Dog': u'Bark'}

=>(让 [[集合 [1 2 3 4]]]
...(关联集合 2 无)
...(印刷收藏))
[1, 2, 无, 4]

注意:
assoc命令 修改数据结构并返回 不包含.

打破
打破 用于跳出循环。 它立即终止循环。 下列
例子有一个无限 用户输入后立即终止的循环 k.

(而真(如果(=“k”(原始输入“?”))
(休息)
(打印“再试一次”)))

COND
COND 可用于构建嵌套 if 声明。 以下示例显示了
宏与其展开的关系:

(cond [条件 1 结果 1]
[条件 2 结果 2])

(如果条件 1 结果 1
(如果条件 2 结果 2))

如下图,只执行第一个匹配结果块。

=> (defn 校验值 [值]
... (cond [(< value 5) (打印“值小于 5”)]
... [(= value 5) (print "value is equal to 5")]
... [(> value 5) (打印“值大于 5”)]
... [真(打印“价值是它不应该是的东西”)]))

=>(检查值 6)
值大于 5

继续
继续 将执行返回到循环的开始。 在下面的例子中,
(副作用1) 每次迭代都会调用。 (副作用2),然而,只被调用
列表中的所有其他值。

;; 假设 (side-effect1) 和 (side-effect2) 是函数和
;; 集合是一个数值列表

(对于 [x 集合]
(做
(副作用1 x)
(如果 (% x 2)
(继续))
(副作用2 x)))

字典编排
字典编排 用于创建字典。 它需要三个或四个参数。 首先
两个参数用于控制返回值(键值对),而第三个是
用于从序列中选择项目。 第四个可选参数可用于
根据条件表达式过滤掉序列中的一些项目。

=> (dict-comp x (* x 2) [x (range 10)] (odd? x))
{1:2、3:6、9:18、5:10、7:14}

do / 程序
do程序 用于评估每个参数并返回最后一个。 返回
丢弃除最后一个参数之外的所有其他参数的值。 它可以用于 拉姆达 or
列表组合 执行更复杂的逻辑,如以下示例之一所示。

一些示例用法:

=>(如果为真
...(做(打印“副作用摇滚!”)
...(打印“是的,真的!”)))
副作用摇滚!
是的,真的!

;; 假设(副作用)是一个我们想要为每个函数调用的函数
;; 以及列表中的每个值,但我们不关心其返回值
=> (list-comp (do (副作用 x)
... (如果 (< x 5) (* 2 x)
... (* 4 x)))
... (x (范围 10)))
[0, 2, 4, 6, 8, 20, 24, 28, 32, 36]

do 可以接受任意数量的参数,从 1 到 n。

DEF / 设置
DEF设置 用于将值、对象或函数绑定到符号。 例如:

=>(定义名称 [“爱丽丝”“鲍勃”“查理”])
=>(打印名称)
[你'爱丽丝',你'鲍勃',你'查理']

=> (setv counter (fn [收藏品] (.count 收藏品)))
=> (计数器 [1 2 3 4 5 2 3] 2)
2

定义类
新类声明为 定义类. 它可以接受两个可选参数:一个向量
定义一个可能的超类和另一个包含新属性的向量
类为两个项目向量。

(defclass 类名 [super-class-1 super-class-2]
[[属性值]])

值和函数都可以绑定到新类上,如下例所示:

=> (defclass Cat []
... [[年龄无]
... [颜色“白色”]
... [speak (fn [self] (print "Meow"))]])

=>(定义点(猫))
=> (setv spot.colour "Black")
'黑色的'
=> (.speak 点)


定义 / 得不偿失
定义得不偿失 宏用于定义函数。 它们采用三个参数: 姓名
要定义的函数的向量 参数,并 身体 功能:

(定义名称 [参数] 正文)

参数前面可能有以下关键字:

&可选的
参数是可选的。 该参数可以作为一个两项列表给出,其中
第一个元素是参数名称,第二个元素是默认值。 参数
也可以作为单个项目给出,在这种情况下,默认值为 不包含.

=> (defn 总价值 [价值 & 可选 [增值税 10]]
...(+(/(*价值增值税)100)价值))

=>(总值 100)
110.0

=>(总值 100 1)
101.0

&钥匙

&kwargs
参数将包含 0 个或多个关键字参数。

以下代码示例定义了一个将打印所有关键字的函数
参数及其值。

=> (defn 打印参数 [&kwargs kwargs]
... (for [(, kv) (.items kwargs)] (print kv)))

=>(应用打印参数 [] {"parameter-1" 1 "parameter-2" 2})
参数-2 2
参数-1 1

&休息 参数将包含 0 个或多个位置参数。 没有其他位置
可以在此之后指定参数。

下面的代码示例定义了一个可以给定 0 到 n 数字的函数
参数。 然后它对每个奇数求和并减去每个偶数。

=> (defn zig-zag-sum [&rest numbers]
(让 [[奇数 (list-comp x [x 数] (奇数?x))]
[偶数 (list-comp x [x numbers] (even? x))]]
(- (和奇数) (和偶数))))

=>(之字形总和)
0
=>(锯齿形总和 3 9 4)
8
=>(锯齿形总和 1 2 3 4 5 6)
-3

定义别名 / defun-别名
版本0.10.0中的新功能。

定义别名defun-别名 宏很像 定义,区别在于
除了定义具有单一名称的函数之外,它们还可以定义别名。 其他
而不是将函数名称的符号列表作为第一个参数, 定义别名
defun-别名定义得不偿失.

=> (defn-alias [main-name alias] []
...(打印“你好!”))
=>(主要名称)
“你好!”
=>(别名)
“你好!”

定义域
版本0.10.1中的新功能。

定义域 宏定义了一个立即调用的主函数 系统参数文件 as
参数当且仅当此文件作为脚本执行时。 换句话说,这:

(定义 [&rest args]
(用 args 做某事))

相当于:

定义主(* args):
do_something_with(参数)
返回0

如果 __name__ == "__main__":
导入系统
retval = main(*sys.arg)

如果 isinstance(retval, int):
系统退出(retval)

请注意,正如您在上面看到的,如果您从此函数返回一个整数,这将是
用作脚本的退出状态。 (Python 默认退出状态 0 否则,
这意味着一切都好!)

(自从 (系统。退出 0) 在非整数返回的情况下不显式运行
定义域,这是一个好主意 (定义) 作为文件中的最后一段代码。)

定义宏
定义宏 用于定义宏。 一般格式是 (定义宏 姓名 [参数]
表达式).

以下示例定义了一个可用于交换代码中元素顺序的宏,
允许用户以中缀表示法编写代码,其中运算符位于
操作数。

=> (defmacro 中缀 [代码]
...(拟引号 (
...(取消引用(获取代码 1))
...(取消引用(获取代码 0))
...(取消引用(获取代码 2)))))

=> (中缀 (1 + 1))
2

定义宏别名
定义宏别名 用于定义具有多个名称(别名)的宏。 一般格式
is (定义宏别名 [姓名] [参数] 表达式). 它创建了多个相同的宏
参数列表和正文,在指定的名称列表下。

下面的例子定义了两个宏,这两个宏都允许用户在
中缀符号。

=> (defmacro-alias [infix infi] [code]
...(拟引号 (
...(取消引用(获取代码 1))
...(取消引用(获取代码 0))
...(取消引用(获取代码 2)))))

=> (中缀 (1 + 1))
2
=> (infi (1 + 1))
2

定义宏/克!
版本0.9.12中的新功能。

定义宏/克! 是一个特殊版本 定义宏 用于自动生成 基因符号
对于任何以 g!.

例如, 啊! 会成为 (基因符号 “一种”).

SEE 另外:
部分使用-gensym

解读器
版本0.9.12中的新功能。

解读器 定义了一个阅读器宏,使您能够重组或修改语法。

=> (defreader ^ [expr] (打印 expr))
=> #^(1 2 3 4)
(1 2 3 4)
=> #^“你好”
“你好”

SEE 另外:
部分阅读器宏


版本0.9.12中的新功能。

从当前命名空间中删除一个对象。

=> (setv foo 42)
=> (del foo)
=> 富
追溯(最近一次通话):
文件 ” ",第 1 行,在
NameError: 名称 'foo' 未定义

还可以从映射、列表等中删除对象。

=>(setv 测试(列表(范围 10)))
=> 测试
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
=> (del (切片测试 2 4)) ;; 从排除的 2 到 4 项中删除项目
=> 测试
[0、1、4、5、6、7、8、9]
=> (setv dic {"foo" "bar"})
=> 迪克
{"foo": "bar"}
=> (del (get dic "foo"))
=> 迪克
{}

多多
版本0.10.1中的新功能。

多多 用于简化对对象的方法调用序列。

=> (doto [] (.append 1) (.append 2) .reverse)
[2 1]

=> (setv 集合 [])
=> (.append 集合 1)
=> (.append 集合 2)
=>(.反向收集)
=> 集合
[2 1]

评估
评估 计算一个带引号的表达式并返回值。

=> (eval '(打印“你好世界”))
“你好,世界”

评估和编译
编译时评估
第一 / 汽车
第一汽车 是用于访问集合的第一个元素的宏:

=>(第一个(范围 10))
0


用于为列表或向量中的每个元素调用一个函数。 每个的结果
呼叫被丢弃并且 表达式返回 不包含 反而。 示例代码迭代
超过 采集 并且对于每个 element in 采集 呼叫 副作用
element 作为其论点:

;; 假设(副作用)是一个接受单个参数的函数
(对于[元素集合](副作用元素))

;; for 可以有一个可选的 else 块
(对于[元素集合](副作用元素)
(否则(副作用2)))

可选的 其他 块只有在 循环正常终止。 如果
执行被暂停 打破是, 其他 块不执行。

=> (for [元素 [1 2 3]] (if (< element 3)
...(打印元素)
... (休息))
...(否则(打印“循环完成”)))
1
2

=> (for [元素 [1 2 3]] (if (< element 4)
...(打印元素)
... (休息))
...(否则(打印“循环完成”)))
1
2
3
循环完成

基因表达
基因表达 用于创建生成器表达式。 它需要两个或三个参数。 这
第一个参数是控制返回值的表达式,而第二个参数被使用
从列表中选择项目。 第三个可选参数可用于过滤掉
列表中的某些项目基于条件表达式。 基因表达 类似于
列表组合,除了它返回一个一个一个一个地计算值而不是一个迭代
立即评估它们。

=>(定义集合(范围 10))
=> (def 过滤 (genexpr x [x 集合] (even? x)))
=>(列表过滤)
[0、2、4、6、8]

基因符号
版本0.9.12中的新功能。

基因符号 用于生成一个唯一的符号,允许在不使用宏的情况下编写宏
意外的变量名冲突。

=> (gensym)
你':G_1235'

=> (gensym "x")
你':x_1236'

SEE 另外:
部分使用-gensym

得到
得到 用于访问列表和字典中的单个元素。 得到 需要两个参数:
data 结构体指数 or 项的。 然后它会返回相应的
字典或列表中的值。 用法示例:

=> (让 [[动物{“狗”“吠”“猫”“喵”}]
... [数字[“零”“一”“二”“三”]]]
...(打印(获取动物“狗”))
...(打印(得到数字 2)))
树皮


注意:
得到 如果为不存在的键查询字典,则引发 KeyError。

注意:
得到 如果查询列表或元组的索引超出范围,则引发 IndexError
界限。

全球化
全球化 可用于将符号标记为全局。 这允许程序员分配一个
值到全局符号。 读取全局符号不需要 全球化 关键词——
只有分配它。

以下示例显示了全局符号如何 a 在函数中被赋值并且
稍后打印在另一个函数中。 没有 全球化 关键字,第二个函数
会抛出一个 名称错误.

(defn set-a [值]
(全局一个)
(设置一个值))

(定义打印-a []
(打印一个))

(设置-a 5)
(打印-a)

if / 如果不
0.10.0 版的新功能:if-not

if 用于有条件地选择要执行的代码。 它必须包含一个条件
块和要执行的块,如果条件块评估为 . 可选,
它可能包含一个最终块,在条件的评估为
.

如果不 类似,但是当条件失败时会执行第二个块,而
当测试成功时执行第三个也是最后一个块 - 的相反顺序 if.

用法示例:

(如果(剩下的钱?帐户)
(打印“我们去购物吧”)
(打印“让我们去工作吧”))

(如果不是(剩下的钱?帐户)
(打印“让我们去工作吧”)
(打印“我们去购物吧”))

Python 的真实性受到尊重。 不包含, ,任何数字类型的零,空序列,
一个空字典被认为是 ; 其他一切都被考虑 .

口齿不清 / LIF 口齿不清 / 如果不是
版本0.10.0中的新功能。

0.10.2 版中的新功能:lisp-if-not / lif-not

对于那些更喜欢 Lispy 的人 if 条款,我们有 口齿不清LIF。 这 仅由 考虑
不包含 / 是假的! 所有其他“假的”Python 值都被认为是真的。
相反,我们有 口齿不清如果不是 平行于 if如果不 哪个反转
比较。

=> (lisp-if True "true" "false")
“真正”
=> (lisp-if False "true" "false")
“真正”
=> (lisp-if 0 "true" "false")
“真正”
=> (lisp-if nil "true" "false")
“错误的”
=> (lisp-if None "true" "false")
“错误的”
=> (lisp-if-not nil "true" "false")
“真正”
=> (lisp-if-not None "true" "false")
“真正”
=> (lisp-if-not False "true" "false")
“错误的”

; 等效但更短
=>(如果真“真”“假”)
“真正”
=> (lif nil "true" "false")
“错误的”
=> (lif-not None "true" "false")
“真正”

进口
进口 用于导入模块,就像在 Python 中一样。 有几种方法可以 进口 能够
使用。

;; 导入这些模块中的每一个
;;
;; Python:
;; 导入系统
;; 导入 os.path
(导入 sys os.path)

;; 从模块导入
;;
;; Python:从 os.path 导入存在,isdir,isfile
(导入 [os.path [exists isdir isfile]])

;; 使用别名导入
;;
;; Python:将 sys 导入为 systest
(导入 [sys :as systest])

;; 您可以列出任意数量的不同类型的导入。
(导入 [tests.resources [kwtest function-with-a-dash]]
[os.path [存在 isdir isfile]]
[系统:作为系统测试])

;; 将所有模块函数导入当前命名空间
(导入 [系统 [*]])

拉姆达 / fn
拉姆达fn 可用于定义匿名函数。 参数类似于
定义: 第一个参数是参数向量,其余是参数的主体
功能。 拉姆达 返回一个新函数。 在以下示例中,匿名函数
被定义并传递给另一个函数来过滤输出。

=> (def people [{:name "Alice" :age 20}
... {:name "Bob" :age 25}
... {:name "Charlie" :age 50}
... {:name "Dave" :age 5}])

=> (defn display-people [人员过滤器]
...(对于 [person people](if(filter person)(print(:name person)))))

=> (display-people people (fn [person] (< (:age person) 25)))
爱丽丝
戴夫

就像在普通函数定义中一样,如果主体的第一个元素是字符串,则它
作为文档字符串。 这对于提供类方法文档字符串很有用。

=> (setv 乘以三
...(fn [x]
...“将输入乘以三并返回结果。”
... (* x 3)))

这可以通过 Python 的内置功能来确认 帮助 功能:

=>(帮助时间-三)
关于函数 times_three 的帮助:

次_三(x)
将输入乘以三并返回结果
(结束)

最后
版本0.10.2中的新功能。

最后 可用于访问集合的最后一个元素:

=> (最后 [2 4 6])
6


用于创建词法范围的变量。 它们是在开始时创建的
形式并在形式之后不复存在。 下面的例子展示了这一点
行为:

=> (让 [[x 5]] (打印 x)
... (让 [[x 6]] (打印 x))
...(打印 x))
5
6
5

宏有两个参数:一个定义向量 变量身体 得到
被执行。 变量 是一个向量,其中每个元素是单个变量或向量
定义一个变量值对。 在单个变量的情况下,它被赋值
不包含; 否则,使用提供的值。

=> (让 [x [y 5]] (打印 xy))
无5

列表组合
列表组合 执行列表理解。 它需要两个或三个参数。 首先
参数是控制返回值的表达式,而第二个用于
从列表中选择项目。 第三个可选参数可用于过滤掉一些
基于条件表达式的列表中的项目。 一些例子:

=>(定义集合(范围 10))
=> (list-comp x [x 集合])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

=> (list-comp (* x 2) [x 集合])
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

=> (list-comp (* x 2) [x 集合] (< x 5))
[0、2、4、6、8]

不能
不能 用于逻辑表达式。 它接受一个参数并返回一个反向
真值。 如果 作为参数给出, 将被退回,反之亦然。
用法示例:

=>(不是真的)


=>(不是假的)


=>(不是无)


or
or 用于逻辑表达式。 它至少需要两个参数。 它将返回
第一个非假参数。 如果不存在这样的值,则返回最后一个参数。

=>(或真假)


=>(和假假)


=>(和假1真假)
1

注意:
or 一旦第一个真值出现,短路并停止评估参数
遭遇。

=>(或 True(打印“你好”))


打印
打印 用于在屏幕上输出。 用法示例:

(打印“你好世界!”)

注意:
打印 总是回来 不包含.

准报价
准报价 允许您引用表单,但也可以有选择地评估表达式。
里面的表达式 准报价 可以有选择地评估使用 引文结束 (~)。 该
评估形式也可以拼接使用 取消引用拼接 (~@)。 Quasiquote 也可以
使用反引号 (`) 象征。

;; 让 `qux' 成为一个有值的变量 (bar baz)
`(foo ~qux)
; 相当于 '(foo (bar baz))
`(foo ~@qux)
; 相当于 '(foo bar baz)

报价
报价 返回传递给它的表单而不对其进行评估。 报价 也可以是
使用撇号 (') 象征。

=> (setv x '(打印“Hello World”))
; 变量 x 设置为表达式且未计算
=> x
(你'打印'你'你好世界')
=> (评估 x)
你好世界

要求
要求 用于从给定模块导入宏。 它至少需要一个参数
指定应导入哪些宏的模块。 可以导入多个模块
与一个 要求.

以下示例将从中导入宏 模块一模块一:

(需要模块 1 模块 2)

其余 / CDR
其余CDR 返回作为参数传递的集合,没有第一个元素:

=>(休息(范围10))
[1、2、3、4、5、6、7、8、9]

设置组合
设置组合 用于创建集合。 它需要两个或三个参数。 第一个参数是
用于控制返回值,而第二个用于从
序列。 第三个和可选参数可用于过滤掉某些项目
基于条件表达式的序列。

=> (setv 数据 [1 2 3 4 5 2 3 4 5 3 4 5])
=> (set-comp x [x 数据] (奇数?x))
{1,3,5}


可用于获取列表的子集并从中创建新列表。 表格
至少需要一个参数来指定要切片的列表。 两个可选参数可以是
用于给出子集的开始和结束位置。 如果不提供,则
默认值 不包含 将被使用。 第三个可选参数用于
元素之间的控制步骤。

遵循与其 Python 对应项相同的规则。 负指数被计算在内
从列表的末尾开始。 一些示例用法:

=>(定义集合(范围 10))

=>(切片集合)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

=>(切片集合 5)
[5、6、7、8、9]

=>(切片集合 2 8)
[2、3、4、5、6、7]

=>(切片集合 2 8 2)
[2,4,6]

=>(切片集合 -4 -2)
[6 7]

/ 提高
or 提高 表格可用于提高 特殊课程 在运行时。 用法示例:

(扔)
; 重新引发最后一个异常

(抛出 IOError)
; 抛出一个 IOError

(抛出(IOError“foobar”))
; 抛出一个 IOError("foobar")

可以接受单个参数(一个 特殊课程 类或实例)或没有参数
重新加注最后一个 特殊课程.

尝试
尝试 表单用于启动一个 尝试 / 捕捉 堵塞。 该表格的用法如下:

(试试
(容易出错的功能)
(catch [e ZeroDivisionError] (打印“被零除”))
(否则(打印“没有错误”))
(最后(打印“全部完成”)))

尝试 必须至少包含一个 捕捉 块,并且可以选择包含一个 其他 or 最后
堵塞。 如果在执行期间使用匹配的 catch 块引发错误
容易出错的功能,这 捕捉 块将被执行。 如果没有出现错误,则 其他
块被执行。 这 最后 块将最后执行,无论是否
错误被提出。

除非
除非 宏是写一个的简写 if 检查是否给定的语句
有条件的是 . 下面展示了这个宏的扩展。

(除非有条件语句)

(如果有条件
不包含
(做声明))

引文结束
在一个quasiquoted形式中, 引文结束 强制对符号进行评估。 引文结束 别名为
波浪号 (~) 象征。

(定义名称“拥抱”)
(准引号 (= name (unquote name)))
;=> (u'=' u'name' u'Cuddles')

`(=名字~名字)
;=> (u'=' u'name' u'Cuddles')

取消引用拼接
取消引用拼接 强制对拟引用形式中的符号进行评估,很像
引文结束. 取消引用拼接 仅当未加引号的符号包含
可迭代值,因为它将可迭代值“拼接”为准引用形式。 取消引用拼接 is
别名为 ~@ 符号。

(定义数字 [1 2 3 4])
(准引号 (+ (unquote-splice nums)))
;=> (u'+' 1L 2L 3L 4L)

`(+ ~@nums)
;=> (u'+' 1L 2L 3L 4L)

,尤其是
,尤其是 类似于 除非, 除非它在给定的条件是 。 它不是
可能有一个 其他 阻止一个 ,尤其是 宏。 下图显示了扩展
宏。

(当条件语句时)

(如果有条件(do 语句))


用于只要满足条件就执行一个或多个块。 下列
示例将输出“Hello world!” 无限期地显示在屏幕上:

(而 True(打印“Hello world!”))


用于在上下文管理器中包装块的执行。 上下文
然后,管理员可以设置本地系统并以受控方式将其拆除。 这
使用的原型示例 是在处理文件时。 可以将上下文绑定到
参数或完全忽略它,如下所示:

(使用 [[arg (expr)]] 块)

(带有 [[(expr)]] 块)

(使用 [[arg (expr)] [(expr)]] 块)

下面的例子将打开 新闻中心 文件并将其内容打印到屏幕上。 这
文件处理完毕后自动关闭。

(用 [[f (open "NEWS")]] (print (.read f)))

带装饰器
带装饰器 用于将一个函数与另一个函数包装在一起。 函数执行
装饰应该接受单个值:被装饰的函数,并返回一个新的
功能。 带装饰器 最少需要两个参数:函数执行
装饰和被装饰的功能。 可以有多个装饰器功能
已申请; 它们将按从最外到最内的顺序应用,即。 首先
装饰器将是最外面的,依此类推。 带参数的装饰器被称为 just
就像一个函数调用。

(with-decoratordecorator-fun
(定义一些函数 [] ...)

(with-decoratordecorator1 decorator2 ...
(定义一些函数 [] ...)

(带有装饰器(装饰器arg)..
(定义一些函数 [] ...)

在下面的例子中, inc-装饰器 用于装饰函数 增加
接受两个参数并使用值调用修饰函数的函数
加1。当装饰 增加 用值 1 和 1 调用,结束
结果将是 4 (1 1 + + 1 1 +).

=> (defn inc-decorator [func]
... (fn [值-1 值-2] (func (+ 值-1 1) (+ 值-2 1))))
=> (defn inc2-decorator [func]
... (fn [值-1 值-2] (func (+ 值-1 2) (+ 值-2 2))))

=> (with-decorator inc-decorator (defn加法[ab] (+ ab)))
=>(加1 1)
4
=> (with-decorator inc2-decorator inc-decorator
... (定义加法 [ab] (+ ab)))
=>(加1 1)
8

with-gensyms
版本0.9.12中的新功能。

with-gensym 用于生成一组 基因符号 用于宏。 以下代码:

(with-gensyms [abc]
...)

扩展为:

(让 [[a (gensym)
[b(gensym)
[c(gensym)]]
...)

SEE 另外:
部分使用-gensym

产量
产量 用于创建返回一个或多个值的生成器对象。 发电机
是可迭代的,因此可用于循环、列表推导式和其他类似的
结构体。

该功能 随机数 展示了如何使用生成器来生成无限级数
而不消耗无限量的内存。

=>(定义乘[基系数]
...(对于 [[(,基系数)(zip 基系数)]]
...(产量(*基系数))))

=>(乘以(范围5)(范围5))


=> (list-comp value [value (multiply (range 10) (range 10))])
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

=>(随机导入)
=>(定义随机数[低高]
...(而 True(产量(.randint 随机低高))))
=> (list-comp x [x (取 15 (随机数 1 50))])])
[7、41、6、22、32、17、5、38、18、38、17、14、23、23、19]

收益率
版本0.9.13中的新功能。

蟒蛇 3.3 AND UP 只!

收益率 用于调用子生成器。 如果你想让你的协程
能够将其进程委托给另一个协程,例如,如果使用类似的东西
异步.

Hy 核心
核心 主要工作内容
但最后
用法: (但最后 科尔)

返回除最后一项之外的所有项目的迭代器 科尔.

=> (list (butlast (range 10)))
[0、1、2、3、4、5、6、7、8]

=>(列表(但最后 [1]))
[]

=>(列表(但最后 []))
[]

=>(导入迭代工具)
=> (list (take 5 (butlast (itertools.count 10))))
[10、11、12、13、14]

科尔?
版本0.10.0中的新功能。

用法: (科尔? x)

退货政策 if x 是可迭代的,而不是字符串。

=>(科尔?[1 2 3 4])


=> (coll? {"a" 1 "b" 2})


=>(科尔?“abc”)


缺点
版本0.10.0中的新功能。

用法: (缺点 a b)

用汽车返回一个新的 cons 单元格 a 和CDR b.

=> (setv a (cons 'hd 'tl))

=> (= '高清(车一))


=> (= 'tl (cdr a))


缺点?
版本0.10.0中的新功能。

用法: (缺点? 富)

检查是否 FOO 是一个缺点细胞。

=> (setv a (cons 'hd 'tl))

=>(缺点?一)


=>(缺点?零)


=>(缺点?[1 2 3])


十二月
用法: (十二月 x)

返回一个小于 x. 相当于 (- x 1). 加注 类型错误 if (不是 (数字? X)).

=>(3 月 XNUMX 日)
2

=>(0 月 XNUMX 日)
-1

=>(12.3 月 XNUMX 日)
11.3

拆卸
版本0.10.0中的新功能。

用法: (拆卸 &可选的 [代码生成器 错误的])

转储给定 Hy 的 Python AST 到标准输出。 如果 代码生成器 is , 功能
而是打印 Python 代码。

=>(反汇编'(打印“Hello World!”))
模块(
身体=[
Expr(value=Call(func=Name(id='print'), args=[Str(s='Hello World!')], 关键字=[], starargs=None, kwargs=None))])

=> (反汇编 '(print "Hello World!") true)
打印('你好世界!')

空的?
用法: (空的? 科尔)

退货政策 if 科尔 是空的。 相当于 (= 0 (连 科尔)).

=>(空?[])


=>(空?“”)


=> (空?(, 1 2))


每一个?
版本0.10.0中的新功能。

用法: (每一个? 预计值 科尔)

退货政策 if (预 x) 对每一个都是合乎逻辑的 x in 科尔, 除此以外 。 返回
if 科尔 是空的。

=>(每个?甚至?[2 4 6])


=>(每个?甚至?[1 3 5])


=>(每个?甚至?[2 4 5])


=>(每个?甚至?[])


漂浮?
用法: (漂浮? x)

退货政策 if x 是一个浮点数。

=>(浮动?3.2)


=>(浮动?-2)


甚至?
用法: (甚至? x)

退货政策 if x 甚至。 加注 类型错误 if (不是 (数字? X)).

=>(甚至?2)


=>(甚至?13)


=>(甚至?0)


身分
用法: (身份 x)

返回提供给函数的参数。

=>(身份4)
4

=>(列表(地图标识 [1 2 3 4]))
[1 2 3 4]

公司
用法: (包括 x)

返回一个多于 x. 相当于 (+ x 1). 加注 类型错误 if (不是 (数字? X)).

=> (包括 3)
4

=> (包括 0)
1

=> (包括 12.3)
13.3

实例?
用法: (实例? x)

退货政策 if x 是一个实例 .

=>(例如?浮动 1.0)


=>(例如?int 7)


=>(例如?str(str“foo”))


=> (defclass TestClass [对象])
=> (setv inst (TestClass))
=>(例如?TestClass 实例)


整数?
用法: (整数? x)

退货政策 if x 是一个整数。 对于 Python 2,这是 INT or . 对于 Python 3,
这是 INT.

=>(整数?3)


=>(整数?-2.4)


交错
版本0.10.1中的新功能。

用法: (交错 序列1 序列2 ...)

返回每个序列中第一个项目的迭代,然后是第二个,依此类推。

=> (list (interleave (range 5) (range 100 105)))
[0, 100, 1, 101, 2, 102, 3, 103, 4, 104]

=> (list (interleave (range 1000000) "abc"))
[0, 'a', 1, 'b', 2, 'c']

插入
版本0.10.1中的新功能。

用法: (设置 项目 序列)

返回由项目分隔的序列元素的可迭代对象。

=>(列表(插入“!”“abcd”))
['A B C D']

=>(列表(插入-1(范围5)))
[0、-1、1、-1、2、-1、3、-1、4]

可迭代?
用法: (可迭代? x)

退货政策 if x 是可迭代的。 可迭代对象在以下情况下返回一个新的迭代器 (迭代器 x) is
叫。 对比 迭代器?.

=>;; 适用于字符串
=>(可迭代?(str“abcde”))


=>;; 适用于列表
=>(可迭代?[1 2 3 4 5])


=>;; 适用于元组
=>(可迭代?(,1 2 3))


=>;; 适用于 dicts
=>(可迭代?{:a 1 :b 2 :c 3})


=>;; 适用于迭代器/生成器
=>(可迭代?(重复 3))


迭代器?
用法: (迭代器? x)

退货政策 if x 是一个迭代器。 迭代器是将自身作为一个对象返回的对象
迭代器当 (迭代器 x) 叫做。 对比 可迭代?.

=>;; 不适用于列表
=>(迭代器?[1 2 3 4 5])


=>;; 但是我们可以从列表中得到一个迭代器
=>(迭代器?(迭代器 [1 2 3 4 5]))


=>;; 不适用于 dict
=>(迭代器?{:a 1 :b 2 :c 3})


=>;; 从字典创建迭代器
=> (迭代器?(iter {:a 1 :b 2 :c 3}))


列表*
用法: (列表* &休息 尾巴)

生成包含参数的嵌套 cons 单元链(点列表)。 如果
参数列表只有一个元素,返回它。

=> (列表* 1 2 3 4)
(1 2 3 . 4)

=> (列表* 1 2 3 [4])
[1,2,3,4]

=>(列表* 1)
1

=>(缺点?(列表* 1 2 3 4))


宏展开
版本0.10.0中的新功能。

用法: (宏展开 形成)

返回完整的宏展开 申请.

=> (宏展开'(-> (ab) (xy)))
(u'x' (u'a' u'b') u'y')

=> (宏展开'(-> (ab) (-> (cd) (ef))))
(u'e' (u'c' (u'a' u'b') u'd') u'f')

宏展开-1
版本0.10.0中的新功能。

用法: (宏展开-1 形成)

返回单步宏展开 申请.

=> (macroexpand-1 '(-> (ab) (-> (cd) (ef))))
(u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f'))

合并
版本0.10.1中的新功能。

用法: (合并 f &休息 地图)

返回一个地图,该地图由首先加入的其余地图组成。 如果一个键出现在
多张地图,来自后者(从左到右)的映射将与
通过调用结果中的映射 (f 结果验证 val-in-later).

=> (merge-with (fn [xy] (+ xy)) {"a" 10 "b" 20} {"a" 1 "c" 30})
{u'a':11L,u'c':30L,u'b':20L}

否定?
用法: (否定? x)

退货政策 if x 小于零。 加注 类型错误 if (不是 (数字? X)).

=>(否定?-2)


=>(否定?3)


=>(否定?0)


零?
用法: (零? x)

退货政策 if x is / 不包含.

=>(零?零)


=>(无?无)


=>(零?0)


=> (setf x nil)
=>(零?x)


=>;; list.append 总是返回 None
=> (nil? (.append [1 2 3] 4))


没有任何?
用法: (没有任何? x)

退货政策 if x is 不包含.

=>(没有?没有)


=>(没有?0)


=> (setf x None)
=>(没有?x)


=>;; list.append 总是返回 None
=> (无?(.append [1 2 3] 4))


第n
用法: (第n 科尔 n &可选的 [默认 零])

返回 n- 集合中的第 - 项,从 0 开始计数。返回默认值, 如果
越界(除非另有说明)。 加注 值错误 if n 是负面的。

=> (第 [1 2 4 7] 1)
2

=> (第 [1 2 4 7] 3)
7

=> (nil? (nth [1 2 4 7] 5))


=> (nth [1 2 4 7] 5 "默认")
'默认'

=> (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))
5

=> (第n [1 2 4 7] -1)
追溯(最近一次通话):
...
ValueError:islice() 的索引必须为 None 或整数:0 <= x <= sys.maxsize。

数字?
用法: (数字? x)

退货政策 if x 是一个数字,如 Python 中定义的 数字.数字 类。

=>(数字?-2)


=>(数字?3.2)


=>(数字?“foo”)


奇怪的?
用法: (奇怪的? x)

退货政策 if x 很奇怪。 加注 类型错误 if (不是 (数字? X)).

=>(奇数?13)


=>(奇数?2)


=>(奇数?0)


位置?
用法: (位置? x)

退货政策 if x 大于零。 加注 类型错误 if (不是 (数字? X)).

=>(位置?3)


=>(位置?-2)


=>(位置?0)


第二
用法: (第二 科尔)

返回第二个成员 科尔. 相当于 (得到 科尔 1).

=> (第二个 [0 1 2])
1

一些
版本0.10.0中的新功能。

用法: (一些 预计值 科尔)

返回第一个逻辑真值 (预 x) 对于任何 x in 科尔, 除此以外 .
退货 if 科尔 是空的。

=>(有些甚至?[2 4 6])


=>(无?(有些甚至?[1 3 5]))


=> (nil? (some identity [0 "" []]))


=>(某些身份[0“非空字符串”[]])
'非空字符串'

=>(零?(有些甚至?[]))


细绳?
用法: (细绳? x)

退货政策 if x 是一个字符串。

=>(字符串?“foo”)


=>(字符串?-2)


象征?
用法: (象征? x)

退货政策 if x 是一个符号。

=>(符号?'foo)


=>(符号?'[abc])


零?
用法: (零? x)

退货政策 if x 是零。

=>(零?3)


=>(零?-2)


=>(零?0)


序列 主要工作内容
序列函数可以创建或操作一个潜在的无限序列,而无需
需要在列表或类似容器中完全实现序列。 他们这样做
返回一个 Python 迭代器。

我们可以使用规范的无限斐波那契数生成器作为如何使用的示例
其中一些功能。

(定义纤维 []
(设置为 0)
(setv b 1)
(虽然是真的
(产量一)
(setv (, ab) (, b (+ ab)))))

注意 (尽管 true ...) 环形。 如果我们在 REPL 中运行它,

=> (fib)


调用该函数只返回一个迭代器,但在我们使用它之前不起作用。
不建议尝试这样的事情,因为无限循环将一直运行直到它
消耗所有可用的 RAM,或者在这种情况下,直到我杀死它。

=>(列表(fib))
[1] 91474 杀死hy

要获得前 10 个斐波那契数,请使用 采取。 注意 采取 还返回一个生成器,
所以我从中创建了一个列表。

=>(列表(取10(fib)))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

要获得索引 9 处的斐波那契数,(从 0 开始):

=> (nth (fib) 9)
34

周期
用法: (循环 科尔)

返回 coll 成员的无限迭代器。

=>(列表(取7(循环[1 2 3])))
[1,2,3,1,2,3,1]

=>(列表(取2(循环[1 2 3])))
[1 2]

不同
用法: (清楚的 科尔)

返回一个只包含唯一成员的迭代器 科尔.

=>(列表(不同的 [ 1 2 3 4 3 5 2 ]))
[1、2、3、4、5]

=>(列表(不同的 []))
[]

=> (list (distinct (iter [ 1 2 3 4 3 5 2 ])))
[1、2、3、4、5]

下降
用法: (降低 n 科尔)

返回一个迭代器,跳过第一个 n 成员 科尔. 加注 值错误 if n is
负。

=>(列表(删除 2 [1 2 3 4 5]))
[3,4,5]

=>(列表(删除 4 [1 2 3 4 5]))
[5]

=>(列表(删除 0 [1 2 3 4 5]))
[1、2、3、4、5]

=>(列表(删除 6 [1 2 3 4 5]))
[]

最后一个
用法: (最后一个 n 科尔)

返回除最后一个之外的所有迭代器 n 项目在 科尔. 加注 值错误 if n is
负。

=> (list (drop-last 5 (range 10 20)))
[10、11、12、13、14]

=>(列表(最后一个 0(范围 5)))
[0、1、2、3、4]

=>(列表(最后一个 100(范围 100)))
[]

=>(导入迭代工具)
=> (list (take 5 (drop-last 100 (itertools.count 10))))
[10、11、12、13、14]

暂时放下
用法: (放下时 预计值 科尔)

返回一个迭代器,跳过成员 科尔 直到 预计值 is .

=>(列表(甚至下降?[2 4 7 8 9]))
[7,8,9]

=> (list (drop-while numeric? [1 2 3 None "a"])))
[没有,你']

=> (list (drop-while pos? [2 4 7 8 9]))
[]

过滤
用法: (筛选 预计值 科尔)

返回所有项目的迭代器 科尔 通过谓词的 预计值.

参见 去掉.

=>(列表(过滤器位置?[1 2 3 -4 5 -7]))
[1,2,3,5]

=>(列表(过滤偶数?[1 2 3 -4 5 -7]))
[2,-4]

展平
版本0.9.12中的新功能。

用法: (压平 科尔)

返回所有项目的单个列表 科尔,通过展平所有包含的列表和/或
元组。

=>(压平 [1 2 [3 4] 5])
[1、2、3、4、5]

=> (展平 ["foo" (, 1 2) [1 [2 3] 4] "bar"])
['foo', 1, 2, 1, 2, 3, 4, 'bar']

重复
用法: (迭代 fn x)

返回一个迭代器 x, fn(x), fn(fn(x))等等。

=> (list (take 5 (iterate inc 5)))
[5、6、7、8、9]

=> (list (take 5 (iterate (fn [x] (* xx)) 5)))
[5、25、625、390625、152587890625]


用法: (读 &可选的 [从文件 埃夫])

从中读取下一个 Hy 表达式 从文件 (默认为 系统标准输入),并且可以取
单字节作为 EOF(默认为空字符串)。 加注 EOF错误 if 从文件 结束前
可以解析完整的表达式。

=>(阅读)
(+ 2 2)
('+' 2 2)
=>(评估(读取))
(+ 2 2)
4

=>(导入io)
=> (def 缓冲区 (io.StringIO "(+ 2 2)\n(- 2 1)"))
=> (eval (apply read [] {"from_file" buffer}))
4
=> (eval (apply read [] {"from_file" buffer}))
1

=>; 假设“example.hy”包含:
=>; (打印“你好”)
=>; (打印“hyfriends!”)
=>(使用 [[f(打开“example.hy”)]]
... (尝试
...(虽然是真的
...(让[[exp(读f)]]
... (做
...(打印“OHY”exp)
... (eval exp)))))
...(抓住 [e EOFError]
...(打印“EOF!”))))
OHY('打印''你好')
hello
OHY('打印''hyfriends!')
朋友们!
EOF!

去掉
用法: (消除 预计值 科尔)

返回一个迭代器 科尔 带有通过谓词的元素, 预计值,删除。

参见 过滤.

=>(列表(删除奇数?[1 2 3 4 5 6 7]))
[2,4,6]

=>(列表(删除位置?[1 2 3 4 5 6 7]))
[]

=>(列表(删除否定?[1 2 3 4 5 6 7]))
[1,2,3,4,5,6,7]

重复
用法: (重复 x)

返回一个迭代器(无限) x.

=>(列表(取6(重复“s”)))
[你的',你的',你的',你的',你的',你的']

反复
用法: (反复 fn)

通过调用返回迭代器 fn 反复。

=>(导入 [随机 [randint]])

=> (列表 (取 5 (反复 (fn [] (randint 0 10)))))
[6、2、0、6、7]

采取
用法: (拿 n 科尔)

返回包含第一个的迭代器 n 成员 科尔. 加注 值错误 if n is
负。

=>(列表(取 3 [1 2 3 4 5]))
[1,2,3]

=>(列表(取4(重复“s”)))
[你的,你的,你的,你的]

=>(列表(取0(重复“s”)))
[]

第n次
用法: (取第 n 个 n 科尔)

返回一个包含每个的迭代器 n-第一个成员 科尔.

=>(列表(取第 n 个 2 [1 2 3 4 5 6 7]))
[1,3,5,7]

=>(列表(取第 n 个 3 [1 2 3 4 5 6 7]))
[1,4,7]

=>(列表(取第 n 个 4 [1 2 3 4 5 6 7]))
[1 5]

=>(列表(取第 n 个 10 [1 2 3 4 5 6 7]))
[1]

暂时
用法: (暂时 预计值 科尔)

返回一个迭代器 科尔 只要 预计值 回报 .

=> (list (take-while pos? [ 1 2 3 -4 5]))
[1,2,3]

=> (list (take-while neg? [ -4 -3 1 2 5]))
[-4,-3]

=> (list (take-while neg? [ 1 2 3 -4 5]))
[]

拉链
版本0.9.13中的新功能。

用法: (带拉链的 fn 科尔 ...)

相当于 拉链,但使用多参数函数而不是创建元组。 如果
拉链 用 N 个集合调用,然后 fn 必须接受 N 个参数。

=>(导入运算符)
=> (list (zipwith operator.add [1 2 3] [4 5 6]))
[5,7,9]

读者
Reader 宏赋予 Lisp 动态修改和改变语法的能力。 你不想
波兰符号? 阅读器宏可以轻松做到这一点。 想要 Clojure 的方式
正则表达式? 阅读器宏也可以轻松做到这一点。

句法
=> (defreader ^ [expr] (打印 expr))
=> #^(1 2 3 4)
(1 2 3 4)
=> #^“你好”
“你好”
=> #^1+2+3+4+3+2
1+2+3+4+3+2

Hy 没有元组的文字。 让我们说你不喜欢 (, ...) 并且想要别的东西。 这
是阅读器宏能够以简洁的方式解决的问题。

=> (defreader t [expr] `(, ~@expr))
=> #t(1 2 3)
(1,2,3)

您甚至可以像 Clojure 那样做,并为正则表达式添加文字!

=>(重新导入)
=> (defreader r [expr] `(re.compile ~expr))
=> #r".*"
<_sre.SRE_Pattern 对象在 0xcv7713ph15#>

SAP系统集成计划实施
解读器 将单个字符作为读取器宏的符号名称; 任何更长的时间
将返回错误。 实施方面, 解读器 扩展为一个 lambda 覆盖
装饰者。 这个装饰器将 lambda 保存在一个字典中,并带有它的模块名称和
符号。

=> (defreader ^ [expr] (打印 expr))
;=> (with_decorator (hy.macros.reader ^) (fn [expr] (print expr)))

# 扩展为 (dispatch_reader_macro ...) 符号和表达式被传递到
正确的功能。

=> #^()
;=> (dispatch_reader_macro ^ ())
=> #^“你好”
“你好”

警告:
由于 Hy 的词法分析器和解析器的限制,读取器宏无法重新定义已定义
语法如 ()[]{}. 这很可能在未来得到解决。

内部 Hy 配套文档
注意:
这些位对于攻击 Hy 本身的人最有用,但也可用于
那些深入研究宏编程的人。

Hy 型号
介绍 Hy 型号
Hy 模型是常规 Python 对象之上的一个非常薄的层,代表 Hy 源
编码为数据。 模型只添加源位置信息,以及一些方法
支持 Hy 源代码的干净操作,例如在宏中。 为了实现这一点
目标,Hy 模型是基础 Python 类和 对象.

对象
hy.models.HyObject 是 Hy 模型的基类。 它只实现一种方法, 更换,
它将当前对象的源位置替换为作为参数传递的位置。
这允许我们跟踪被修改的表达式的原始位置
宏,无论是在编译器中还是在纯 hy 宏中。

对象 不打算直接用于实例化 Hy 模型,而仅用作混合
对于其他班级。

复合肥产线 型号
Hy 解析器将括号和括号列表解析为复合模型。

海表
hy.models.list.Hy列表 是“可迭代”Hy 模型的基类。 它的基本用途是
代表括号 [] 列表,当用作顶级表达式时,转换为
编译阶段的 Python 列表文字。

将 HyList 添加到另一个可迭代对象会重用左侧对象的类,
例如,当您想在宏中连接 Hy 对象时,这是一个有用的行为。

超速表达
hy.models.Expression.HyExpression 继承 海表 对于括号 () 表达式。 这
这些表达式的编译结果取决于列表的第一个元素:
编译器在编译器特殊形式、用户定义的宏和
常规 Python 函数调用。

海字典
hy.models.dict.HyDict 继承 海表 对于花括号 {} 表达式,编译
归结为 Python 字典字面量。

使用列表而不是字典作为基类的决定 海字典 允许更容易
在宏中操作字典,还有允许复合表达式的额外好处
作为字典键(例如, 超速表达 Python 类不可哈希)。

原子 型号
在输入流中,双引号字符串,尊重字符串的 Python 表示法,
被解析为单个标记,直接解析为 超字符串.

一个不间断的字符串,不包括空格、括号、引号、双引号
和评论,被解析为标识符。

标识符在解析阶段按以下顺序解析为原子模型:

· 超整数

· 海浮

· 综合体 (如果原子不是裸 j)

· 关键字 (如果原子以 :)

· 符号

超字符串
hy.models.string.HyString 是字符串等效 Hy 模型的基类。 它也是
表示双引号字符串文字, "", 编译成 unicode 字符串
Python 中的字面量。 字符串 在 Python 2 中继承 unicode 对象,在 Python XNUMX 中继承字符串对象
Python 3(因此不依赖于编码)。

超字符串 基于模型是不可变的。

Hy 文字字符串可以跨越多行,并被解析器视为单个
单元,尊重 unicode 字符串的 Python 转义。

数字 型号
hy.models.integer.HyInteger 表示整数文字(使用 在 Python 2 上输入,
INT 在 Python 3 上)。

hy.models.float.HyFloat 表示浮点文字。

hy.models.complex.HyComplex 表示复杂的文字。

使用相应的 Python 例程解析数值模型,并使用有效的数值 Python
文字将变成它们的 Hy 对应物。

符号
hy.models.symbol.Hy符号 是Hy语言中用来表示符号的模型。 它
继承 超字符串.

符号 对象在解析阶段被破坏,以帮助 Python 互操作性:

· 被星号包围的符号 (*) 变成大写;

· 破折号 (-) 变成下划线 (_);

· 一个尾随问号 (?) 变成了领先 是_.

警告:由于重整是在解析阶段完成的,因此可以
以编程方式生成无法使用 Hy 源代码生成的 HySymbol。 这样一个
gensym 使用机制来生成“非内部”符号。

关键字
hy.models.keyword.HyKeyword 表示 Hy 中的关键字。 关键字是开头的符号
a :. 类继承 超字符串.

区分 关键词符号,没有(非自愿)的可能性
冲突,私人使用的 unicode 字符 “\uFDD0” 前置到关键字文字
储存前。

缺点 细胞
hy.models.cons.HyCons 是 Python 友好的表示 缺点 细胞. 缺点细胞是
对于模仿“常见”LISP 变体(例如 Scheme 或 Common)的特征特别有用
口齿不清。

cons 单元格是一个 2 项对象,包含一个 汽车 (头)和一个 CDR (尾巴)。 在某些 Lisp 中
变体,cons 单元是基本构建块,而 S 表达式实际上是
表示为 cons 单元的链表。 像往常一样,Hy 的情况并非如此
表达式由包裹在一个 Python 列表中 超速表达。 但是,那 海康
因此模仿“通常”Lisp 变体的行为:

· (缺点 东西 零) is (Hy表达 [某物])

· (缺点 东西 一些列表) is ((类型 一些列表) (+ [某物] 一些列表)) (如果
一些列表 继承自 名单).

· (得到 (缺点 a b) 0) is a

· (片 (缺点 a b) 1) is b

Hy 支持点列表语法,其中 '(一个 . b) 手段 (缺点 'a '乙)'(一个 b . c) 手段
(缺点 'a (缺点 'b 'C)). 如果编译器在顶层遇到 cons 单元格,它会引发
编译错误。

海康 将传递的参数(car 和 cdr)包装在 Hy 类型中,以简化对
宏上下文中的 cons 单元格。

Hy 内部 理论
概述
Hy 内部结构通过充当 Python 字节码的前端来工作,因此 Hy 本身
编译成 Python 字节码,允许未经修改的 Python 运行时运行 Hy 代码,
甚至没有注意到它。

我们这样做的方法是将 Hy 转换为内部 Python AST 数据结构,并且
使用 Python 标准中的模块将该 AST 构建到 Python 字节码中
库,这样我们就不必为每一个都重复 Python 内部的所有工作
单个 Python 版本。

Hy 分四个阶段工作。 以下部分将涵盖 Hy 从源代码到
运行。

步骤 1 2: 符号化 解析
编译 Hy 的第一阶段是将源词法转换为我们可以处理的标记。 我们
使用一个名为 rply 的项目,它是一个非常好的(且快速的)解析器,以子集编写
的 Python 称为 rpython。

词法分析代码都定义在 hy.lex.词法分析器. 这段代码主要是定义 Hy
语法,所有实际的困难部分都由 rply 处理——我们只是定义
回复的“回调” hylex 解析器,它接受生成的令牌,并返回
Hy 模型。

您可以将 Hy 模型视为 Hy 的“AST”,它是宏操作的对象
(直接),这是编译器在编译 Hy 时使用的。

SEE 另外:
部分 Hy 型号 有关 Hy 模型及其含义的更多信息。

3: Hy 汇编 蟒蛇 AST
这是 Hy 中大部分魔法发生的地方。 这是我们采用 Hy AST(模型)的地方,
并将它们编译成 Python AST。 在这里发生了一些时髦的事情来解决一些问题
AST 中的问题,以及在编译器中工作是我们所做的一些最重要的工作
有。

编译器有点复杂,所以如果你第一次没有理解它,不要难过,
可能需要一些时间才能正确。

编译器的主要入口点是 HyASTCompiler.编译. 调用此方法,并且
类上唯一真正的“公共”方法(也就是说,我们并没有真正承诺
超出该方法的 API)。

事实上,即使在内部,我们也几乎从不直接递归,我们几乎总是强制
Hy 树通过 , 并且经常对表达式的子元素执行此操作
我们有。 由基于类型的调度器来正确调度子元素。

执行编译的所有方法都标有 @构建() 装饰者。 你可以
传递它编译的 Hy 模型的类,或者您可以使用字符串
表达式。 我会在一秒钟内解决这个问题。

姓氏: 阶段 类型调度
让我们从 方法。 我们做的第一件事是检查事物的类型
我们正在建设。 我们抬头看看是否有一个方法可以构建 类型() 我们
有,并分派到可以处理它的方法。 如果我们没有任何方法可以
建立那种类型,我们提出一个内部 特殊课程.

例如,如果我们有一个 超字符串,我们有一个 Hy AST 到 Python 的几乎 1 对 1 的映射
AST。 这 编译字符串 方法取 超字符串,并返回一个 ast.Str()
填充了正确的行号和内容。

宏观扩张
如果我们得到一个 超速表达,我们将尝试查看这是否是一个已知的宏,并推动拥有
它通过调用扩展 hy.macros.macro展开,然后将结果推回到
HyASTCompiler.编译.

其次 阶段 表达调度
唯一的特殊情况是 超速表达,因为我们需要根据情况创建不同的 AST
在有问题的特殊表格上。 例如,当我们击中 (如果 true true 错误的)我们
需要生成一个 如果,并正确编译子节点。 这就是 @构建()
以 String 作为参数进来。

如报名参加 编译表达式 (定义为 @builds(HyExpression)) 将派送
基于第一个参数的字符串。 如果由于某种原因,第一个参数不是
一个字符串,它也将正确处理这种情况(最有可能通过提高 特殊课程).

如果字符串不为 Hy 所知,它将默认创建一个 调用,这将尝试
执行运行时调用(在 Python 中,类似于 富()).

问题 击中 蟒蛇 AST
Python AST 很棒; 正是它让我们能够在上面编写如此强大的项目
Python 无需与 Python 打得过火。 像任何事情一样,我们已经获得了应有的份额
问题,这里是您可能会遇到的常见问题的简短列表。

蟒蛇 分化带来 之间 声明 表达式.

这听起来可能没什么大不了的——事实上,对于大多数 Python 程序员来说,这将
很快就变成了“嗯,是啊”的时刻。

在 Python 中,执行以下操作:

打印 x in 范围(10): 通过因为 打印 打印表达式,和 不是
表达式,它是一个控制流语句。 像 1 + 1 是表达式,原样 拉姆达
x: 1 + x,但其他语言功能,例如 if, 是陈述。

由于它们对 Python 没有“价值”,这使得在 Hy 中工作变得困难,因为做某事
喜欢 (打印 (如果 true true 错误的)) 不仅常见,而且是预料之中的。

因此,我们使用 结果 对象,我们提供任何 标准文件
需要运行,以及一个 ast.表达式 可以用来获取任何东西的价值
刚刚运行。 Hy 通过在运行时强制分配事物来做到这一点。

例如,Hy:

(打印(如果真真假))

会变成:

如果是真的:
_mangled_name_here = 真
其他:
_mangled_name_here = 假

打印_mangled_name_here

好吧,这有点撒谎,因为我们实际上把那个陈述变成了:

打印真如果真否则假

通过强迫事物进入 ast.表达式 如果可以,但总体思路是成立的。

4: 蟒蛇 字节码 输出 运行时
在我们有了一个完整的 Python AST 树之后,我们可以尝试将其编译为 Python
通过推送字节码 评估. 从今往后,我们不再掌控,
Python 正在处理一切。 这就是为什么像 Python 回溯、pdb 和
Django 应用程序工作。

Hy
运用 基因符号 更安全
在编写宏时,必须小心避免捕获外部变量或使用
可能与用户代码冲突的变量名称。

我们将使用一个示例宏 NIF (见
http://letoverlambda.com/index.cl/guest/chap3.html#sec_5 以获得更完整的描述。)
NIF 是一个例子,类似于数字 if,其中基于表达式,其中之一
根据表达式是正数、零还是负数来调用 3 种形式。

第一次通过可能是这样的:

(defmacro nif [expr pos-form zero-form neg-form]
`(让[[晦涩的名字~expr]]
(cond [(pos?晦涩的名字)~pos-form]
[(零?晦涩的名字)~零形式]
[(否定?晦涩的名字)~否定形式])))

哪里 隐名 试图选择一些变量名,以免与其他变量名冲突
代码。 但是,当然,虽然是善意的,但这并不能保证。

方法 gensym 旨在为这样的场合生成一个新的、独特的符号。
一个更好的版本 NIF 将会:

(defmacro nif [expr pos-form zero-form neg-form]
(让 [[g (gensym)]]
`(让 [[~g ~expr]]
(cond [(pos?~g) ~pos-form]
[(零?~g)~零形式]
[(否定?~g)~否定形式]))))

这是一个简单的例子,因为只有一个符号。 但是如果需要几个
gensym 有第二个宏 with-gensyms 基本上扩展为一系列
声明:

(with-gensyms [abc]
...)

扩展为:

(让 [[a (gensym)
[b(gensym)
[c(gensym)]]
...)

所以我们重写 NIF 看起来像:

(defmacro nif [expr pos-form zero-form neg-form]
(with-gensyms [g]
`(让 [[~g ~expr]]
(cond [(pos?~g) ~pos-form]
[(零?~g)~零形式]
[(否定?~g)~否定形式]))))

最后,尽管我们可以制作一个新的宏来为我们完成所有这些。 定义宏/克! 将采取
所有以 g! 并自动调用 基因符号 与剩余的
象征。 所以 啊! 会成为 (基因符号 “一种”).

我们的最终版本 NIF,用 定义宏/克! 变为:

(defmacro/g!nif [expr pos-form zero-form neg-form]
`(让 [[~g!res ~expr]]
(cond [(pos?~g!res)~pos-form]
[(零?~g!res)~零形式]
[(否定?〜g!res)〜否定形式]))))

检查 参数 升起 例外
Hy 编译器 内置插件

贡献者 课程结构 指数


内容:

照应
版本0.9.12中的新功能。

anaphoric macros 模块使 Hy 中的函数式编程非常简洁且易于使用
阅读。
照应宏是一种编程宏,它有意捕捉某种形式
提供给可由照应词(指代词的表达)引用的宏
到另一个)。 — 维基百科(http://en.wikipedia.org/wiki/Anaphoric_macro)


应用程序
用法: (如果 (富) (打印 它))

评估第一个形式的真实性,并将其绑定到 it 在真假中
分支机构。

每个
用法: (ap-每个 [1 2 3 4 5] (打印 它))

评估列表中每个元素的表单的副作用。

每次都
用法: (每次都 名单 预计值 身体)

评估谓词形式返回的每个元素的形式 .

=> (ap-each-while [1 2 3 4 5 6] (< it 4) (print it))
1
2
3

地图
用法: (AP地图 申请 列表)

map 的照应形式就像普通 map 一样,只是它不是一个函数
object 它采用 Hy 形式。 特别的名字 it 绑定到当前对象
迭代中的列表。

=> (list (ap-map (* it 2) [1 2 3]))
[2,4,6]

ap-map-何时
用法: (ap-map-when 预定义 代表 列表)

使用谓词函数评估列表上的映射以确定何时应用
形式。

=> (list (ap-map-when奇怪?(* it 2) [1 2 3 4]))
[2,2,6,4]

=> (list (ap-map-when even? (* it 2) [1 2 3 4]))
[1,4,3,8]

过滤器
用法: (ap-过滤器 申请 列表)

和...一样 地图 我们采用特殊形式而不是函数来过滤元素
列表。 特别的名字 it 绑定到迭代中的当前元素。

=> (list (ap-filter (> (* it 2) 6) [1 2 3 4 5]))
[4 5]

拒绝
用法: (ap-拒绝 申请 列表)

此功能与 过滤器,它拒绝通过的元素
谓词。 特别的名字 it 绑定到迭代中的当前元素。

=> (list (ap-reject (> (* it 2) 6) [1 2 3 4 5]))
[1,2,3]

应用程序时间
用法 (ap-dotimes n 身体)

这个函数评估身体 n 次,使用特殊变量 it 绑定自 0
1年. 它对副作用很有用。

=> (setv n [])
=> (ap-dotimes 3 (.append n it))
=> n
[0,1,2]

ap优先
用法 (ap优先 预定义 列表)

此函数返回传递谓词的第一个元素或 不包含,与
特殊变量 it 绑定到迭代中的当前元素。

=>(ap-first (> it 5) (range 10))
6

aplast
用法 (最后 预定义 列表)

此函数返回传递谓词的最后一个元素或 不包含,特别
变量 it 绑定到迭代中的当前元素。

=>(ap-last (> it 5) (范围 10))
9

减少
用法 (减少 申请 名单 &可选的 初始值)

此函数返回将 form 应用于 body 中的前 2 个元素的结果,以及
应用结果和第三个元素等,直到列表用完。 可选的
可以提供初始值,因此该函数将应用于初始值和
代替第一个元素。 这将被迭代的元素暴露为 it 和当前
累计值作为 ACC.

=>(ap-reduce (+ it acc) (范围 10))
45

循环/重复
版本0.10.0中的新功能。

循环 / 复发 宏为程序员提供了一种使用尾调用优化 (TCO) 的简单方法
在他们的 Hy 代码中。
尾调用是在另一个过程中作为其最终调用发生的子例程调用
行动; 它可能会产生一个返回值,然后立即由调用返回
程序。 如果子程序执行了任何调用,以至于它最终可能导致
在调用链中再次被调用的同一个子程序位于尾部位置,
这样的子程序被称为尾递归,这是递归的一种特殊情况。
尾调用很重要,因为它们可以在不添加新堆栈的情况下实现
帧到调用堆栈。 当前程序的大部分框架不需要任何
more,可以用尾调用的frame代替。 然后程序可以跳转
到被调用的子程序。 产生这样的代码而不是标准的调用序列是
称为尾调用消除或尾调用优化。 尾调用消除允许
过程调用尾部位置与 goto 语句一样有效地实现,
从而允许高效的结构化编程。 — 维基百科(—
http://en.wikipedia.org/wiki/Tail_call)


循环
循环 建立递归点。 和 循环, 复发 重新绑定中设置的变量
递归点并将代码执行发送回该递归点。 如果 复发 在使用
非尾部位置,抛出异常。

用法: (循环 绑定 &休息 身体)

示例:

(需要 hy.contrib.loop)

(定义阶乘 [n]
(循环 [[in] [acc 1]]
(如果(零?我)
ACC
(重复出现(dec i)(* acc i)))))

(阶乘 1000)

定义多
版本0.10.0中的新功能。

定义多 允许您按给定数量的 args 和/或 kwargs 重载函数。
受到 Clojure 的启发 定义.

=>(需要 hy.contrib.multi)
=>(定义多重乐趣
... ([a] "a")
... ([ab] "ab")
... ([abc] "abc"))
=>(有趣的1)
“一种”
=>(有趣 1 2)
“ab”
=>(有趣 1 2 3)
“ABC”

黑客入侵 ON HY


加入 我们的 海夫!
请来攻击Hy!

请和我们一起出去玩 #hy on irc.freenode.net!

请在 Twitter 上与 #hy #标签!

请写博客!

请不要在邻居的栅栏上喷漆(没有很好地询问)!

哈克!
做这个:

1。 创建一个 虚拟 环境:

$ 虚拟环境 venv

并激活它:

$ . venv/bin/激活

或使用 虚拟包装器 创建和管理您的虚拟环境:

$ mk虚拟环境
$ 工作 hy

2.获取源代码:

$ git 克隆 https://github.com/hylang/hy.git

或使用你的叉子:

$ git 克隆 [电子邮件保护]: /hy.git

3.安装黑客:

$ CD 嗨/
$ pip install -e 。

4.安装其他develop-y要求:

$ pip install -r 要求-dev.txt

5. 做很棒的事情; 让某人对你所做的感到高兴/厌恶而尖叫。

测试!
测试位于 测试/。 我们用 鼻子.

要运行测试:

$鼻子测试

写测试——测试是好的!

此外,最好为所有支持的平台和 PEP 8 兼容运行测试
代码。 您可以通过运行 tox 来实现:

$毒药

文档!
文档位于 docs /。 我们用 人头狮身.

要以 HTML 格式构建文档:

$ cd 文档
$ 制作 html

写文档---文档很好! 甚至这个医生!

特约
欢迎贡献并非常感谢,每一点都有助于让 Hy 更多
真棒。

拉取请求很棒! 我们爱他们; 这是一个快速指南:

· fork repo 并为功能/修复创建主题分支。 避免直接进行更改
在主分支上。

· 所有传入的特性都应该伴随着测试。

· 在您提交 PR 之前,请运行测试并根据样式检查您的代码
指导。 您可以同时执行以下两项操作:

$ 使 d

· 将提交放入逻辑单元,以便以后更容易跟踪和导航。 前
提交 PR,尝试将提交压缩到易于返回的变更集中
之后。 另外,请确保不要在变更集中留下虚假的空白; 这
避免在以后创建空白修复提交。

· 就提交信息而言,请尽量遵守以下几点:

· 尝试坚持 Git 提交消息的第一行的 50 个字符限制。

· 有关更多详细信息/解释,请在后面添加一个空行并继续
详细描述提交。

· 最后,将您自己添加到 AUTHORS 文件中(作为单独的提交):您应得的 :)

· 所有传入的更改都需要由 Hylang 核心团队的 2 名不同成员确认。
显然欢迎额外的审查,但我们需要至少 2 个签收
改变。

· 如果核心成员发送 PR,请找到 2 个核心成员,不包括
公关提交者。 这里的想法是,一个人可以与 PR 作者合作,第二个 acks
整个变更集。

· 对于文档和其他琐碎的更改,我们最好在一个 ACK​​ 后合并。 我们有
低覆盖率,所以保持低障碍会很好。

核心 团队
Hy的核心开发团队由以下开发人员组成:

· 朱利安 Danjou上尉

· 莫滕 林德鲁德

· J 肯尼斯 国王

· 盖尔盖伊 纳吉

· 图卡 图尔托

· 卡伦 鲁斯塔德

· 阿布舍克 L

· 克里斯托弗 艾伦 韦伯

· 康拉德 兴森

· 卡恩-格林

· 保罗 塔利亚蒙特

· 萨科 丹德里蒙特

· 短发 托尔伯特

· 的Berker 佩克萨格

· 克林顿 N. 德赖斯巴赫

· 塞马伊

使用 onworks.net 服务在线使用 hy


免费服务器和工作站

下载 Windows 和 Linux 应用程序

Linux 命令

Ad