F # альтернативный синтаксис списка - PullRequest
0 голосов
/ 06 февраля 2012

, поэтому у меня есть тип Жанр с именем свойства.

Я создаю список названий жанров, как показано ниже.

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

Хотите знать, есть ли более лаконичный способ создания этого?

Ответы [ 4 ]

8 голосов
/ 06 февраля 2012

Код в вашем примере создает только один объект Genre, а затем создает список значений unit. Значение unit немного похоже на void в C # - это результат выполнения выражения, которое ничего не возвращает, но имеет побочный эффект. В вашем случае побочным эффектом является изменение свойства Name отдельного экземпляра (это то, что делает оператор <-), поэтому вы заканчиваете одним значением genres, Name которого равно "Rock".

Существует множество способов изменить код, чтобы он делал то, что вы хотите - начать с того, что вы написали:

let genre = new Genre() 
genre.Name <- "Disco"

Это создает единственное значение genre, поэтому вы можете создать значения genre1, genre2 и genre3, а затем превратить их в список, используя:

let genres = [ genre1; genre2; genre3 ]

Это было бы довольно много повторений. Если у вас есть конструктор по умолчанию для Genre, который принимает имя, вы можете просто написать Genre("Disco"). Если вы этого не сделаете, вы можете использовать синтаксис инициализации объекта F # и указать значение свойства во время построения как Genre(Name="Disco"). Обратите внимание, что вы также можете опустить new, если объект не реализует IDisposable.

Теперь вы можете построить список следующим образом:

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

Теперь вы можете начать использовать функциональные возможности, такие как List.map (как предложено Дэниелом) или синтаксис понимания списка F #, чтобы сделать конструкцию еще короче. В этом случае я бы предпочел понимание списка и написал бы:

let genres = [ for name in ["Disco"; "Jazz"; "Rock"] -> Genre(Name = name) ]

Это то же самое, что и 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" } ]

В отличие от предыдущего случая, записи являются неизменяемыми, поэтому вы не рискуете путаницы, возникающей при создании изменяемого объекта, а затем его изменения. Здесь вы получите список из трех различных объектов (которые создаются путем копирования template).

4 голосов
/ 06 февраля 2012
["Disco"; "Jazz"; "Rock"]
|> List.map (fun name -> Genre(name))
2 голосов
/ 06 февраля 2012

Я думаю, что самым простым способом было бы использовать construcotr, который выполнил задание для вас, тогда вы могли бы написать

let genres = Genre("Disco")::Genre("Jazz")::Genre("Rock")::[]
1 голос
/ 06 февраля 2012

Чуть терже:

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

printfn "%A" genres

Отпечатки [Genre "Disco"; Genre "Jazz"; Genre "Rock"].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...