为什么 Scala 除了零参数方法还需要无参数? [英] Why does Scala need parameterless in addition to zero-parameter methods?

查看:23
本文介绍了为什么 Scala 除了零参数方法还需要无参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解零参数方法和无参数方法之间的区别,但我真正不明白的是使无参数方法成为必需的语言设计选择.

I understand the difference between zero-parameter and parameterless methods, but what I don't really understand is the language design choice that made parameterless methods necessary.

我能想到的缺点:

  • 令人困惑.每隔一两周,这里或 Scala 邮件列表上都会有关于它的问题.
  • 这很复杂;我们还必须区分 () =>X=>X.
  • 这是模棱两可的:x.toFoo(y) 的意思是它所说的,还是 x.toFoo.apply(y)?(答案:这取决于xtoFoo方法和Fooapply方法的重载> 方法,但如果发生冲突,您在尝试调用它之前不会看到错误.)
  • 它弄乱了操作符风格的方法调用语法:在链接方法时或在末尾避免分号干扰时,没有可以用来代替参数的符号.使用零参数方法,您可以使用空参数列表 ().
  • It's confusing. Every week or two there are questions here or on the Scala mailing list about it.
  • It's complicated; we also have to distinguish between () => X and => X.
  • It's ambiguous: does x.toFoo(y) mean what it says, or x.toFoo.apply(y)? (Answer: it depends on what overloads there are x's toFoo method and the overloads on Foo's apply method, but if there's a clash you don't see an error until you try to call it.)
  • It messes up operator style method calling syntax: there is no symbol to use in place of the arguments, when chaining methods, or at the end to avoid semicolon interference. With zero-arg methods you can use the empty parameter list ().

目前,您不能在一个类中同时定义两者:您会收到一条错误消息,指出该方法已被定义.它们也都转换为 Function0.

Currently, you can't have both defined in a class: you get an error saying the method is already defined. They also both convert to a Function0.

为什么不让方法 def foodef foo() 完全相同,并允许它们带或不带括号被调用?它的优点是什么?

Why not just make methods def foo and def foo() exactly the same thing, and allow them to be called with or without parentheses? What are the upsides of how it is?

推荐答案

Currying, That's Why

Daniel 在解释为什么需要无参数方法方面做得很好.我将解释为什么将它们与零参数方法区别开来.

Currying, That's Why

Daniel did a great job at explaining why parameterless methods are necessary. I'll explain why they are regarded distinctly from zero-parameter methods.

许多人将无参数函数和零参数函数之间的区别视为某种语法糖的模糊形式.事实上,它纯粹是 Scala 如何支持柯里化的产物(为了完整起见,请参阅下文以更全面地解释柯里化是什么,以及为什么我们都如此喜欢它).

Many people view the distinction between parameterless and zero-parameter functions as some vague form of syntactic sugar. In truth it is purely an artifact of how Scala supports currying (for completeness, see below for a more thorough explanation of what currying is, and why we all like it so much).

形式上,一个函数可能有零个或多个参数列表,每个参数列表有零个或多个参数.
这意味着以下是有效的:def adef b(),还有人为的 def c()()def d(x: Int)()()(y: Int) 等等...

Formally, a function may have zero or more parameter lists, with zero or more parameters each.
This means the following are valid: def a, def b(), but also the contrived def c()() and def d(x: Int)()()(y: Int) etc...

函数 def foo = ??? 有零个参数列表.一个函数 def bar() = ??? 正好有一个参数列表,参数为零.引入将这两种形式混为一谈的附加规则会破坏柯里化作为一致的语言特性:def a 在形式上等同于 def b()def c()() 两者;def d(x: Int)()()(y: Int) 等价于 def e()(x: Int)(y: Int)()()代码>.

A function def foo = ??? has zero parameter lists. A function def bar() = ??? has precisely one parameter list, with zero parameters. Introducing additional rules that conflate the two forms would have undermined currying as a consistent language feature: def a would be equivalent in form to def b() and def c()() both; def d(x: Int)()()(y: Int) would be equivalent to def e()(x: Int)(y: Int)()().

柯里化无关的一种情况是在处理 Java 互操作时.Java 不支持柯里化,因此为 "test".length()(直接调用 java.lang.String#length() 等零参数方法引入语法糖是没有问题的)) 也可以作为 "test".length 调用.

One case where currying is irrelevant is when dealing with Java interop. Java does not support currying, so there's no problem with introducing syntactic sugar for zero-parameter methods like "test".length() (which directly invokes java.lang.String#length()) to also be invoked as "test".length.

Scala 支持一种名为currying"的语言功能,以数学家 Haskell Curry 的名字命名.
柯里化允许您定义具有多个参数列表的函数,例如:

Scala supports a language feature called 'currying', named after mathematician Haskell Curry.
Currying allows you to define functions with several parameter lists, e.g.:

def add(a: Int)(b: Int): Int = a + b
add(2)(3) // 5

这很有用,因为您现在可以根据 add 的部分应用来定义 inc:

This is useful, because you can now define inc in terms of a partial application of add:

def inc: Int => Int = add(1)
inc(2) // 3

柯里化最常被视为通过库引入控制结构的一种方式,例如:

Currying is most often seen as a way of introducing control structures via libraries, e.g.:

def repeat(n: Int)(thunk: => Any): Unit = (1 to n) foreach { _ => thunk }

repeat(2) {
  println("Hello, world")
}

// Hello, world
// Hello, world

回顾一下,看看 repeat 如何打开另一个使用柯里化的机会:

As a recap, see how repeat opens up another opportunity to use currying:

def twice: (=> Any) => Unit = repeat(2)

twice {
  println("Hello, world")
}

// ... you get the picture :-)

这篇关于为什么 Scala 除了零参数方法还需要无参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆