Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何创建模拟点的自定义运算符(无括号)?_Scala - Fatal编程技术网

Scala 如何创建模拟点的自定义运算符(无括号)?

Scala 如何创建模拟点的自定义运算符(无括号)?,scala,Scala,让我们看看下面的代码: scala>case类Num(n:Int){def inc=Num(n+1)} 定义类数 scala>隐式类管道(n:Num){def |=n} 定义类管道 这项工作: scala>(Num(0)|)公司 res7:Num=Num(1) 但是,是否有可能在不修改Num类的情况下(可能是隐式的还是宏?)让Scala以与带括号的代码相同的方式运行下面的示例 scala>Num(0)| inc :11:错误:Num不接受参数 Num(0)公司 ^ 结果是: scala>N

让我们看看下面的代码:

scala>case类Num(n:Int){def inc=Num(n+1)}
定义类数
scala>隐式类管道(n:Num){def |=n}
定义类管道
这项工作:

scala>(Num(0)|)公司
res7:Num=Num(1)
但是,是否有可能在不修改
Num
类的情况下(可能是隐式的还是宏?)让Scala以与带括号的代码相同的方式运行下面的示例

scala>Num(0)| inc
:11:错误:Num不接受参数
Num(0)公司
^
结果是:

scala>Num(0)inc | inc
res8:Num=Num(2)

编辑:
这里的代码更接近真实情况。我希望这是可以理解的

object ApplyTroubles2 extends App {

  import GrepOption.GrepOption

  abstract class Builder {
    var parent: Builder = null

    def getOutput: String

    def append(ch: Builder) = { ch.parent = this; ch }

    def echo(s: String) = append(new Echo(s))

    def wc() = append(new Wc())

    def grep(s: String, opts: Set[GrepOption]) = append(new Grep(s, opts))

    def grep(s: String) = append(new Grep(s))
  }

  object MainBuilder extends Builder {
    def getOutput: String = ""

    override def append(ch: Builder): Builder = ch
  }

  class Echo(data: String) extends Builder {
    def getOutput = data
  }

  class Wc() extends Builder {
    def getOutput = parent.getOutput.size.toString
  }

  class Grep(var pattern: String, options: Set[GrepOption]) extends Builder {
    def this(pattern: String) = this(pattern, Set.empty)

    val isCaseInsensitive = options.contains(GrepOption.CASE_INSENSITIVE)

    if (isCaseInsensitive) pattern = pattern.toLowerCase

    def getOutput = {
      val input = if (isCaseInsensitive) parent.getOutput.toLowerCase else parent.getOutput
      if (input.contains(pattern)) input
      else ""
    }
  }

  object GrepOption extends Enumeration {
    type GrepOption = Value
    val CASE_INSENSITIVE = Value
  }

  object BuilderPimps {
    //    val wc: Builder => Builder = x => x.wc()
    //    def echo(msg: String): Builder => Builder = x => x.echo(msg)
  }

  implicit class BuilderPimps(b: Builder) {
    // as suggested in one answer, should solve calling an apply method
    //    def |(fn: Builder => Builder): Builder = fn(b)

    def | : Builder = b

    def getStringOutput: String = b.getOutput

    def >> : String = getStringOutput
  }

  import MainBuilder._

  // working
  println(echo("xxx").wc().getOutput)
  println(echo("str") getStringOutput)
  println((echo("y") |) wc() getStringOutput)
  println(((((echo("y") |) echo ("zz")) |) wc()) >>)
  println(((echo("abc") |) grep ("b")) >>)
  println((echo("aBc") |) grep("AbC", Set(GrepOption.CASE_INSENSITIVE)) getStringOutput)

  // not working
  println((echo("yyyy") | wc()) getStringOutput)
  println(echo("yyyy") | wc() getStringOutput)
  println((echo("y")|) grep("y") >>)
  println(echo("x") | grep("x") | wc() >>)
}

我意识到想要的操作符在功能上并没有增加额外的价值,它应该只是一个语法糖,让事情看起来更好(在这个例子中,我试图模仿shell管道)。

后缀vs中缀

让我们首先看看中缀和后缀符号是如何相互关联的。如果您在编写
Num(0)|inc
时遇到这种情况,那么这相当于后缀符号中的
Num(0)。|(inc)

因此,看看您想要的语法:

Num(0) | inc | inc
这将等同于以下后缀符号:

Num(0).|(inc).|(inc)
好了,现在清楚了,让我们开始吧

解决方案

def |
需要获取一个参数,该参数保存它应该执行的函数。这里有两种解决方案,或者我们在
Num
上定义一个函数,或者我们在
Int
上定义一个函数
Num
实际上包含:

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}
两者都可以——你需要选择哪一个最适合你

现在我们有了这个,我们需要定义这个函数。您可以将其放入
Num
的伴生对象中(还提供了两种不同的实现):

看来我们结束了。现在我们只需要从对象导入这些函数并使用它们。整个代码:

case class Num(n:Int)
object Num {
  val incNum: Num => Num = n => Num(n.n + 1)
  val inc = (i: Int) => i + 1
}

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}

import Num._
Num(0) | inc | inc         // Num(2)
Num(0) | incNum | incNum   // Num(2)

后缀vs中缀

让我们首先看看中缀和后缀符号是如何相互关联的。如果您在编写
Num(0)|inc
时遇到这种情况,那么这相当于后缀符号中的
Num(0)。|(inc)

因此,看看您想要的语法:

Num(0) | inc | inc
这将等同于以下后缀符号:

Num(0).|(inc).|(inc)
好了,现在清楚了,让我们开始吧

解决方案

def |
需要获取一个参数,该参数保存它应该执行的函数。这里有两种解决方案,或者我们在
Num
上定义一个函数,或者我们在
Int
上定义一个函数
Num
实际上包含:

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}
两者都可以——你需要选择哪一个最适合你

现在我们有了这个,我们需要定义这个函数。您可以将其放入
Num
的伴生对象中(还提供了两种不同的实现):

看来我们结束了。现在我们只需要从对象导入这些函数并使用它们。整个代码:

case class Num(n:Int)
object Num {
  val incNum: Num => Num = n => Num(n.n + 1)
  val inc = (i: Int) => i + 1
}

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}

import Num._
Num(0) | inc | inc         // Num(2)
Num(0) | incNum | incNum   // Num(2)

后缀vs中缀

让我们首先看看中缀和后缀符号是如何相互关联的。如果您在编写
Num(0)|inc
时遇到这种情况,那么这相当于后缀符号中的
Num(0)。|(inc)

因此,看看您想要的语法:

Num(0) | inc | inc
这将等同于以下后缀符号:

Num(0).|(inc).|(inc)
好了,现在清楚了,让我们开始吧

解决方案

def |
需要获取一个参数,该参数保存它应该执行的函数。这里有两种解决方案,或者我们在
Num
上定义一个函数,或者我们在
Int
上定义一个函数
Num
实际上包含:

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}
两者都可以——你需要选择哪一个最适合你

现在我们有了这个,我们需要定义这个函数。您可以将其放入
Num
的伴生对象中(还提供了两种不同的实现):

看来我们结束了。现在我们只需要从对象导入这些函数并使用它们。整个代码:

case class Num(n:Int)
object Num {
  val incNum: Num => Num = n => Num(n.n + 1)
  val inc = (i: Int) => i + 1
}

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}

import Num._
Num(0) | inc | inc         // Num(2)
Num(0) | incNum | incNum   // Num(2)

后缀vs中缀

让我们首先看看中缀和后缀符号是如何相互关联的。如果您在编写
Num(0)|inc
时遇到这种情况,那么这相当于后缀符号中的
Num(0)。|(inc)

因此,看看您想要的语法:

Num(0) | inc | inc
这将等同于以下后缀符号:

Num(0).|(inc).|(inc)
好了,现在清楚了,让我们开始吧

解决方案

def |
需要获取一个参数,该参数保存它应该执行的函数。这里有两种解决方案,或者我们在
Num
上定义一个函数,或者我们在
Int
上定义一个函数
Num
实际上包含:

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}
两者都可以——你需要选择哪一个最适合你

现在我们有了这个,我们需要定义这个函数。您可以将其放入
Num
的伴生对象中(还提供了两种不同的实现):

看来我们结束了。现在我们只需要从对象导入这些函数并使用它们。整个代码:

case class Num(n:Int)
object Num {
  val incNum: Num => Num = n => Num(n.n + 1)
  val inc = (i: Int) => i + 1
}

implicit class Pipe(n:Num){
  def |(fn: (Num) => Num) = fn(n)
  def |(fn: (Int) => Int) = Num(fn(n.n))
}

import Num._
Num(0) | inc | inc         // Num(2)
Num(0) | incNum | incNum   // Num(2)
来自Akos Krivachy的答案非常接近,但由于我无法将我的完整解决方案附加到它,我必须创建一个新的单独答案(SO的这一特性对我来说似乎有点奇怪)

来自Akos Krivachy的答案非常接近,但由于我无法将我的完整解决方案附加到它,我必须创建一个新的单独答案(SO的这一特性对我来说似乎有点奇怪)

来自Akos Krivachy的答案非常接近,但由于我无法将我的完整解决方案附加到它,我必须创建一个新的单独答案(SO的这一特性对我来说似乎有点奇怪)

来自Akos Krivachy的消息非常接近,但由于我无法附加我的com