F# 函数调用语法混乱 [英] F# function calling syntax confusion

查看:16
本文介绍了F# 函数调用语法混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码:

links
    |> Seq.map (fun x -> x.GetAttributeValue ("href", "no url"))

我想重写的内容:

links
    |> Seq.map (fun x -> (x.GetAttributeValue "href" "no url"))

但 F# 编译器似乎不喜欢那样.我的印象是这两个函数调用是可以互换的:

But the F# compiler doesn't seem to like that. I was under the impression that these two function calls were interchangeable:

f (a, b)
(f a b)

我得到的错误是:

无法从此代码位置访问带有 2 个参数的成员或对象构造函数GetAttributeValue".方法GetAttributeValue"的所有可访问版本都采用 2 个参数.

The member or object constructor 'GetAttributeValue' taking 2 arguments are not accessible from this code location. All accessible versions of method 'GetAttributeValue' take 2 arguments.

这似乎很有趣,因为它似乎表明它需要我给它的东西.我在这里错过了什么?

Which seems amusing, as it seems to indicate that it needs what I'm giving it. What am I missing here?

推荐答案

F# 中常见的函数调用是不带括号的,参数之间用空格分隔.定义一个多参数函数的简单方法是这样写:

A usual function call in F# is written without parentheses and parameters are separated by spaces. The simple way to define a function of several parameters is to write this:

let add a b = a + b

正如 Pascal 所指出的,这种指定参数的方式称为柯里化 - 其思想是一个函数只接受一个参数,结果是一个接受第二个参数并返回实际结果(或另一个函数)的函数.当调用这样一个简单的函数时,你会写add 10 5,编译器(原则上)将其解释为((add 10) 5).这有一些不错的优点 - 例如,它允许您使用 部分函数应用,其中您只指定函数的前几个参数:

As Pascal noted, this way of specifying parameters is called currying - the idea is that a function takes just a single parameter and the result is a function that takes the second parameter and returns the actual result (or another function). When calling a simple function like this one, you would write add 10 5 and the compiler (in principle) interprets this as ((add 10) 5). This has some nice advantages - for example it allows you to use partial function application where you specify only a first few arguments of a function:

let addTen = add 10 // declares function that adds 10 to any argument
addTen 5  // returns 15
addTen 9  // returns 19

此功能在处理列表时非常有用:

This feature is practically useful for example when processing lists:

// The code using explicit lambda functions..
[ 1 .. 10 ] |> List.map (fun x -> add 10 x) 

// Can be rewritten using partial function application:
[ 1 .. 10 ] |> List.map (add 10) 

现在,让我们进入令人困惑的部分 - 在 F# 中,您还可以使用元组,元组是一种简单的数据类型,允许您将多个值组合为一个值(请注意,元组与任何函数都无关)大大地).例如,您可以这样写:

Now, let's get to the confusing part - in F#, you can also work with tuples, which are simple data types that allow you to group multiple values into a single values (note that tuples aren't related to functions in any way). You can for example write:

let tup = (10, "ten")    // creating a tuple
let (n, s) = tup         // extracting elements of a tuple using pattern 
printfn "n=%d s=%s" n s  // prints "n=10 s=ten"

当您编写一个函数,该函数的参数用逗号分隔,括号中的参数实际上是在编写一个函数,该函数只接收一个元组参数:

When you write a function that takes parameters in parentheses separated by a comma, you're actually writing a function that takes a single parameter which is a tuple:

// The following function:
let add (a, b) = a * b

// ...means exactly the same thing as:
let add tup = 
  let (a, b) = tup  // extract elements of a tuple
  a * b

// You can call the function by creating tuple inline:
add (10, 5)
// .. or by creating tuple in advance
let t = (10, 5)
add t

这是一个不同类型的函数 - 它接受一个元组参数,而第一个版本是一个接受两个参数的函数(使用柯里化).

This is a function of a different type - it takes a single parameter which is a tuple, while the first version was a function that took two parameters (using currying).

在 F# 中,情况比这要复杂一些 - .NET 方法显示为将元组作为参数的方法(因此您可以使用带括号的符号调用它们),但它们有些限制(例如您不能首先创建一个元组,然后调用只给出元组的方法).此外,编译后的 F# 代码实际上不会生成柯里化形式的方法(因此您不能直接从 C# 使用部分函数应用程序).这是由于性能原因 - 大多数情况下,您指定所有参数,这样可以更有效地实现.

In F#, the situation is a bit more complicated than that - .NET methods appear as methods that take a tuple as a parameter (so you can call them with the parenthesized notation), but they are somewhat limited (e.g. you cannot create a tuple first and then call the method giving it just the tuple). Also, the compiled F# code doesn't actually produce methods in the curried form (so you cannot use partial function application directly from C#). This is due to performance reasons - most of the times, you specify all arguments and this can be implemented more efficiently.

但是,原理是一个函数要么接受多个参数,要么接受一个元组作为参数.

However, the principle is that a function either takes multiple parameters or takes a tuple as a parameter.

这篇关于F# 函数调用语法混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆