F # - отображение списка с аккумулятором
Я новичок в F # и функциональном программировании в целом. Учитывая сценарий, в котором вы хотите перебирать последовательность или список строк и сопоставлять это с новым списком другого типа, с аккумулятором, какой правильный функциональный подход? Я могу добиться этого в F #, используя изменяемые переменные, но я изо всех сил пытаюсь найти нужную функцию для этого. Это похоже на карту, я думаю, но есть понятие состояния.
Другими словами, я хочу преобразовать список строк в список переключателей win-форм, но для каждой новой кнопки я хочу добавить 20 к предыдущей координате y. Что-то вроде:
new RadioButton(Text=str,Location=new Point(20,y+20),Width=350)
Ответы
Ответ 1
Вы можете использовать List.fold
:
open System.Drawing
open System.Windows.Forms
let getButtons () =
let strings = ["a"; "b"; "c"]
let (_, pointsRev) = List.fold (fun (offset, l) s -> (offset+20, (new RadioButton(Text=s, Location = new Point(20, offset), Width = 350))::l)) (0, []) strings
pointsRev |> List.rev
Состояние представляет собой пару, содержащую текущее смещение и текущий список результатов. Выходной список построен в обратном порядке, поэтому в конце должен быть отменен.
Вы также можете использовать Seq.map2:
let points = Seq.map2 (fun offset s -> new RadioButton(Text=s, Location = new Point(20, offset)) (Seq.initInfinite ((*)20)) strings |> List.ofSeq
Ответ 2
Вы можете получить доступ и изменить переменную по ссылке
let x = ref 0
x := !x + 5
new Point(20,!x+20)
и вы можете использовать такую переменную внутри замыканий.
Также вы можете использовать mapi
: http://msdn.microsoft.com/en-us/library/ee353425.aspx
И добавьте значение к y, основанное на i
подобно new Point(20,i*20+20)
Ответ 3
Использование List.fold
- отличная идея (см. принятый ответ).
Являясь самим начинающим F #, я разбил складку на отдельную функцию и переименовал некоторые переменные, чтобы я мог понять вещи более четко. Кажется, что это работает:
let buttonNames = ["Button1Name"; "Button2Name"]
let createRadioButton (offset, radioButtons) name =
let newRadioButton = new RadioButton(Text=name, Location=new Point(20, offset), Width=350)
(offset + 20, newRadioButton::radioButtons)
let (_, buttonsReversed) = buttonNames |> List.fold createRadioButton (0, [])
let buttons = buttonsReversed |> List.rev