2011-11-13 10 views
5

İsteğe bağlı ve anahtar kelime bağımsız değişkenleri alabilen bir Lisp işlevi yazmaya çalışıyorum. Anahtar kelime argümanları kullanarak işlevi çağırmak için çalışıyorum ama değil isteğe bağlı olanlar, bir hata olsun fonksiyonuİsteğe bağlı argümanlar VE anahtar kelime argümanlarını aynı işleve nasıl alabilirim?

(defun max-min (v &optional max min &keyword (start 0) (end nil)) 

başlar. Ne yapmaya çalışıyorum ben max için :start bağlamaya çalıştığı için bu olduğunu varsayalım hatası Error: :START' is not of the expected type REAL'

alıyorum

(max-min #(1 2 3 4) :start 1 :end 2) 

olduğunu. Bunu nasıl çalıştırabilirim? Teşekkürler.

cevap

8

Bu işlevi gerekli parametreyle, isteğe bağlı parametrelerle ve ardından anahtar sözcük parametreleriyle çağırmanız gerekir. Aksi halde nasıl çalışması gerekir? Aramanız isteğe bağlı parametrelerden yoksundur. Aramada anahtar kelime parametrelerini belirtmek isterseniz, isteğe bağlı isteğe bağlı değildir.

(max-min #(1 2 3 4) 0 100 :start 1 :end 2) 

temel stil kuralı:

bir fonksiyonu anahtar kelime parametreleri ile isteğe bağlı karıştırmayın. Örneğin, Common Lisp onu bir yerde kullanır ve bir hata kaynağıdır.

CL:READ-FROM-STRING böyle bir örnektir.

read-from-string string 
       &optional eof-error-p eof-value 
       &key start end preserve-whitespace 

http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_fro.htm

Bu çalışır:

(read-from-string " 1 3 5" :start 2) 

Ama kullanıcı EOF-HATA-P belirtmeyi unuttunuz ve EOF-DEĞER:

(read-from-string " 1 3 5" t nil :start 2) 

Bu aynı zamanda çalışabilir . Eğer teknik olarak verilen argümanlar listesini ayrıştırma ile çalışmak için alabilirsiniz, Lisp derleyici şikayet olmayabilir ve 2. tamlık hatırına

5

de başlamaz neden kullanıcı merak edecektir kendiniz:

(defun max-min (v &rest args) 
    (flet ((consume-arg-unless-keyword (default) 
      (if (keywordp (first args)) 
       default 
       (pop args)))) 
    (let ((max (consume-arg-unless-keyword nil)) 
      (min (consume-arg-unless-keyword nil))) 
     (destructuring-bind (&key (start 0) (end nil)) args 
     ;; ... 
     )))) 

Her zamanki gibi, Rainer'i dinlemek iyi bir fikir. Bu çok büyülü bir tasarıma benziyor. Hem geliştirme ortamını (örneğin, otomatik arglist gösterimini bozarak) hem de kullanıcıyı karıştırır (tür hatalarını daha kolay bulmak için: bir numarayı geçmeyi amaçladığınız bir anahtar kelimeyi yanlışlıkla ilettiğinizde ne olur?).