简体   繁体   English

如何解释用花括号括起来的 function 值(菊石问题)

[英]How to interpret function value wrapped in curly braces (ammonite issue)

After reading What is the formal difference in Scala between braces and parentheses, and when should they be used?看完Scala 大括号和圆括号的形式区别是什么,应该什么时候使用? , I still don't know how to understand function value wrapped in {} . ,我仍然不知道如何理解用{}包裹的 function 值。

Consider the following two REPL sessions:考虑以下两个 REPL 会话:

@ val f = { (x: Int) =>
    x
    val y = x
    y
  }
f: Int => Int = ammonite.$sess.cmd30$$$Lambda$1765/0x0000000801346840@24c7b944
@ { (x: Int) =>
    x
    val y = x
    y
  }
cmd31.sc:3: not found: value x
  val y = x
          ^
Compilation Failed

I have several questions.我有几个问题。

  1. Why the first snippet compiles while the second doesn't?为什么第一个片段编译而第二个不编译? In the first snippet, compiler knows the {...} as a whole is a function value.在第一个片段中,编译器知道{...}作为一个整体是一个 function 值。 In the second snippet, only the (x: Int) => \nx part is function value (Sorry about the \n to indicate line break).在第二个片段中,只有(x: Int) => \nx部分是 function 值(抱歉, \n表示换行符)。 Why?为什么?
  2. Regarding the { (x: Int) => \n... } , when is it interpreted as function value and when is it not?关于{ (x: Int) => \n... } ,它什么时候被解释为 function 值,什么时候不是?
  3. Is the curly brace ( {} ) part of the function value, or only (...) =>... inside is function value?花括号 ( {} ) 是 function 值的一部分,还是只有(...) =>...里面是 function 值? If it is a part it, does the form have a name?如果它是它的一部分,表格是否有名称? For example, I think (_ + _) could be called function value's placeholder syntax.例如,我认为(_ + _)可以称为 function 值的占位符语法。

Update: This is purely an Ammonite issue.更新:这纯粹是一个菊石问题。 See answer for detail.详情见答案。

The problem here is ammonite.这里的问题是菊石。

Scala REPL has a paste mode allowing you to paste multiple lines before evaluating: Scala REPL 具有粘贴模式,允许您在评估之前粘贴多行:

:paste
sealed trait X
class Implementation extends X // impossible without doing it at once
// Ctrl+D

Ammonite doesn't have such paste mode, but it allows you to perform multi-line copy paste... but wrapping them all in {} which ammonite would unwrap. Ammonite 没有这种粘贴模式,但它允许您执行多行复制粘贴......但是将它们全部包装在{}中,ammonite 会解开。 So your code:所以你的代码:

{ (x: Int) =>
  x
  val y = x
  y
}

is seen by compiler as编译器将其视为

(x: Int) =>
  x // end of function definition
val y = x // new variable calling x, which isn't defined anywhere
y // call to undefined y, because previous line failed

The first example works because you have val f = so ammonite's parser cannot assume that all of your code is within one block, so it doesn't strip it before passing it into compiler.第一个示例有效,因为您有val f =所以 ammonite 的解析器不能假设您的所有代码都在一个块内,因此它不会在将其传递给编译器之前将其剥离。

As docs suggest if you don't want this behavior you should add another layer of curly brackets:正如文档建议的那样,如果您不想要这种行为,您应该添加另一层大括号:

{{ (x: Int) =>
  x
  val y = x
  y
}}

This isn't a compiler and language specification issue as much as issue with some particular REPL implementation.这不是编译器和语言规范问题,而是某些特定 REPL 实现的问题。

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

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