2010-09-06 74 views
9

我最近給Scala的第二次機會,並開始與項目,我始終貫徹執行(功能性或僞函數式語言):一個自動推理的命題邏輯(後來謂詞邏輯)。斯卡拉 - 前綴目運算符

現在,我已經試圖讓命題邏輯的符號語言本身一樣漂亮越好,到目前爲止,我已經得到了這一點 - 與隱式轉換(字符串 - >凌動):

("A" and "B") implies "C" 

功能「與」和「隱含」(和「或」和「等價物」)是調用相關的情況下,類的構造函數的簡單方法。然而,在實現時「不」,我被卡住有以下兩種符號的:

("A" and "B").not 
Not("A" and "B") 

有沒有辦法來欺騙斯卡拉接受這項期望:

not("A" and "B") 

Preferrably不重新命名類「不」「不」,因爲我可能喜歡把它稱爲「¬」或別的東西,在未來屆。

回答

4

截至2014年2月,我認爲最簡潔的方式定義表達式前綴'not操作,同時避免所有類型的額外cruft/wrapping,將直接在包範圍內聲明函數,與所有你的其他函數,類,類型等等:這是通過定義一個包對象來完成的(Scala不允許你僅僅把函數放在.scala文件的根目錄下(我想知道爲什麼) Java的腳步?))。

package org.my.logiclib 

implicit class Atom(s: String) { ... } 
class MyType1 
class MyType2 

object `package` { 
    def not(expr: Expr) = ... 
} 

這樣,做import org.my.logiclib._將導入的一切,包括not()

以上相同

package org.my 

package logiclib { 
    implicit class Atom ... 
    ... 

    def not(expr: Expr) = ... 
} 
14

可以將單獨的對象上限定not爲方法,是這樣的:

object Logic { 
    def not(x:Expr) = Not(x) 
} 
import Logic._ 
not("A" and "B") 

(凡Expr應該是的AndOrNotAtom的公共超)

編輯:下面是一個只用一次導入就可以使用的例子:

object Logic { 
    abstract class Expr { 
    def and(e: Expr) = Conjunction(this, e) 
    def or(e: Expr) = Disjunction(this, e) 
    def implies(e: Expr) = Implication(this, e) 
    } 
    case class Conjunction(e1: Expr, e2: Expr) extends Expr 
    case class Disjunction(e1: Expr, e2: Expr) extends Expr 
    case class Implication(e1: Expr, e2: Expr) extends Expr 
    case class Negation(e: Expr) extends Expr 
    case class Atom(name: String) extends Expr 

    def not(e: Expr) = Negation(e) 
    implicit def string2atom(str: String) = Atom(str) 
} 

// use site 
import Logic._ 
not("A" and "B") implies (not("A") or not("B")) 
+0

謝謝,我不知道我可以使用Scala的「靜態導入」 - 這會離開我,每個頁面上的強制性進口,雖然,這 - 一起隱式轉換對於每次使用都會有很多額外的代碼。 – wen 2010-09-06 14:00:02

+2

@Dennetik:如果你只是把所有東西都放到Logic對象中,那麼'import logic._'就是你需要使用你的類的所有東西。 – sepp2k 2010-09-06 14:15:17

+1

沒想到這一點,我仍然必須習慣Scala的自由,與Java相比... – wen 2010-09-06 14:23:35

19

我注意到this answer來,它似乎是一個可以與unary_前綴運營商的名稱才達到你正在嘗試做的另一個問題。 (見unary_!

編輯:this article確認語法。

+1

儘管如此,它並不適用於自定義操作符名稱。即你不能定義'unary_not'來得到一個前綴「not」 - 操作符。 – sepp2k 2010-09-06 12:58:45

+16

具體而言'prefix_'只適用於'!','〜','+'和'-'。 – sepp2k 2010-09-06 13:02:42

+1

@ sepp2k:謝謝,沒有意識到這個細節。這個限制看起來有些恥辱(並且完全是任意的)。 – 2010-09-06 13:06:57

8

爲什麼Not代替not?有沒有什麼可以阻止你這樣做:

object not { 
    def apply(expr: T) = ... 
} 

然後使用not("A" and "B")

+0

爲什麼大家總是想方設法使用包對象將函數直接放入包中... – 2014-02-13 02:58:38

+1

@ErikAllik因爲2010年沒有包對象。 – 2014-02-13 05:32:40

+0

好點!沒有意識到 - 謝謝:) P.S.然而,你今天會用一個來定義'not(expr:T)'嗎? – 2014-02-13 12:45:25