F# 返回匿名记录而不是元组的注意事项

F# 返回匿名记录而不是元组的注意事项,f#,record,anonymous-types,F#,Record,Anonymous Types,考虑以下(常规,可以在库中公开)实用程序函数,用于将字符串解析为HTTP基本凭据并返回用户名和密码: let parseBasicCredentials (encodedCredentials: string) = (* approx. 10 lines of pipes, matching and try/with *) username, password 由于用户名和密码都是字符串,调用方需要记住(或检查文档)用户名作为元组的第一个元素返回,密码作为第二个元素返回 然而,F#将很

考虑以下(常规,可以在库中公开)实用程序函数,用于将字符串解析为HTTP基本凭据并返回用户名和密码:

let parseBasicCredentials (encodedCredentials: string) =
  (* approx. 10 lines of pipes, matching and try/with *)
  username, password
由于用户名和密码都是字符串,调用方需要记住(或检查文档)用户名作为元组的第一个元素返回,密码作为第二个元素返回

然而,F#将很快获得匿名记录的支持(已经在《睡梦》中提供)。发生这种情况时,此类函数还可以返回匿名记录:

let parseBasicCredentials (encodedCredentials: string) =
  (* approx. 10 lines of pipes, matching and try/with *)
  {| Username = username; Password = password |}
这似乎很好,但由于这是一个全新的语言功能,我不确定这是否有任何缺点,无论是技术上的还是仅仅是不赞成的。对于这样的简单帮助函数,AFAIK返回元组是一种惯用且被接受的解决方案。匿名类型还允许您命名元素,因此可以被认为更“安全”,因为它更具有自文档性,从而更好地防止调用者混淆返回值

< >我不考虑通用(非域)辅助函数,例如返回单独定义的记录类型的候选,或者单个情况下DUs的元组。我只是好奇,既然匿名记录已经存在,当人们需要特殊的、非原语的返回值时,它们是否可以作为“更好的元组”,或者元组是否仍然是首选(如果是,原因是什么).

我没有太多使用匿名记录,但我认为主要的限制是您无法编写将它们作为输入的函数。这严重限制了它们作为在函数之间传递的应用程序范围数据的使用,这是一种有意的设计选择

作为在函数或脚本文件中存储瞬态数据的方便方法,它们将更有用

更正: 可以将它们作为输入。下面是一个例子:

let showCredentials (x:{| Username:string; Password:string |}) =
    printfn "Username: %s, Password %s" x.Username x.Password
但是,您必须提及记录中的所有字段,以使其与类型匹配。因此,要编写另一个接受相同类型但不使用密码的函数,可以编写以下内容:

let showUsername (x:{| Username:string; Password:_ |}) =
    printfn "Username: %s" x.Username
这意味着每次编辑类型定义时,都必须编辑该类型的函数参数的所有类型注释。对于一般用途来说,它的伸缩性不是很好

可能会添加模式匹配,以便您可以改为编写:

let showUsername {| Username = username |} =
    printfn "Username: %s" username

但我不清楚这是否会添加到语言中。

你确定吗?你能不能说一些像
让getFoo(x:{Foo:string})=x.Foo
?据我所知,这应该行得通。只要不需要在类型注释中给出记录本身的类型,比如消除歧义,就可以像其他记录类型一样传递它们。编译器有它的名字;你就是不知道那个名字。哦,前几天我看到的另一个简洁的用法是DU case的值,在这里它们也可以比元组更有表现力。@cmeeren感谢你指出这一点,我以前从未见过。在我的答案中添加了一个,以防对任何人都有用。请注意,您实际上可以使用匿名记录的类型缩写,这有点奇怪,但不需要调整每个参数。虽然如果你是在缩写一个匿名记录,你应该只使用一个普通的记录类型,这是有争议的:)我能想到的唯一的警告是已经使用元组的函数太多了。例如,
let usernames,passwords=multipleCredentials |>List.map parseBasicCredentials |>List.unzip
对于匿名记录是不可能的(非常简洁)。就个人而言,我宁愿有一个强名称,也不愿与元组函数兼容。