被 FoldLeft 错误困惑(在 Eclipse 和 REPL 中)

2023-11-26

其背景非常简单。我的假设基于 Odersky 的书“Programming in Scala, 2nd Edition”,第 8.5 节描述了“占位符语法”。

我有一个 List[List[Boolean]] (即矩形位图),我试图在其中计算值“true”的总出现次数。这是定义执行良好的数据的 REPL 行:

val rowsByColumns =
    List(   List(false, true, false)
          , List(true, true, true)
          , List(false, true, false)
        )

接下来,我尝试使用以下行来计算“true”的出现次数。我没有执行,而是收到一个错误:

val marks = (for(row <- rowsByColumns)
    yield {row.foldLeft[Int](0)(_ + (if (_) 1 else 0))}).sum

<console>:8: error: wrong number of parameters; expected = 2
       val marks = (for(row <- rowsByColumns) yield {row.foldLeft[Int](0)(_ + (i
f (_) 1 else 0))}).sum
                                                                        ^

我不明白这个错误,因为我有两个下划线代表函数的参数。因此,我通过编写执行得很好的代码来使该函数更加明确:

val marks = (for(row <- rowsByColumns)
      yield {row.foldLeft[Int](0)((sum, marked) => sum + (if (marked) 1 else 0))}
    ).sum

我的问题是:为什么我会收到不太明确的情况的错误,但是当我通过减少“简化”来映射函数时,它会正确执行?

感谢您就此问题向我提供的任何见解。


Scala 的占位符语法对匿名函数的限制可能非常令人困惑(至少对我来说)。一个经验法则是下划线绑定到最近的括号,但这是一个近似值 - 请参阅第 6.23 节Scala 规范详细信息:

一种表达e属于句法范畴Expr binds下划线 部分u,如果满足以下两个条件: (1)e适当地 包含u,并且(2)没有其他句法表达 类别Expr它正确地包含在e以及它本身 正确包含u.

在这种情况下,编译器不会将第二个下划线视为第二个参数。这可能看起来很奇怪,因为_ + _被正确地视为具有两个参数,并且if (_) x else y相当于z => if (z) x else y (where z是一个新的标识符),但是嵌套两者不起作用。

编译器确实如此could理论上讲,两个下划线应该是您的同一个匿名函数的参数foldLeft,但不是,例如,在下面,第二个下划线确实需要单独绑定:

rowsByColumns.map(_.map(!_))

不过,这需要编译器付出很多额外的聪明才智,Scala 语言设计者认为这不值得——只需要为一些相当简单的情况提供占位符语法,而无需嵌套表达式。


幸运的是,在这种情况下你可以写rowsByColumns.flatten.count(identity)反而。flatten这里连接子列表以给出单个List[Boolean]。然后我们想知道该列表中有多少个值true. count采用谓词并告诉您集合中有多少值满足该谓词。例如,以下是计算 1 到 10(含)之间偶数的一种方法:

val isEven: Int => Boolean = _ % 2 == 0    
(1 to 10) count isEven

不过,在您的情况下,我们已经有了布尔值,因此谓词不需要做任何工作 - 它可以只是恒等函数x => x。正如 dhg 在评论中指出的那样,Scala 的Predef object将此作为名为的方法提供identity,我在这里使用的。你可以很容易地写rowsByColumns.flatten.count(x => x)不过,如果你发现这一点更清楚的话。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

被 FoldLeft 错误困惑(在 Eclipse 和 REPL 中) 的相关文章

  • Spark Scala:按小时或分钟计算两列的 DateDiff

    我在数据框中有两个时间戳列 我想获取它们的分钟差异 或者小时差异 目前我可以通过四舍五入获得日差 val df2 df1 withColumn time datediff df1 ts1 df1 ts2 但是 当我查看文档页面时https
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • 映射存在类型列表

    我有一个要映射的存在类型对象的列表 像这样的东西 sealed abstract class IntBox val v Int case object IB1 extends IntBox 1 case object IB2 extends
  • Spark - scala - 如何检查配置单元中是否存在表

    我必须使用 Spark 1 6 2 scala 检查配置单元中是否存在表 如果没有 我必须创建一个空数据框并将其保存为配置单元表 如果存在 则覆盖现有表 我需要一个返回布尔值的函数 基于该函数我可以做出上述决定 是否创建新表或覆盖现有表 1
  • Joda Time 类没有任何构造函数...为什么?我做错了什么?

    显然 Eclipse 上的 Scala 试图让我相信DateTime Period DateMidnightJoda Time 中的许多其他类没有任何构造函数 考虑到它们的文档显示了构造函数和许多方法 这很奇怪 我唯一可以访问的是静态方法
  • 覆盖 Predef 的隐式转换

    我有多个返回 java lang Integer 的方法 然后使用 Scala 的 Predef 隐式转换将其隐式转换为 Int 下面是它的编写方式there https github com scala scala blob v2 11
  • 以编程方式启动 Scala REPL?

    我想从命令行启动 Scala Swing 应用程序 然后在应用程序启动后 放入 Scala REPL 中以用作控制界面 理想情况下 我还想预先绑定一些变量名称 更好的是使用 REPL 的 Java2D 终端模拟器 但我找不到任何合适的东西
  • Scala:如何将可变参数指定为类型?

    代替 def foo configuration String String 我希望能够写 type Configuration String String def foo configuration Configuration 主要用例是
  • HashPartitioner 是如何工作的?

    我阅读了文档HashPartitioner http spark apache org docs 1 3 1 api java index html org apache spark HashPartitioner html 不幸的是 除了
  • 更改 build.sbt 自定义任务中的版本

    我在 build sbt 中定义了一个自定义任务 val doSmth taskKey Unit smth doSmth version 1 0 SNAPSHOT 但它不会改变版本 我真正想要的是自定义 sbt 发布任务 它将始终将相同的版
  • 模拟 BlazeClientBuilder[IO] 以返回模拟客户端[IO]

    我正在使用BlazeClientBuilder IO resource方法得到Client IO 现在 我想模拟客户端进行单元测试 但不知道该怎么做 有没有一个好的方法来嘲笑这个 我会怎么做 class ExternalCall val r
  • Spark SQL 失败,因为“常量池已超过 JVM 限制 0xFFFF”

    我在 EMR 4 6 0 Spark 1 6 1 上运行此代码 val sqlContext SQLContext getOrCreate sc val inputRDD sqlContext read json input try inp
  • Spark:如何使用crossJoin

    我有两个数据框 df1有 100000 行并且df2有 10000 行 我想创建一个df3这是两者的交叉连接 val df3 df1 crossJoin df2 这将产生 10 亿行 尝试在本地运行它 但似乎需要很长时间 您认为本地可以实现
  • Scala:什么是 CompactBuffer?

    我试图弄清楚 CompactBuffer 的含义 和迭代器一样吗 请解释其中的差异 根据 Spark 的文档 它是 ArrayBuffer 的替代方案 可以提供更好的性能 因为它分配的内存更少 以下是 CompactBuffer 类文档的摘
  • 为什么用scala写的代码比用java写的慢6倍?

    我不确定我在编写 scala 代码时是否犯了一些错误 问题是 The four adjacent digits in the 1000 digit number that have the greatest product are 9 9
  • andThen 类型不匹配的 Scala 链接函数

    我有一堆函数可以清理文本并将它们分成单词 最小的例子 val txt Mary had a little nlamb val stopwords Seq a def clean text String String text replace
  • 在 Scala 中将元素追加到列表末尾

    我无法添加 type 元素T到一个列表中List T 我尝试过myList myElement但它似乎创建了一个奇怪的对象并访问myList last始终返回放入列表中的第一个元素 我怎么解决这个问题 List 1 2 3 4 Result
  • 如何通过 javascript 和 ajax 调用 Scala 中的方法?

    我不知道我的标题是否有点误导 但这是我真正需要帮助的 我正在获取这个网址 get fb login fbEmail function data console log data 这是我的路线 GET fb login email prese
  • 如何执行仅匹配正则表达式的测试?

    在 sbt 0 10 1 中 我经常使用test only缩小我的测试数量 sbt gt test only com example MySpec 但是 我想缩小范围 以便只运行名称 描述与正则表达式匹配的测试 是否有一些语法可以实现这样的
  • 获取SettingKey[T]的值

    我正在开发一个用于文档生成的插件 我想将所有生成的文件输出到我选择的目录中 该目录可以是SBT的子目录target目录 如下 val newTargetDirectory SettingKey File document target di

随机推荐