#f#
#f#
Вопрос:
Я пытаюсь сделать что-то вроде этого:
[ list of things ]
|> List.map (fun i -> some transformation)
|> List.iter (fun i -> do stuff, like printfn or whatever)
|> List.filter (fun i -> ...)
|> List.andDoOtherThings... (fun i -> ...)
List.iter возвращает единицу измерения, поэтому это невозможно. Но бывают случаи, когда я беру список, применяю некоторую фильтрацию и преобразования, а затем мне нужно выполнять задачи на основе этого списка (например, с List.iter), а затем продолжаю, выполняя другие действия с тем же списком. Я не могу выполнить iter в качестве последнего оператора в этом случае.
Я мог бы записать это как:
let myNewList =
[ list of things ]
|> List.map (fun i -> some transformation)
myNewList
|> List.iter (fun i -> do stuff, like printfn or whatever)
myNewList
|> List.filter (fun i -> ...)
|> List.andDoOtherThings... (fun i -> ...)
но было бы проще сделать все это сразу. Есть ли обходной путь?
Ответ №1:
Как предлагает @tranquility , я бы, вероятно, просто использовал a , List.map
в котором do stuff, like printfn or whatever
вызывается перед возвратом входного значения.
Но если это шаблон, который вы часто используете (например, для ведения журнала), вы могли бы определить оператор Tee, как показано в Linux или R. Это может выглядеть примерно так
let tee func v =
func(v) |> ignore
v
[ list of things ]
|> List.map (fun i -> some transformation)
|> tee (List.iter (fun i -> do stuff, like printfn or whatever))
|> List.filter (fun i -> ...)
|> List.andDoOtherThings... (fun i -> ...)
В R это реализовано как оператор %T>%
. Это, конечно, можно было бы сделать и в F #, хотя я бы этого не рекомендовал. Обычно я нахожу, что пользовательские операторы снижают удобочитаемость.
Комментарии:
1. Мне нравится эта идея, потому что она все еще более удобочитаема, чем «злоупотребление» картой. Обычно это используется для ведения журнала, поэтому я думаю, что на удобочитаемость это влиять не должно. Спасибо!
Ответ №2:
Чтобы подробнее остановиться на ответе торбонде, вы могли бы создать функцию расширения, например:
module List =
let doIter func lst =
lst |> List.iter func
lst
таким образом, его можно красиво передать как:
[1..10]
|> List.map (fun x -> x * 2)
|> List.doIter (printfn "%d")
|> List.filter (fun x -> x % 4 = 0)
|> List.fold (fun sum x -> sum x) 0
|> printfn "%d"
Ответ №3:
Вы можете использовать List.map
еще раз и просто вернуть то же значение:
[ list of things ]
|> List.map (fun i -> some transformation)
|> List.map
(fun i ->
do stuff, like printfn or whatever
i)
|> List.filter (fun i -> ...)
|> List.andDoOtherThings... (fun i -> ...)
При более чем одном отображении последовательно их можно комбинировать, чтобы избежать дополнительного цикла:
[ list of things ]
|> List.map
(fun i ->
let x = some transformation
do stuff, like printfn or whatever
x)
|> List.filter (fun i -> ...)
|> List.andDoOtherThings... (fun i -> ...)