lambda函数体中的更多说明

时间:2018-04-11 14:48:23

标签: f# f#-interactive

据我所知,我可以在F#中定义lambda函数,就像那样

(fun arg -> arg * arg)

但是,如何将该定义的主体扩展为多个表达式?在某些伪代码中,它可能看起来像这样:

(fun arg -> {
    log "abcd"
    arg * arg
})

我需要它来做一些副作用。

1 个答案:

答案 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不是函数。

在实践中,最常见的是使用括号。