所以我有一个带有属性名称的类型类型。
我正在创建一个类型名称列表,如下所示。
let genres = new Genre()
[ genres.Name <- "Disco";
genres.Name <- "Jazz";
genres.Name <- "Rock"; ] |>ignore
想知道是否有更多的succint方式来创建它?
答案 0 :(得分:8)
示例中的代码只创建一个Genre
对象,然后创建一个unit
值列表。 unit
值有点像C#中的void
- 它是对表达式执行的结果,该表达式不返回任何内容,但具有副作用。在您的情况下,副作用是修改单个实例的Name
属性(这是<-
运算符所做的),因此您以{{1}的genres
值结束是} Name
。
有许多方法可以更改代码以执行您想要的操作 - 从您编写的内容开始:
"Rock"
这会创建一个let genre = new Genre()
genre.Name <- "Disco"
值,因此您可以创建值genre
,genre1
和genre2
,然后使用以下内容将它们转换为列表:
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"]
。