=> 和有什么区别? 、()=>、单位=>
我试图表示一个不带参数且不返回任何值的函数(如果您必须知道的话,我正在用 JavaScript 模拟 setTimeout 函数。)
case class Scheduled(time : Int, callback : => Unit)
无法编译,说“‘val’参数可能不会被调用-name"
case class Scheduled(time : Int, callback : () => Unit)
编译,但必须奇怪地调用,而不是
Scheduled(40, { println("x") } )
我必须这样做
Scheduled(40, { () => println("x") } )
什么也有效,
class Scheduled(time : Int, callback : Unit => Unit)
但以一种甚至不太明智的方式调用
Scheduled(40, { x : Unit => println("x") } )
(Unit 类型的变量会是什么?)我 Want 当然是一个构造函数,可以按照我调用它的方式调用它(如果它是一个普通函数):
Scheduled(40, println("x") )
给宝宝他的瓶子!
I'm trying to represent a function that takes no arguments and returns no value (I'm simulating the setTimeout function in JavaScript, if you must know.)
case class Scheduled(time : Int, callback : => Unit)
doesn't compile, saying " `val' parameters may not be call-by-name"
case class Scheduled(time : Int, callback : () => Unit)
compiles, but has to be invoked strangely, instead of
Scheduled(40, { println("x") } )
I have to do this
Scheduled(40, { () => println("x") } )
What also works is
class Scheduled(time : Int, callback : Unit => Unit)
but is invoked in an even-less-sensible way
Scheduled(40, { x : Unit => println("x") } )
(What would a variable of type Unit be?) What I want of course is a constructor that can be invoke the way I would invoke it if it were an ordinary function:
Scheduled(40, println("x") )
Give baby his bottle!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
按姓名呼唤: =>输入
=>类型
表示法代表按名称调用,这是多种方式之一可以传递参数。如果您不熟悉它们,我建议花一些时间阅读维基百科文章,尽管现在它主要是按值调用和按引用调用。这意味着传递的内容将替换函数内的值名称。例如,采用这个函数:
如果我像这样调用它
那么代码将像这样执行
虽然这提出了如果存在标识符名称冲突会发生什么的问题。在传统的按名称调用中,会发生一种称为避免捕获替换的机制来避免名称冲突。然而,在 Scala 中,这是以另一种方式实现的,具有相同的结果——参数内的标识符名称不能引用或隐藏被调用函数中的标识符。
还有一些与直呼姓名相关的要点,我将在解释完其他两点之后再谈。
0 元函数: () =>类型
语法
() =>; Type
代表Function0
的类型。也就是说,一个不带参数并返回某些内容的函数。这相当于调用方法size()
——它不带参数并返回一个数字。然而有趣的是,这种语法与匿名函数文字的语法非常相似,这导致了一些混乱。例如,
是一个 arity 0 的匿名函数字面量,其 type 是
所以我们可以这样写:
但是,重要的是不要将类型与值混淆。
单位=>类型
这实际上只是一个
Function1
,其第一个参数的类型为Unit
。其他编写方式为(Unit) =>类型
或Function1[单位,类型]
。问题是……这不太可能是人们想要的。Unit
类型的主要目的是指示一个人们不感兴趣的值,因此接收该值没有意义。例如,考虑一下,
人们可以用
x
做什么?它只能有一个值,因此不需要接收它。一种可能的用途是链接返回Unit
的函数:因为
andThen
仅在Function1
上定义,并且我们链接的函数返回Unit
,我们必须将它们定义为Function1[Unit, Unit]
类型才能链接它们。混乱的来源
第一个混乱的来源是认为 0 元函数中存在的类型和文字之间的相似性也存在于按名称调用中。换句话说,认为,because
是
() => 的文字。 Unit
则将是
=> 的文字单位
。它不是。这是一个代码块,而不是文字。另一个令人困惑的来源是
Unit
类型的 value 被写成()
,它看起来像一个 0 元参数列表(但事实并非如此) 。Call-by-Name: => Type
The
=> Type
notation stands for call-by-name, which is one of the many ways parameters can be passed. If you aren't familiar with them, I recommend taking some time to read that wikipedia article, even though nowadays it is mostly call-by-value and call-by-reference.What it means is that what is passed is substituted for the value name inside the function. For example, take this function:
If I call it like this
Then the code will execute like this
Though that raises the point of what happens if there's a identifier name clash. In traditional call-by-name, a mechanism called capture-avoiding substitution takes place to avoid name clashes. In Scala, however, this is implemented in another way with the same result -- identifier names inside the parameter can't refer to or shadow identifiers in the called function.
There are some other points related to call-by-name that I'll speak of after explaining the other two.
0-arity Functions: () => Type
The syntax
() => Type
stands for the type of aFunction0
. That is, a function which takes no parameters and returns something. This is equivalent to, say, calling the methodsize()
-- it takes no parameters and returns a number.It is interesting, however, that this syntax is very similar to the syntax for a anonymous function literal, which is the cause for some confusion. For example,
is an anonymous function literal of arity 0, whose type is
So we could write:
It is important not to confuse the type with the value, however.
Unit => Type
This is actually just a
Function1
, whose first parameter is of typeUnit
. Other ways to write it would be(Unit) => Type
orFunction1[Unit, Type]
. The thing is... this is unlikely to ever be what one wants. TheUnit
type's main purpose is indicating a value one is not interested in, so doesn't make sense to receive that value.Consider, for instance,
What could one possibly do with
x
? It can only have a single value, so one need not receive it. One possible use would be chaining functions returningUnit
:Because
andThen
is only defined onFunction1
, and the functions we are chaining are returningUnit
, we had to define them as being of typeFunction1[Unit, Unit]
to be able to chain them.Sources of Confusion
The first source of confusion is thinking the similarity between type and literal that exists for 0-arity functions also exists for call-by-name. In other words, thinking that, because
is a literal for
() => Unit
, thenwould be a literal for
=> Unit
. It is not. That is a block of code, not a literal.Another source of confusion is that
Unit
type's value is written()
, which looks like a 0-arity parameter list (but it is not).case
修饰符使构造函数的每个参数隐含val
。因此(正如有人指出的)如果您删除case
您可以使用按名称调用参数。无论如何,编译器可能会允许它,但如果它创建val 回调
而不是转变为lazy val 回调
,人们可能会感到惊讶。当您更改为
callback: () =>;现在你的案例只需要一个函数而不是一个按名称调用的参数。显然该函数可以存储在
valcallback
中,所以没有问题。获得所需内容的最简单方法(
Scheduled(40, println("x") )
,其中使用按名称调用参数传递 lambda)可能是跳过case
并显式创建您一开始无法获得的apply
:在使用中:
The
case
modifier makes implicitval
out of each argument to the constructor. Hence (as someone noted) if you removecase
you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it createdval callback
instead of morphing intolazy val callback
.When you change to
callback: () => Unit
now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored inval callback
so there's no problem.The easiest way to get what you want (
Scheduled(40, println("x") )
where a call-by-name parameter is used to pass a lambda) is probably to skip thecase
and explicitly create theapply
that you couldn't get in the first place:In use:
在问题中,您想在 JavaScript 中模拟 SetTimeOut 函数。根据之前的答案,我编写了以下代码:
在REPL中,我们可以得到这样的结果:
我们的模拟与SetTimeOut的行为并不完全相同,因为我们的模拟是阻塞函数,但SetTimeOut是非阻塞的。
In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:
In REPL, we can get something like this:
Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.
我这样做(只是不想打破应用):
并调用它
I do it this way (just don't want to break apply):
and call it