2015-01-10 34 views
-1

我有以下的代碼,這被認爲是一個高階函數,其過濾基於所述&key參數元件輸入(在這種情況下:year:month:type使用除去-IF-不與&關鍵參數

(defun filter-by (&key year month type) 
    "Remove members of the list not matching the given year and/or month and/or type, returns a 
    function that takes the list" 
    (lambda (lst) 
     (remove-if-not #'(lambda (element) 
     (when year 
      (equalp (local-time:timestamp-year (get-record-date element)) 
        year))) 
     (when month 
      (equalp (local-time:timestamp-month (get-record-date element)) 
        month))) 
     (when type 
      (equalp (get-type element) 
        type)))) 
     lst))) 

的問題是,除非使用所有的關鍵字參數,它總是返回nil,我因爲如何when表單內remove-if-not行爲猜測。

反正有沒有訴諸多個cond陳述這項工作? cond的問題是,我將不得不特別是寫下所有可能的參數組合,這對3個參數是可以的,但是如果將來我想使用其他關鍵字進行過濾。

+2

代碼中並沒有太大的意義,因爲括號設置不正確。您可能想要正確縮進該功能,然後修復語法錯誤。 –

+0

問題是你沒有合併'equalp'形式的結果,所以實際上只有最後一個重要。在'when'表格周圍使用'或'。 – acelent

+0

爲什麼在函數中有外部lambda?該函數返回函數而不是過濾列表。 – enrey

回答

2

Common Lisp的關鍵字參數有一個特殊的語法,可讓您告訴 是否提供參數。我認爲你應該可以使用 這個來達到你想要的效果。

下面是一個工作示例,儘管數據表示略有差異 因爲我沒有您的定義local-timeget-record-date。你應該能夠很容易地將它適應你的代碼。

(defun my-filter-by (lst &key 
         (year nil year-p) ;; nil is the default 
         (month nil month-p) ;; year-p/month-p/day-p say whether 
         (day nil day-p)) ;; the argument was supplied 
    (remove-if-not 
    (lambda (element) 
    (let* ((year-okp (or (not year-p) 
          (equal year (cdr (assoc :year element))))) 
      (month-okp (or (not month-p) 
          (equal month (cdr (assoc :month element))))) 
      (day-okp (or (not day-p) 
         (equal day (cdr (assoc :day element))))) 
      (all-okp (and year-okp month-okp day-okp))) 
     all-okp)) 
    lst)) 

而且一些例子:

(defparameter *lst* '(((:year . 2000) (:month . :may) (:day . 17)) 
         ((:year . 2000) (:month . :may) (:day . 18)) 
         ((:year . 2001) (:month . :aug) (:day . 2)) 
         ((:year . 2002) (:month . :jan) (:day . 5)))) 


(my-filter-by *lst*) ;; keeps everything 
(my-filter-by *lst* :year 2000) ;; everything from 2000 
(my-filter-by *lst* :year 2000 :day 17) ;; only 2000/may 17 
+0

這很完美,謝謝。我沒有考慮使用這樣的謂詞。 – momo

相關問題