据我所知,我可以在F#中定义lambda函数,就像那样
(fun arg -> arg * arg)
但是,如何将该定义的主体扩展为多个表达式?在某些伪代码中,它可能看起来像这样:
(fun arg -> {
log "abcd"
arg * arg
})
我需要它来做一些副作用。
答案 0 :(得分:3)
F#是对空格和缩进敏感的。嵌套代码块取决于它们向右缩进的方式。
对于您的具体示例,为了在函数体中嵌套多个表达式,只需将它们向右缩进至少一个空格:
let f1 = fun arg -> arg * arg
let f2 = fun arg ->
log "abcd"
arg * arg
包含多个表达式的另一种方法是用分号分隔它们:
let f3 = fun arg -> log "abcd"; arg * arg
通常,在大多数情况下,分号可用于F#而不是换行符。
如果你需要使用这样的多行lambda表达式作为另一个函数的参数(例如List.map
),你可能需要将整个主体括在括号中:
[1;2;3]
|> List.map ( fun x ->
log "abcd"
x*x )
这不是因为缩进所必需的,而仅仅是因为没有括号,这将是一个语法上不正确的程序:关键字fun
似乎是传递给List.map
的参数,它不能发生了,因为fun
是一个关键字。此规则同样适用于单行lambda表达式:
[1;2;3]
|> List.map ( fun x -> x*x )
您可以使用“竖直管道”操作符来避免使用括号:
let squareAll =
List.map <| fun x ->
log "abcd"
x*x
let squares = squareAll [1;2;3]
在这种情况下,不需要括号,因为即使没有括号,从语法的角度来看,关键字fun
也不会出现为List.map
的参数。
但请记住,使用“竖管”可能并不总是方便,因为它与更常见的“管道右”操作符冲突,例如:
[1;2;3]
|> List.map <| fun x -> x*x
上面的代码无法编译,因为编译器会将其理解为:
([1;2;3] |> List.map)
<| fun x -> x*x
这是不正确的,因为[1;2;3] |> List.map
不是函数。
在实践中,最常见的是使用括号。