Подтвердить что ты не робот

F # - отображение списка с аккумулятором

Я новичок в F # и функциональном программировании в целом. Учитывая сценарий, в котором вы хотите перебирать последовательность или список строк и сопоставлять это с новым списком другого типа, с аккумулятором, какой правильный функциональный подход? Я могу добиться этого в F #, используя изменяемые переменные, но я изо всех сил пытаюсь найти нужную функцию для этого. Это похоже на карту, я думаю, но есть понятие состояния.

Другими словами, я хочу преобразовать список строк в список переключателей win-форм, но для каждой новой кнопки я хочу добавить 20 к предыдущей координате y. Что-то вроде:

new RadioButton(Text=str,Location=new Point(20,y+20),Width=350)
4b9b3361

Ответ 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