Я относительный новичок в Clojure, который недавно прошел это точное упражнение.Здесь следует рассмотреть, хотите ли вы как можно точнее придерживаться кода Norvig (например, писать Clojure со вкусом Common-Lisp) или же вы хотите написать что-то более близкое к идиоматическому 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 - это сахар, который позволяет вам добавлять строки документации в переменные более естественно.В этом случае я использую карту (пары значений ключей, разделенных {}), чтобы получить поиск в словарном стиле от LHS каждого правила до RHS.Я также использую векторы (разделенные []) вместо списков для представления RHS каждого правила.Вообще говоря, «идиоматический» код Clojure редко использует списки для хранения последовательных данных;векторы предпочтительнее, если вы не представляете формы Clojure (исходный код).
Изменения такого рода позволят вам использовать больше встроенных возможностей языка вместо того, чтобы, например, создавать небольшие вспомогательные функции.манипулировать вложенными списками.