简体   繁体   English

Scala - 前缀一元运算符

[英]Scala - Prefix Unary Operators

I've recently given Scala a second chance, and started with the project I always implement (in functional or pseudo-functional languages): an automated reasoner for propositional logic (and later predicate logic). 我最近给了Scala第二次机会,并从我总是实现的项目开始(在函数或伪函数语言中):命题逻辑(以及后来的谓词逻辑)的自动推理器。

Now, I've tried to get the notation of propositional logic in the language itself as pretty as possible, and I've gotten this far - with an implicit conversion (String -> Atom): 现在,我试图尽可能地在语言本身中获得命题逻辑的符号,并且我已经实现了这一点 - 使用隐式转换(String - > Atom):

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

The functions "and" and "implies" (and "or" and "equivalent") are simple methods that call the relevant case class constructor. 函数“和”和“暗示”(以及“或”和“等价”)是调用相关案例类构造函数的简单方法。 However, when implementing "not", I get stuck with either of the two following notations: 但是,在实现“not”时,我会遇到以下两种符号中的任何一种:

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

Is there a way to trick Scala into accepting the desired: 有没有办法欺骗Scala接受所需的:

not("A" and "B")

Preferrably without renaming the class "Not" to "not", because I might like to call it "¬" or something else, in th future. 最好不要将“Not”类重命名为“not”,因为我可能希望将来称之为“¬”或其他东西。

I noticed on this answer to another question that it appears that one can prefix the operator name with unary_ to achive what you are trying to do. 我注意到另一个问题的答案 ,看起来人们可以在运算符名称前加上unary_以达到你想要做的事情。 (See unary_! .) (见一unary_!

Edit: this article confirms the syntax. 编辑: 本文确认了语法。

You can define not as a method on a singleton object, like this: 您可以not单个对象上定义方法,如下所示:

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

(Where Expr is supposed to be the common superclass of And , Or , Not and Atom ) (其中Expr应该是AndOrNotAtom的常见超类)

Edit: Here's an example of how this could be used with only a single import: 编辑:这是一个例子,说明如何只使用一次导入:

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

Why Not instead of not ? 为什么Notnot There's nothing to stop you from doing this: 没有什么可以阻止你这样做:

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

And then use not("A" and "B") . 然后not("A" and "B")使用not("A" and "B")

As of Feb 2014, I think the cleanest way to define a prefix'ish not operation on expressions, while avoiding all sorts of extra cruft/wrapping, would be to declare the function directly in the package scope, together with all your other functions, classes, types etc: This is done by defining a package object (Scala doesn't allow you to just put functions at the root level of the .scala file (I'd love to learn why—is it just to follow Java's footsteps?)). 截至2014年2月,我认为最简单的方法是在表达式上定义一个前缀' not operation,同时避免各种额外的cruft /包装,将是直接在包范围内声明函数,以及所有其他函数,类,类型等:这是通过定义一个包对象来完成的(Scala不允许你只将函数放在.scala文件的根级别(我很想知道为什么 - 它只是跟随Java的脚步? ))。

package org.my.logiclib

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

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

this way, doing import org.my.logiclib._ will import everything, including not() . 这样,执行import org.my.logiclib._将导入所有内容,包括not()

The above is the same as 以上是相同的

package org.my

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM