2010-09-06 12 views
9

Ich habe vor kurzem Scala eine zweite Chance gegeben und begann mit dem Projekt, das ich immer implementiere (in funktionalen oder pseudo-funktionalen Sprachen): ein automatisierter Begründer für Aussagenlogik (und spätere Prädikatenlogik).Scala - Präfix Unäre Operatoren

Nun, ich habe versucht, die Schreibweise der Aussagenlogik in der Sprache selbst so hübsch wie möglich zu bekommen, und ich habe so weit gekommen - mit einer impliziten Konvertierung (String -> Atom):

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

Die Funktionen "and" und "implicates" (und "or" und "equivalent") sind einfache Methoden, die den relevanten Fallklassenkonstruktor aufrufen. Wenn jedoch „nicht“ zur Durchführung, bekomme ich mit einem der beiden folgenden Bezeichnungen fest:

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

Gibt es eine Möglichkeit Scala Trick zu akzeptieren die gewünschte:

not("A" and "B") 

Vorzugsweise ohne die Klasse zu umbenennen "Nicht" zu "nicht", denn ich möchte es in Zukunft "¬" oder etwas anderes nennen.

Antwort

4

Ab Februar 2014, ich denke, die sauberste Möglichkeit, eine Präfix'ish not Operation auf Ausdrücke zu definieren, während alle Arten von zusätzlichen Cruft/Wrapping zu vermeiden, würde die Funktion direkt im Paketumfang zusammen mit allen zu deklarieren Ihre anderen Funktionen, Klassen, Typen etc: Dies geschieht durch die Definition eines Paketobjekts (Scala erlaubt es Ihnen nicht, einfach Funktionen auf die Stammebene der Datei .scala zu setzen (ich würde gerne wissen, warum) - soll es nur folgen Javas Fußstapfen?)).

package org.my.logiclib 

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

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

diese Weise import org.my.logiclib._ tun alles importieren, einschließlich not().

Die oben die gleichen wie

package org.my 

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

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

Sie können not als Methode auf einem Singleton-Objekt definieren, wie folgt aus:

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

(Wo Expr sollte die gemeinsame übergeordnete Klasse von And, Or, Not und Atom sein)

bearbeiten : Hier ist ein Beispiel, wie dies mit nur einem einzigen Import verwendet werden könnte:

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

Dank, ich wusste nicht, dass ich „statische Importe“ in Scala nutzen könnte - das mich auf jeder Seite mit einem obligatorischen Import verlassen würde, obwohl, die - zusammen mit der impliziten Konvertierung wäre eine Menge zusätzlichen Code für jede Verwendung. – wen

+2

@Dennetik: Wenn Sie einfach alles in das Logic-Objekt einfügen, brauchen Sie 'logic._ importieren' nur, um Ihre Klassen zu verwenden. – sepp2k

+1

Hätte ich nicht gedacht, ich muss mich immer noch an Scalas Freiheit gewöhnen, verglichen mit Java ... – wen

19

Ich bemerkte auf this answer zu einer anderen Frage, dass es scheint, dass man den Operatornamen mit unary_ voranstellen kann, um zu erreichen, was Sie versuchen zu tun. (Siehe unary_!.)

Edit: this article bestätigt die Syntax.

+1

Das funktioniert jedoch nicht mit benutzerdefinierten Benutzernamen. I.e. Sie können 'unary_not' nicht definieren, um einen Präfix" not "-Operator zu erhalten. – sepp2k

+16

Speziell 'prefix_' funktioniert nur mit'! ',' ~ ',' + 'Und' -'. – sepp2k

+1

@ sepp2k: Danke, habe das nicht klar erkannt. Diese Einschränkung scheint ein wenig beschämend (und völlig willkürlich) zu sein. –

8

Warum Not anstelle von not? Es gibt nichts, was Sie zu tun, um dies zu stoppen:

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

Und dann not("A" and "B") verwenden.

+0

Warum findet jeder immer Wege um Funktionen direkt in Pakete zu setzen, die Paketobjekte verwenden ... –

+1

@ErikAllik Weil es 2010 keine Paketobjekte gab. –

+0

Guter Punkt! Habe das nicht realisiert - Danke :) P.S. Würden Sie heute einen verwenden, um 'not (expr: T)' zu definieren? –