2

私が理解している限り、ラベルの使用は flet と同じですが、より高いスコープを持つローカル関数を定義することです。あれは正しいですか。例を挙げます:

(defun nested-average (tree)
  ;labels are the same as flet but with higher scope, define local functions
  (labels ((%nested-average
                ;arguments for the function
                (branch sum visited)                
                (cond
                 ((consp branch)
                      (multiple-value-call
                      ;calls the previous function with reference to the label
                       #'%nested-average (rest branch)
                       (%nested-average (first branch) sum visited)))

                   ;is branch a number
                 ((numberp branch)
                    (values (+ sum branch) (1+ visited)))
                  ;otherwise
                 (t 
                 (values sum visited))
                 )
            )
           )
            (multiple-value-call #'/ (%nested-average tree 0 0))
    )
)
    ;(nested-average ' (10 ((30 1) 20) (8 (5 (50 7)) 9) 40))
4

1 に答える 1

3

Hyperspec から: labels は flet と同等ですが、ラベル用に定義された関数名の範囲が関数定義自体と本体を包含する点が異なります。

これが実際に意味することは、ラベルを使用すると再帰関数を記述できるということです。例えば:

(defun fact (n)
  (labels ((rec (x)
             (if (< x 1) 
                 1
                 (* x (rec (- x 1))))))
    (rec n)))

この関数は正常に動作しますが、シンボル rec が関数定義でバインドされないため、flet で記述された同じ関数はエラーを引き起こします。ご提供いただいたサンプル関数は、同じ理由で flet で書くとエラーになります。

于 2012-11-06T19:40:08.490 に答える