【问题标题】:Rewrite Scala && to and将 Scala && 重写为 and
【发布时间】:2018-03-02 03:08:12
【问题描述】:

我正在尝试通过以下方式将 Scala 的 && 重写为 and(我喜欢 python,这就是我尝试这样做的原因):

def and(p1: () => Boolean, p2: () => Boolean): Boolean = p1() && p2()

但是,当我尝试使用它时,例如:

def and(p1: () => Boolean, p2: () => Boolean): Boolean = p1() && p2()
if ((l < h.length) and (h(l) > h(i)))

(我把def放在前面只是为了调试,以确保它不是可见性问题),我得到:

Error:(40, 26) value and is not a member of Boolean
  if ((l < h.length) and (h(l) > h(i)))

这是怎么回事???

【问题讨论】:

  • 如所示 and 不是 Boolean 的成员,定义其第一个参数为 () =&gt; Boolean 不会使其成为 Boolean 类型的成员
  • @cchantep - 好点...所以我必须以某种方式编写implicit 以使and 可与Boolean 一起使用?
  • 通常隐式转换过于自动化,降低可读性
  • 请记住,and&amp;&amp; 具有不同的优先级。将一个更改为另一个可能会改变程序的含义。可能不是一个好主意。
  • @AlvaroCarrasco - 是的,我确实注意到优先级不一样。有什么方法可以在 Scala 中操纵运算符的优先级(我认为没有)?

标签: scala


【解决方案1】:

做你想做的事情的方法是这样的:

  object Pythonians {
    implicit class Bool(val b: Boolean) extends AnyVal { 
      def and(p: => Boolean) = b && p
    }
  }

现在您可以执行以下操作:

  import Pythonians._
  3 < 4 and "foo" == "bar"

但是,帮自己一个忙,而且……不要。 如果你这么“爱python”,为什么不用python写代码呢?如果您无论如何都花时间学习 scala,不妨尝试一下它自己的语法和习语……谁知道呢,也许您会变得更喜欢它而不是喜欢 python? 其他必须阅读您编写的代码的人会很高兴不必也了解全新的语言。

【讨论】:

  • 这里有问题。我试过了,它没有&amp;&amp;的语义,而是&amp;的语义:-)
  • @Frank 我不知道你在说什么。什么是“&& 的语义”,什么是“& 的语义”? &amp; 是位运算符。我不确定您所说的“语义”是什么意思,但这个and 绝对不是&amp;
  • 是的,&amp; 具有评估两侧的效果,而&amp;&amp; 不评估右侧,如果左侧为假 (stackoverflow.com/questions/25067702/scala-booleans-vs-vs)。上面提供的代码总是评估双方(我试过)。为了完美替换&amp;&amp;,如果左侧评估为假,则不应评估右侧。
  • @Frank 不,它不评估双方。您“尝试”了一些错误:)
  • 我收回我的评论:我对您的代码进行了剪切和粘贴,但我不再看到右侧的评估。我一定是在某个地方出错了(可能是使用() =&gt; Boolean 而不是: =&gt; Boolean)。
【解决方案2】:

根据您的定义,您可以将其称为

and(() => l < h.length, () => h(l) > h(i))

由于参数的类型为() =&gt; Boolean,这就是您需要传递的,而不是Boolean。 Scala 有特殊的语法来解决这个所谓的按名称参数,您可以在 Dima 的回答中看到。使用它(但没有隐式转换),你会写

def and(p1: => Boolean, p2: => Boolean): Boolean = p1 && p2
and(l < h.length, h(l) > h(i))

这意味着您将Boolean 类型的表达式作为参数传递,但它不是像往常一样在调用方法之前 计算,而是在使用它的地方计算。因此,在这种情况下,如果 p1 评估为 false,则永远不会评估 p2,就像 &amp;&amp; 一样。

【讨论】:

  • 这不是我观察到的——或者我在某处犯了错误。我使用了该代码并得到了一个与评估 and 的左侧和右侧相关的错误。我会回去仔细检查,我一定是在什么地方弄错了。
  • 见上文,我一开始的语法有误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 2022-01-22
  • 2014-02-05
  • 2021-02-25
  • 2021-11-14
相关资源
最近更新 更多