10

Land of Lispの良いところをたくさん読んだので、そこを調べて何が見えるか見てみようと思いました。

(defun tweak-text (lst caps lit)
  (when lst
    (let ((item (car lst))
      (rest (cdr lst)))
      (cond 
       ; If item = space, then call recursively starting with ret
       ; Then, prepend the space on to the result.
       ((eq item #\space) (cons item (tweak-text rest caps lit)))
       ; if the item is an exclamation point.  Make sure that the
       ; next non-space is capitalized.
       ((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
       ; if item = " then toggle whether we are in literal mode
       ((eq item #\") (tweak-text rest caps (not lit)))
       ; if literal mode, just add the item as is and continue
       (lit (cons item (tweak-text rest nil lit)))
       ; if either caps or literal mode = true capitalize it?
       ((or caps lit) (cons (char-upcase item) (tweak-text rest nil lit)))
       ; otherwise lower-case it.
       (t (cons (char-downcase item) (tweak-text rest nil nil)))))))

(コメントは私のものです)
(参考までに-メソッドのシグネチャはです(list-of-symbols bool-whether-to-caps bool-whether-to-treat-literally)が、作成者はこれらを短縮しました(lst caps lit)。)

しかしとにかく、ここに質問があります:
これは(cond... (lit ...) ((or caps lit) ...))それにあります。私の理解では、これはif(lit){ ... } else if(caps || lit){...}Cスタイルの構文に変換されます。その場合、orステートメントは冗長ではありませんか?(or caps lit)キャップがの場合に条件が呼び出される条件はありnilますか?

4

2 に答える 2

10

確かに、あなたは正しいです。この本の正誤表を参照してください。

ページ97:関数tweak-textには2つのグリッチがありますが、ほとんどのLisp実装では問題なく実行されます。まず、eq関数を使用して文字を比較します。ANSI仕様に従って、文字は常にeqlやchar-equalなどの他の関数でチェックする必要があります。また、キャップに簡略化できる不要なチェック(またはキャップが点灯)があります。

于 2011-01-02T01:41:29.500 に答える
8

私はそれを次のように書きます:

(defun tweak-text (list caps lit)
  (when list
    (destructuring-bind (item . rest) list
      (case item
        ((#\space)             (cons item (tweak-text rest caps lit)))
        ((#\! #\? #\.)         (cons item (tweak-text rest t    lit)))
        ((#\")                 (tweak-text rest caps (not lit)))
        (otherwise (cond (lit  (cons item (tweak-text rest nil  lit)))
                         (caps (cons (char-upcase item)
                                     (tweak-text rest nil lit)))
                         (t    (cons (char-downcase item)
                                     (tweak-text rest nil nil)))))))))

CASEステートメントはキャラクターにディスパッチします。次に、CONDステートメントが他の条件を処理します。CASEはEQLと比較されます。つまり、CASEはキャラクターに対しても機能し、複数のアイテムと比較することもできます。私は、対応する式を並べるコードレイアウトスタイルのファンでもあります。これは、等幅フォントでのみ役立ちます。これは、コード内のパターンを視覚的に検出するのに役立ち、簡略化できるコードを検出するのに役立ちます。

DESTRUCTURING-BINDはリストを分解します。

楽しみのために、LOOPを使用して書き直しました:

(defun tweak-text (list)
  (loop with caps and lit

        for item in list

        when (eql item #\space)
        collect item

        else when (member item '(#\! #\? #\.))
        collect item and do (setf caps t)

        else when (eql item #\")
        do (setf lit (not lit))

        else when lit
        collect item and do (setf caps nil)

        else when caps
        collect (char-upcase item) and do (setf caps nil)

        else
        collect (char-downcase item) and
        do (setf caps nil lit nil)))
于 2011-01-02T10:04:56.097 に答える