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.

Était-ce utile?

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").

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top