我有一个函数文字
{case QualifiedType(preds, ty) =>
t.ty = ty ;
Some((emptyEqualityConstraintSet,preds)) }
Run Code Online (Sandbox Code Playgroud)
这会导致错误消息
missing parameter type for expanded function The argument types of an anonymous function
must be fully known. (SLS 8.5) Expected type was:
? => Option[(Typer.this.EqualityConstraintSet, Typer.this.TypeRelationSet)]
Run Code Online (Sandbox Code Playgroud)
我查看了SLS 8.5,但未找到解释.
如果我自己扩展功能
{(qt : QualifiedType) =>
qt match {case QualifiedType(preds, ty) =>
t.ty = ty ;
Some((emptyEqualityConstraintSet,preds)) }}
Run Code Online (Sandbox Code Playgroud)
错误消失了.
(a)为什么这是一个错误?
(b)我该怎么做才能解决这个问题?
我尝试了明显的修复,即: QualifiedType
在模式和=>之间添加,但这是一个语法错误.
我注意到的一件事是上下文有所不同.如果我使用函数literal作为声明为期望a的函数的参数QualifiedType => B
,则没有错误.但是如果我将它用作期望a的函数的参数A => B
,则会出现错误.我希望这里发生的事情是,由于模式可以想象应用于类型为QualifiedType的超类型的对象,编译器不愿意在不保证函数不会应用于的情况下分配明显的类型.任何不是QualifiedType的东西.我真正想要的是能够写出{QualifiedType( preds, ty) => ...} …
现在似乎有不少主流语言支持函数文字.它们也被称为匿名函数,但我不在乎它们是否有名称.重要的是函数文字是一个表达式,它产生一个尚未在别处定义的函数,因此例如在C中,&printf
不计算.
编辑添加:如果你有一个真正的函数文字表达式<exp>
,你应该能够将它传递给一个函数f(<exp>)
或立即将它应用于一个参数,即.<exp>(5)
.
我很好奇哪些语言可以让你编写递归的函数文字.维基百科的" 匿名递归 "文章没有给出任何编程示例.
我们以递归因子函数为例.
以下是我所知道的:
JavaScript/ECMAScript可以用callee
:
function(n){if (n<2) {return 1;} else {return n * arguments.callee(n-1);}}
Run Code Online (Sandbox Code Playgroud)在语言方面很容易letrec
,例如Haskell(称之为let
):
let fac x = if x<2 then 1 else fac (x-1) * x in fac
Lisp和Scheme中有等价物.请注意,绑定fac
是表达式的局部,因此整个表达式实际上是一个匿名函数.
还有其他人吗?
recursion language-features function-literal anonymous-function letrec
我总是想知道为什么有时使用函数文字我们可以忽略大括号,即使是多个语句.为了说明这一点,多行函数文字的语法是用大括号括起语句.像这样,
val fl = (x: Int) => {
println("Add 25 to "+x)
x + 25
}
Run Code Online (Sandbox Code Playgroud)
但是,当您将其传递给单参数函数时,您可以忽略函数文字所需的大括号.
所以对于给定的函数f,
def f( fl: Int => Int ) {
println("Result is "+ fl(5))
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样调用f(),
f( x=> {
println("Add 25 to "+x)
x + 25
})
-------------------------
Add 25 to 5
Result: 30
Run Code Online (Sandbox Code Playgroud)
或者在函数调用中使用花括号而不是括号时,可以从函数文本中删除内部花括号.所以下面的代码也可以,
f{ x=>
println("Add 25 to "+x)
x + 25
}
Run Code Online (Sandbox Code Playgroud)
上面的代码更具可读性,我注意到很多例子都使用这种语法.但是,是否有任何我可能错过的特殊规则,以解释为什么这样做符合预期?
在JavaScript中,有对象文字和函数文字.
对象文字:
myObject = {myprop:"myValue"}
Run Code Online (Sandbox Code Playgroud)
功能文字:
myFunction = function() {
alert("hello world");
}
Run Code Online (Sandbox Code Playgroud)
字面文字的意义是什么?我们可以说Java有方法文字吗?
public void myMethod() {
System.out.println("are my literal");
}
Run Code Online (Sandbox Code Playgroud) 是否可以从对象文字中递归调用一个方法?
例如:
(function () {
'use strict';
var abc = ['A', 'B', 'C'],
obj = {
f: function () {
if (abc.length) {
abc.shift();
f(); // Recursive call
}
}
};
obj.f();
}());
Run Code Online (Sandbox Code Playgroud)
错误:在定义之前使用'f'.
谢谢.
我会用Scala示例来问这个问题,但很可能这会影响其他允许混合命令和函数样式的语言.
这是一个简短的例子(更新,见下文):
def method: Iterator[Int] {
// construct some large intermediate value
val huge = (1 to 1000000).toList
val small = List.fill(5)(scala.util.Random.nextInt)
// accidentally use huge in a literal
small.iterator filterNot ( huge contains _ )
}
Run Code Online (Sandbox Code Playgroud)
现在iterator.filterNot
懒惰地工作,这很棒!因此,我们希望返回的迭代器不会消耗太多内存(实际上是O(1)).然而,可悲的是,我们犯了一个可怕的错误:因为filterNot
它是懒惰的,所以它保留了对函数文字的引用huge contains _
.
因此,虽然我们认为该方法在运行时需要大量内存,并且该方法可以在方法终止后立即释放,但实际上内存会被卡住,直到我们忘记返回Iterator
.
(我只是犯了这样一个错误,这需要很长时间才能找到!你可以抓住这些东西看堆堆...)
避免此问题的最佳做法是什么?
似乎唯一的解决方案是仔细检查在范围结束时存活的函数文字,以及捕获的中间变量.如果您构建一个非严格的集合并计划返回它,这有点尴尬.任何人都可以想到一些不错的技巧,特定于Scala或其他方式,避免这个问题,让我写出漂亮的代码?
更新:我之前给出的例子是愚蠢的,正如huynhjl的答案所示.它曾经是:
def method: Iterator[Int] {
val huge = (1 to 1000000).toList // construct some large intermediate value
val n = huge.last // do some calculation …
Run Code Online (Sandbox Code Playgroud) 我是scala的新手,并试图编写一个函数文字来检查给定的整数是否为奇数.我的第一次尝试是:
val isOdd = (x:Int) => (x & 1) == 1
它工作得很好,而且,由于参数x只在这个函数文字中出现一次,我很想用"_"表示法进一步简化它,如下所示:
val isOdd = ((_:Int) & 1 ) == 1
但这次编译器抱怨:
warning: comparing a fresh object using `==' will always yield false val isOdd = ((_:Int) & 1 ) == 1
这个警告意味着什么?为什么编译器识别((_ :Int) & 1)
为新对象而不是按位运算导致值?有没有办法用"_"表示法编写这个函数文字?
我有以下代码:
var x = Array(1,3,4,4,1,1,3)
var m = Int.MaxValue
x.foreach((x)=>(m = m min x))
Run Code Online (Sandbox Code Playgroud)
我试图将最后一句简化为:
x.foreach((m = _ min m))
Run Code Online (Sandbox Code Playgroud)
但口译员说:
scala> x.foreach((m = _ min m))
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.min(m))
x.foreach((m = _ min m))
^
Run Code Online (Sandbox Code Playgroud)
我试图更明确地说明这种类型:
scala> x.foreach((m = (_:Int) min m))
<console>:8: error: type mismatch;
found : (Int) => Int
required: Int
x.foreach((m = (_:Int) min m))
^
Run Code Online (Sandbox Code Playgroud)
编译器和我彼此不了解:(
最好的祝福,
斯坦
syntax lambda scala function-literal scala-placeholder-syntax
我试图弄清楚它是如何工作的.当我引用一个尚未声明的命名Javascript函数时,在某些情况下,它可以工作.但是,如果我使用函数文字,它不会,但它也不会失败ReferenceError
.
function works() {
var works_ref = foo;
function foo() {
console.log('ok');
};
console.log('works ' + works_ref);
}
function fails() {
var fails_ref = foo;
var foo = function() {
console.log('ok');
};
console.log('fails ' + fails_ref);
}
works();
fails();
Run Code Online (Sandbox Code Playgroud)
这回来了
"works function foo() {
console.log('ok');
}"
"fails undefined"
Run Code Online (Sandbox Code Playgroud)
我想知道第一个例子是如何工作的 - 这是一个解释语言,没有编译,所以我希望任何类型的前向引用都会失败 - 为什么第二个例子不能生成ReferenceError
?
我正在阅读-nophytes-guide-to-scala-part-10,其中我遇到了以下代码.
type EmailFilter = Email => Boolean
val minimumSize: Int => EmailFilter = n => email => email.text.size >= n
Run Code Online (Sandbox Code Playgroud)
我理解了第一行,其中为一个函数创建了类型别名EmailFilter,该函数接收电子邮件返回布尔值.但我不明白我们将电子邮件和数字作为输入的第二行,并通过检查大小返回布尔值.请解码第二行并向我解释该函数的语法糖代码.