2017-03-07 72 views
0

我是Clojure的新手,試圖編寫一個應該簡化邏輯表達式的程序。例如:Clojure:使用多個參數簡化邏輯表達式

(or x false) => x 
(or true x) => true 
(or x y z) => (or x(or y z)) 

我相信,我已經想出瞭如何將表達式簡化爲兩個參數。但是,我不知道如何簡化包含兩個以上參數的表達式。我試圖使用第n函數來嘗試和分區的表情,但似乎事情進一步複雜化:

(defn pre-simplify [expression n] 
    (cond 
    (= n 0) (nth expression 0) 
    (= n 1) (nth expression 1) 
    (= n 2) (nth expression 2) 
    (= n 3) (nth expression 3) 
    ) 
) 

這是簡化功能的代碼:

(defn simplify 
    ([op arg1]             
    (cond 
     (and (= arg1 'true) (= op 'not)) false 
     (and (= arg1 'false) (= op 'not)) true 
     (= arg1 'true) true 
     (= arg1 'false) false) 
     ;not not x -> x 
    ) 
    ([op arg1 arg2]           
    (cond 
     (seq? arg1) (let [arg1 (simplify op arg1)])) 
    (cond 
     (seq? arg2) (let [arg2 (simplify op arg2)])) 
    (cond 
     (= op 'or) (
       (cond 
        (and (= arg1 'false) (= arg2 'false)) false 
        (or (= arg1 'true) (= arg2 'true)) true 
        (and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2 
        (and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1 
       ) 
      ) 
     (= op 'and') (
        (cond 
        (and (= arg1 'true) (= arg2 'true)) true 
        (or (= arg1 'false) (= arg2 'false)) false 
        (and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2 
        (and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1 
        ) 
      ) 
     ) 
) 

而且,我想在前兩個參數後的列表的其餘部分使用遞歸。例如,這是我在嘗試做兩個以上參數:

([op arg1 arg2 & rest]          
     (simplify op (list (op arg1 (op arg2 rest)))))) 
+0

連續3個'cond'應該做什麼?我可能會很累,但前兩個對任何事物都應該沒有任何影響。您正在創建'arg1'和'arg2'的局部陰影,然後將其扔掉。 – Carcigenicate

+0

你來自命令式編程嗎? – Carcigenicate

回答

2

這看起來像功課,所以讓我請你從另外一個角度考慮問題。

在Clojure中,

  • 一個and表達式是與符號'and開始表達式列表(或其他序列);
  • or表達式是以 符號'or開頭的表達式列表;
  • ...。

的表達式也可以是

  • 一個符號的參數或其他本地名稱,或
  • 字面truefalse

simplify的表達式:

  • 如果它是一個序列(使用seq?來測試這一點),simplify其 參數(列表中的所有元素,但first - rest會給你的) 。您可以使用map進行遞歸調用。
  • 然後,例如,如果操作員(first元件)是一種and符號,
    • 如果在操作數中的任false文字(可以使用 some測試此),更換整個表達與false
    • 如果不是,remove任何true文字。

這些簡化可以爲他人開闢道路。例如,

  • (and)只是true
  • (and x)只是x

不管你做什麼,在你開發它的時候測試你的功能,確保它能做你認爲它的功能。在一起案件中,我被抓到了操作員。我倒下了(and x)的情況。

還有什麼可以爭取的是,預計如何以及在多大程度上驗證表達式是否有效。

  • 未知算子呢?
  • 您是否期望驗證符號是否涉及某物。如果是這樣, 如何?

  • 我假設我們絕對不能忽視的副作用:所有的表達確實是 返回值。
  • 我不會用(or x (or y z))代替(or x y z)。這並沒有實現 ,並且使用了額外的令牌:與簡化相反。
  • 任何Clojure值 - 一個數字,甚至是一個函數 - 在邏輯上起到 的作用,除了falsenil,它們在邏輯上是錯誤的。是否 這與您的問題有關,我不知道。
  • 如果你感到聰明,你可以進行參數如何andor的行爲從字面來講你(分別truefalse)忽略,返回 當一個你得出結論,和一個沒有任何爭論。

整個問題被認爲是棘手的。如果你找到一個有效的解決方案,你會成爲世界聞名的!