Scala - Prefix unaire Opérateurs
-
01-10-2019 - |
Question
J'ai récemment donné Scala une seconde chance, et a commencé avec le projet que je toujours mettre en œuvre (dans les langages fonctionnels ou pseudo-fonctionnel):. Un raisonneur automatisé pour la logique propositionnelle (et logique plus tard prédicat)
Maintenant, je l'ai essayé d'obtenir la notation de la logique propositionnelle dans la langue elle-même aussi jolie que possible, et je l'ai obtenu jusqu'ici - avec une conversion implicite (String -> Atom):
("A" and "B") implies "C"
Les fonctions « et » et « implique » (et « ou » et « équivalent ») sont des méthodes simples qui appellent le constructeur de la classe de cas pertinents. Cependant, la mise en œuvre « non », je suis bloqué avec l'une des deux notations suivantes:
("A" and "B").not
Not("A" and "B")
Yat-il un moyen de tromper Scala à accepter le choix:
not("A" and "B")
sans renommer la De préférence classe « Non » à « non », parce que je pourrais appeler cela « ¬ » ou autre chose, dans l'avenir e.
La solution
Au mois de février 2014, je pense que la plus propre façon de définir une opération de not
prefix'ish sur les expressions, tout en évitant toutes sortes de cochonneries supplémentaire / emballage, serait de déclarer la fonction directement dans le cadre de l'emballage, ainsi que tous vos d'autres fonctions, classes, types etc: Ceci est fait en définissant un objet de package (Scala ne vous permet pas de simplement mettre des fonctions au niveau de la racine du fichier .scala
(j'aimerais savoir pourquoi-est-il juste de suivre de Java traces?)).
package org.my.logiclib
implicit class Atom(s: String) { ... }
class MyType1
class MyType2
object `package` {
def not(expr: Expr) = ...
}
De cette façon, faire import org.my.logiclib._
importera tout, y compris not()
.
ci-dessus est le même que
package org.my
package logiclib {
implicit class Atom ...
...
def not(expr: Expr) = ...
}
Autres conseils
Je remarque sur cette réponse à une autre question que il semble que l'on peut préfixer le nom de l'opérateur avec unary_
à achive ce que vous essayez de faire. (Voir unary_!
.)
Edit:. cet article confirme la syntaxe
Vous pouvez définir not
comme une méthode sur un objet singleton, comme ceci:
object Logic {
def not(x:Expr) = Not(x)
}
import Logic._
not("A" and "B")
(où Expr
est censé être la superclasse commune de And
, Or
, Not
et Atom
)
Edit: Voici un exemple de la façon dont cela pourrait être utilisé avec une seule importation:
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"))
Pourquoi Not
au lieu de not
? Il n'y a rien pour vous empêcher de faire ceci:
object not {
def apply(expr: T) = ...
}
puis utilisez not("A" and "B")
.