Scala 用';别名';参数和非';别名';参数

Scala 用';别名';参数和非';别名';参数,scala,Scala,我有一个似乎是错误的假设。我过去的主要语言是C++,C++中我可以在伪:中做像这样的函数参数绑定。 // declaration void f(int param1, int param2); // usage func<void, int> boundfunc = bind(f, 1, _1) func(2) // equivalent to f(1, 2) 我希望s的定义能做它正在做的事情(即不调用“新X”),但我确实希望r的定义能调用它,因为f有X参数的基本定义(即非“按名

我有一个似乎是错误的假设。我过去的主要语言是C++,C++中我可以在伪:

中做像这样的函数参数绑定。
// declaration
void f(int param1, int param2);

// usage
func<void, int> boundfunc = bind(f, 1, _1)
func(2) // equivalent to f(1, 2)
我希望
s
的定义能做它正在做的事情(即不调用“新X”),但我确实希望
r
的定义能调用它,因为
f
X
参数的基本定义(即非“按名称”)

现在,正如我所说的,我显然遗漏了一些基本的FP概念,我希望很快纠正这些概念,但我也想知道是否有一种方法可以获得参数绑定的等价物,这样就不会重复调用
new X

(在barjak回答后编辑)

事实上,问题源于我在创建
r
s
时滥用
def
——我应该使用
val
,这使得调用
new X
发生在“绑定站点”

最后一件令人惊讶的事情是,当我们创建
s
时,
g
中的“byname”参数只解析一次,而不是显式地计算
s
时。(即,“构造”仅在定义
r
s
时打印,而不是在定义
r
和评估
s
时打印)

现在,我的假设是Scala正在做正确定义的事情,并将
x
绑定到第二个参数的结果,因此在
s
r
的上下文中,
x
是否为“byname”并不重要


我想,如果我想重复计算
x
,我需要的不仅仅是一个“byname”参数,而是一个显式的函数参数,它将在计算
s
时重复计算
r
用关键字
def
声明,这实际上意味着“为每个调用重新计算表达式”。我想您应该使用
val
关键字,它将为
X
的每个实例只计算表达式一次

val r = f(100)(new X)
val s = g(100)(new X)

否则,我认为您的解释是正确的。

r
是用关键字
def
声明的,这实际上意味着“为每个调用重新计算表达式”。我认为您应该使用
val
关键字,该关键字只为
X
的每个实例计算表达式一次

val r = f(100)(new X)
val s = g(100)(new X)

否则,我认为你的解释是正确的。

就我对名称参数的理解而言,
f
g

def f(limit: Int)(x: X) = x.r.nextInt(limit)
def g(limit: Int)(x: => X) = x.r.nextInt(limit) 
因为在正文定义中只计算一次
x

但是,如果您有一个循环左右,内部定义中的
x
可以被计算多个…然后在
f
a
new x
中只计算一次(在方法调用之前),但在
g
a
new x
中,随着循环的运行,计算频率将相同

/* using x in body twice (for demonstration only) */
def f(limit: Int)(x: X) = { x.r.nextInt(limit); x.r.nextInt(limit) }
def g(limit: Int)(x: => X) = { x.r.nextInt(limit); x.r.nextInt(limit) }
val r = f(100)(new X) /* prints "Constructing" only one time */
val s = g(100)(new X) /* prints "Constructing" twice */
r /* Doesn't print "Constructing" */
r /* Doesn't print "Constructing" */
s /* Doesn't print "Constructing" */
s /* Doesn't print "Constructing" */
最后,为了发挥currying的作用,您可能希望将
新的X
绑定到
X
,您可以在函数定义中交换参数列表,然后执行以下操作

def f(x: X)(limit: Int) = x.r.nextInt(limit)
val r = f(new X)_
val s = f(new X)_
r(100)
r(200)
s(100)
s(200)

其中,
r
s
是两个不同(独立)的随机流,由currying
f
(不需要按名称参数)构成。

就我按名称参数理解,
f
g

def f(limit: Int)(x: X) = x.r.nextInt(limit)
def g(limit: Int)(x: => X) = x.r.nextInt(limit) 
因为在正文定义中只计算一次
x

但是,如果您有一个循环左右,内部定义中的
x
可以被计算多个…然后在
f
a
new x
中只计算一次(在方法调用之前),但在
g
a
new x
中,随着循环的运行,计算频率将相同

/* using x in body twice (for demonstration only) */
def f(limit: Int)(x: X) = { x.r.nextInt(limit); x.r.nextInt(limit) }
def g(limit: Int)(x: => X) = { x.r.nextInt(limit); x.r.nextInt(limit) }
val r = f(100)(new X) /* prints "Constructing" only one time */
val s = g(100)(new X) /* prints "Constructing" twice */
r /* Doesn't print "Constructing" */
r /* Doesn't print "Constructing" */
s /* Doesn't print "Constructing" */
s /* Doesn't print "Constructing" */
最后,为了发挥currying的作用,您可能希望将
新的X
绑定到
X
,您可以在函数定义中交换参数列表,然后执行以下操作

def f(x: X)(limit: Int) = x.r.nextInt(limit)
val r = f(new X)_
val s = f(new X)_
r(100)
r(200)
s(100)
s(200)
其中,
r
s
是两个不同(独立)的随机流,由currying
f
构造(不需要按名称参数)