gpt4 book ai didi

clojure - F# 中有没有办法以 Clojure 方式提取记录成员的值?

转载 作者:行者123 更新时间:2023-12-04 14:57:58 25 4
gpt4 key购买 nike

在 Clojure 中,我会编写上面的代码:

user=> (def points [{:x 11 :y 12} {:x 21 :y 22}])
#'user/points
user=> (map :x r)
(11 21)

我可以这样做,因为 :x 可以用作函数。这是一个非常有用的功能

F# 中的相同代码如下所示:
> type Point = {x : int; y: int};;
> let points = [{x=11;y=12}; {x=21; y=22}];;
> List.map (fun p -> p.x) points
val it : int list = [11; 21]

因为我一直讨厌编写匿名函数,所以我发现自己在编写 Point 这样的类型:
type Point =                 
{
x: int
y : int
}

static member getX p = p.x;;

...这让我有可能做:
> List.map Point.getX points

这仍然很困惑,因为我需要为我使用的每个记录成员编写一个 getter。

相反,我想要的是这样的语法:
> List.map Point.x points

有没有办法做到这一点,而不必编写凌乱的匿名函数(fun p -> p.x)或静态 getter?

更新:

顺便说一句,Haskell 的做法也与 Clojure 相同(实际上是相反的):
Prelude> data Point = Point { x :: Int, y :: Int}
Prelude> let p = Point { x = 11, y=22}
Prelude> x p
11

更新 2:

希望针对 lambda 的一个更明显的原因是类型推断在没有帮助的情况下无法工作的示例:
type Point2D = { x : int; y : int}
type Point3D = { x : int; y : int; z : int}

let get2dXes = List.map (fun (p:Point2D) -> p.x)
let get2dXes' : Point2D list -> int list = List.map (fun p -> p.x)
let get2dXes'' (ps : Point2D list) = List.map (fun p -> p.x) ps

...这远不如以下优雅:
let get2dXes = List.map Point2D.x

我不想就哪种语法更好而引发激烈的争论。我只是真诚地希望有一些优雅的方法来完成上述操作,因为我自己还没有找到任何方法。

显然我所能做的就是祈祷 F# 的强大之神在 future 的版本中包含这样的功能,在类型类旁边;)

更新 3:

此功能已针对 future 的语言版本提出。 https://fslang.uservoice.com/forums/245727-f-language/suggestions/5663326-syntax-for-turning-properties-into-functions谢谢 jack 。!

最佳答案

我的建议是这样的:

namespace Temp

type Point = { x:int; y:int }

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Point =
let x: Point -> int = fun p -> p.x
let y: Point -> int = fun p -> p.y


type Circle = { r: int; x: int; y: int }

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Circle =
let x: Circle -> int = fun c -> c.x
let y: Circle -> int = fun c -> c.y
let r: Circle -> int = fun c -> c.r


module test =
let p1 : Point = { x = 1; y = 2}

Point.y p1 |> printf "%i"

如果您可以保证不重复使用记录字段名称,那么您可以使用 AutoOpen像这样的属性:
namespace Temp

type Point = { x:int; y:int }

[<AutoOpen>]
module PointExt =
let x: Point -> int = fun p -> p.x
let y: Point -> int = fun p -> p.y


module test =
let points = [ { x = 1; y = 2}; { x=5;y=10} ]

points |> List.map x |> List.iter (printf "%i")

不过,这种编码风格对我来说感觉不太明显。我宁愿保留模块名称。

关于clojure - F# 中有没有办法以 Clojure 方式提取记录成员的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26562197/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com