Ex2.2 終端記号と非終端記号を明に区別するgenerate

以前のgenerateは、rewriteの戻り値を分岐条件としていたけど、それだと分かりにくいよね、ちゃんと述語を作ろう。という問題。

PAIPの答えでは、non-terminal-pを定義していたので、自分はterminal-symbol-pを定義して解いてみる。当然、あまり変わらない。

;;; Exercise 2.2 [m] Write a version of generate that explicitly differentiates between
;;; terminal symbols (those with no rewrite rules) and non-terminal symbols.
(defun rule-find (category)
  "Find rule of specified category."
  (assoc category *grammar*))

(defun rewrites (category)
  "Return a list of the possible rewrites for this category."
  (rule-rhs (rule-find category)))

(defun terminal-symbol-p (symbol)
  "True if this symbol is not a category in the grammar."
  (not (rule-find symbol)))

(defun generate (phrase)
  "Generate a random sentence or phrase"
  (cond ((listp phrase)
	 (mappend #'generate phrase))
	((not (terminal-symbol-p phrase))
	 (generate (random-elt (rewrites phrase))))
	(t (list phrase))))

(generate 'sentence)
;; => (THE BALL LIKED A BALL)