F#中在lambda表达式中调用对象方法的速记法

6

我认为这与这个问题有些关联,但不确定,因为那里没有真正的答案,所以我来这里提问:

在Scala中,您可以编写以下代码:

aStringArray.map(_.toUpperCase())

这是一个缩写,意思是:

aStringArray.map(s => s.toUpperCase())

在F#中是否有类似的东西或者一种实现方式(不使用?操作符或大量使用反射)?如果不可能,是否正在考虑将其作为未来版本的语言特性?(我真的很讨厌在闭包中调用对象上的方法时需要编写冗长的函数!)
4个回答

7
正如Dario所指出的那样,在Scala中类似_.Foo()语法的特性在F#中目前不可用,因此您将需要显式编写lambda函数,使用 fun a -> a.Foo()
据我所知,像这样的问题每隔一段时间就会在F#讨论中出现,所以F#团队肯定考虑过它。这有点棘手(例如,您是否只想允许成员使用或其他使用方式,例如_ + 10,并且lambda表达式的范围是什么?)另外,与其他可以完成的事情相比,该特性的价值相对较低...无论如何,拥有它是很好的!
这也可能是为什么许多F#类型同时将操作作为成员(可在面向对象的风格中使用)和模块中的函数(用于函数式风格)公开的原因之一。 我认为您可以将其视为良好的F#实践(但这取决于您的设计偏好)。例如:
type Foo(a:int) = 
  member x.Add(b:int) = a + b

// Attribute allows you to define module with the same name
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Foo = 
  let add b (v:Foo) = v.Add(b)

接下来,您可以使用fun v -> v.Add(10)Foo.add 10两种方式创建函数值。不幸的是,String类型没有对应的模块包含所有核心F#库中的函数,因此您需要自己编写。


5

只需使用 fun s -> s.ToUpper() 作为参数,这将创建与Scala相同类型的匿名函数。

请注意,来自Scala的巧妙的 _ 技巧在F#中(目前)不存在,但如果您没有调用对象方法,您可以像下面这样使用部分求值:

filter ((=) 42) list

1

1
这只是一小部分字符,但对我来说在概念上更容易理解。当然,如果将a.b视为应用点运算符,则会更简单。那么.b就是一种自然的语法。 - Muhammad Alkarouri
除了在字符方面节省的内容,考虑到使用经典Oo库时此代码的频繁出现,这将是巨大的。还有另一个巨大的优点:它的阅读更容易。 - em70

-1

这并不是你想要的答案,但目前我通过创建虚拟静态函数(如果我需要多次使用相同的内容)来解决这个问题,因为它比lambda语法更美观:

let toupper (s:string) = s.ToUpper()
aStringArray.map toupper

如果你想定义一个命名函数,可以使用let toUpper (s:string) = s.ToUpper(),或者直接使用匿名函数。 - Tomas Petricek
@Tomas,是的,这就是我想要的,忘记了类型定义。 - Benjol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接