F#替代列表语法

net*_*x01 0 f#

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

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

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

想知道是否有更多的创造这种创造的方式?

Tom*_*cek 8

示例中的代码只创建一个Genre对象,然后创建一个unit值列表.一个unit值是有点像void在C#中-这是perfroming不返回任何表达式的结果,但有副作用.在你的情况,副作用正在修改Name的单一实例的属性(这是什么<-操作呢),所以你有一个最终genres值,其Name"Rock".

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

let genre = new Genre() 
genre.Name <- "Disco"
Run Code Online (Sandbox Code Playgroud)

这将创建一个单一的genre值,所以你可以创造价值genre1,genre2并且genre3,然后把它们变成使用列表:

let genres = [ genre1; genre2; genre3 ]
Run Code Online (Sandbox Code Playgroud)

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

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

let genres = [ Genre(Name="Disco"); Genre(Name="Jazz"); Genre(Name="Rock") ]
Run Code Online (Sandbox Code Playgroud)

现在,您可以开始使用功能特性List.map(如Daniel建议)或F#list comprehension语法,以使构造更短.在这种情况下,我可能更喜欢列表理解,我写道:

let genres = [ for name in ["Disco"; "Jazz"; "Rock"] -> Genre(Name = name) ]
Run Code Online (Sandbox Code Playgroud)

这与做同样的事情List.map,但使用为此目的设计的F#语法.

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

// 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" } ]
Run Code Online (Sandbox Code Playgroud)

与前一种情况不同,记录是不可变的,因此您不会冒着创建可变对象然后对其进行变异所造成的混淆的风险.在这里,您将获得三个不同对象的列表(通过复制创建template).