我正在阅读 Peter Norvig 撰写的 人工智能编程范式 (PAIP),并且尝试用 Clojure 而不是 Common Lisp 编写所有的代码。然而,我被第 39 页上的这段代码卡住了:
(defparameter *simple-grammar* '((sentence -> (noun-phrase verb-phrase)) (noun-phrase -> (Article Noun)) (verb-phrase -> (Verb noun-phrase)) (Article -> the a) (Noun -> man ball woman table) (Verb -> hit took saw liked)) "A grammar for a trivial subset of English.") (defvar *grammar* *simple-grammar*)
我该如何将其翻译成 Clojure?谢谢。
回答:
我是一个相对的 Clojure 新手,前段时间也做了完全一样的练习。这里需要考虑的是,你是否想尽可能地坚持 Norvig 的代码(就像编写 “具有 Common-Lisp 风味” 的 Clojure),或者你是否想编写更接近惯用的 Clojure 代码。这是我所做的:
(use '[clojure.contrib.def :only [defvar]])(defvar *simple-grammar* {:sentence [[:noun-phrase :verb-phrase]] :noun-phrase [[:Article :Noun]] :verb-phrase [[:Verb :noun-phrase]] :Article ["the" "a"] :Noun ["man" "ball" "woman" "table"] :Verb ["hit" "took" "saw" "liked"]} "A grammar for a trivial subset of English.")
defvar 是一种语法糖,允许你更自然地向 vars 添加文档字符串。 在这种情况下,我使用一个 map(由 {} 分隔的键值对)来获得从每个规则的 LHS 到 RHS 的字典式查找。 我还使用 vectors(由 [] 分隔)而不是列表来表示每个规则的 RHS。 一般来说,“惯用的” Clojure 代码很少使用列表来保存顺序数据; 除非您正在表示 Clojure 形式(源代码),否则首选 vectors。
这些类型的更改将允许你使用更多语言的内置功能,而无需例如编写一些辅助函数来操作嵌套列表。