F#替代列表语法

时间:2012-02-06 15:01:39

标签: f#

所以我有一个带有属性名称的类型类型。

我正在创建一个类型名称列表,如下所示。

let genres = new Genre()
    [ genres.Name <- "Disco"; 
      genres.Name <- "Jazz"; 
      genres.Name <- "Rock"; ] |>ignore

想知道是否有更多的succint方式来创建它?

4 个答案:

答案 0 :(得分:8)

示例中的代码只创建一个Genre对象,然后创建一个unit值列表。 unit值有点像C#中的void - 它是对表达式执行的结果,该表达式不返回任何内容,但具有副作用。在您的情况下,副作用是修改单个实例的Name属性(这是<-运算符所做的),因此您以{{1}的genres值结束是} Name

有许多方法可以更改代码以执行您想要的操作 - 从您编写的内容开始:

"Rock"

这会创建一个let genre = new Genre() genre.Name <- "Disco" 值,因此您可以创建值genregenre1genre2,然后使用以下内容将它们转换为列表:

genre3

这将是相当多的重复。如果你有一个名为let genres = [ genre1; genre2; genre3 ] 的默认构造函数,你可以写Genre。如果不这样做,则可以使用F#对象初始化语法,并在构造期间将属性的值指定为Genre("Disco")。请注意,如果对象未实现Genre(Name="Disco"),您也可以省略new

现在你可以构建一个这样的列表:

IDisposable

现在,您可以开始使用let genres = [ Genre(Name="Disco"); Genre(Name="Jazz"); Genre(Name="Rock") ] (由Daniel建议)或F#list comprehension语法等功能特性来使构造更短。在这种情况下,我可能更喜欢列表理解,我写道:

List.map

这与let genres = [ for name in ["Disco"; "Jazz"; "Rock"] -> Genre(Name = name) ] 完全相同,但使用为此目的而设计的F#语法。

编辑:除此之外,在F#中使用可变属性并不总是最好的方法。您可以尝试使用F#记录解决相同的问题,这使您可以轻松地创建具有已修改属性的副本。例如:

List.map

与前一种情况不同,记录是不可变的,因此您不会冒生成创建可变对象然后变异的混淆的风险。在这里,您将获得三个不同对象的列表(通过复制// A genre has a name and an era type Genre = { Name : string; Era : string; } // Create a template with the basic properties set let template = { Name = "Default"; Era = "Twentieth century" } // Create a list of 20th century genres let genres = [ { template with Name = "Disco" } { template with Name = "Jazz" } { template with Name = "Rock" } ] 创建)。

答案 1 :(得分:4)

["Disco"; "Jazz"; "Rock"]
|> List.map (fun name -> Genre(name))

答案 2 :(得分:2)

我认为最简单的方法是使用一个为你完成作业的构造函数,然后你可以编写

let genres = Genre("Disco")::Genre("Jazz")::Genre("Rock")::[]

答案 3 :(得分:1)

稍微多一点:

type Genre = Genre of string
let genres = List.map Genre ["Disco"; "Jazz"; "Rock"]

printfn "%A" genres

打印[Genre "Disco"; Genre "Jazz"; Genre "Rock"]