【问题标题】:Scala method = trait { ... } meaningScala 方法 = trait { ... } 含义
【发布时间】:2013-11-26 14:48:50
【问题描述】:

我正在尝试同时学习 Scala 和 Play Framework。 Scala 在我看来有很多非常酷的想法,但我的挫败感之一是试图理解方法/函数/lambdas/匿名函数/等的所有不同语法。

所以我的主应用程序控制器是这样的:

object Application extends Controller {
  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }
}

这告诉我我有一个单例Application,它有一个方法index,它返回什么类型?我期待index 的定义更像:

def index(req: Request) : Result = { ... }

查看 Play Framework 的文档,似乎 Action 是一个特征,它将请求转换为结果,因为我很难理解这行在说什么:

def index = Action { ... }

我来自 Java 背景,所以我不知道这是在说什么? (这句话感觉就像是在说“method index = [some interface Action]”,这对我来说没有意义;似乎一些美好的事情正在发生,但它对我来说很神奇,而且我对我的代码中的魔法感到不安;))

【问题讨论】:

  • 我试图理解这一点的另一个打击:def index = Action { ... } 类似于说index = new Action { _interface implementation here_ }(例如,Java 中的匿名接口实例化)?
  • 我分享你在语法上不知所措的感觉。其他一切都是泥泞的时候有几个工具:使用调试器单步执行,以及 -Xprint:all 使用编译器。

标签: function scala methods lambda traits


【解决方案1】:

当您像调用函数一样调用对象时,它会转换为对apply 的调用。即:

foo(bar)

被翻译成

foo.apply(bar)

因此,在 index 内部,您正在调用 Action 对象,就好像它是一个函数一样,这意味着您实际上在调用 Action.apply

index 的返回类型被省略了,因为编译器可以推断它是Action.apply 的返回类型(我从名字猜想是Unit)。

【讨论】:

  • 酷。感谢您花时间解释。这开始变得有意义了。查看此页面:playframework.com/documentation/2.2.x/api/scala/… 似乎Action.apply 返回Future[SimpleResult]?但是如果我把它放在我对index 的定义中,它就不会编译(但正如你所建议的,Unit 可以)。这里发生了什么?还有,Action也定义了abstract parser: BodyParser[A],我怎么根本不需要定义这个方法?
  • 我认为他真的在为 Action 同伴的匿名子类调用 apply 是正确的吗?如果是这样,那对我们这些 Java 专家来说就容易多了。
  • 花括号是参数的替代语法。您可以在圆括号或花括号中传递参数。在花括号中传递旨在作为代码块的参数是很常见的,以使它们看起来像代码块。
  • @JörgWMittag 花括号不是括号的替代品。花括号只是简单地包装一段代码并组成一个表达式,然后可以作为参数传递。
  • 令人着迷。所以让我一步一步来确保我理解:def index = Action { ... } 说“索引是调用Action.apply({...}) 返回的函数。也就是说,代码块{...} 正在传递给Action.apply
【解决方案2】:

所以对这个问题的简短回答是,在幕后发生了一些事情,使上述工作得以实现:即编译器正在推断类型,而在 Scala 中,可以像调用 apply 方法一样调用对象它们是函数。

所以这里发生的是这段代码:

def index = Action {
  Ok("Hello World!")
}

...等价于(或者更确切地说是简写)这段代码:

def index : Action[AnyContent] = Action.apply(
    (req: Request[AnyContent]) => {
        Ok(views.html.index("Hello World!"))
    } : Result
)

魔法在这里发生:... = Action {...}Action {...} 表示“使用此匿名函数 {...} 调用 Action”。

因为Action.apply 被定义为apply(block: => Result): Action[AnyContent],所以可以推断出所有的argument-/return- 类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多