私はいくつかの要素を生成してリストに返す関数を持っています。この関数は、返された要素をフィルタリングするためのパラメータをとります。関数は次のようになります。複数の計算式を含むリストを追加する
let create x = [1..1000] |> List.filter (fun c -> (c % x) = 0)
この関数を複数の条件で呼び出し、すべての結果を1つのリストに追加したいと思います。
最初に私は、このやって考えていた:
let result = (create 100)
|> List.append (create 300)
|> List.append (create 500)
|> List.append (create 3)
printf "%A" result
をしかし、私はこのソリューションは、エレガントでList.append
式で繰り返し見つけることができませんでした。
は、私は2番目の解決策を試してみました:
let result = [100; 300; 500; 3] |> List.map (fun c -> create c)
|> List.reduce (fun acc c -> acc |> List.append c)
printf "%A" result
このソリューションは、より簡潔であるが、私はそれについて好きではない何かがあります。私たちが達成しようとしたことを推測することは、あまり明確ではなく、より困難でした。
だから、私は第三ソリューションを探してと計算式を使用して新しいソリューションを実装することを試みた。
type AppendBuilder() =
member this.Bind (x, f) = f x |> List.append x
member this.Return x = x
をし、そのようにそれを使用します。
let append = new AppendBuilder()
let result = append {
let! a = create 100
let! b = create 300
let! c = create 500
let! d = create 3
return []
}
printf "%A" result
この最後のソリューションは、動作し、私はそれを好む。私たちが何をしているのか、繰り返しList.append式がないのかをより理解しやすくなっています。しかし、まだ何かが間違っています。私はreturn []
の部分が好きではありませんが、これは不自然で不明瞭です。しかし、このトリックはそれを動作させるために必要です。
第3の解決策は私のお気に入りですが、これが私の問題を解決する正しい方法であるかどうかはわかりません。それは問題を解決する、私は正しい結果を得るが、これが正しいアプローチであるかどうかわからない。
第3の解決策を自分の意図を混乱させることなく維持できますか?解決策はそれをそのまま維持するのに十分明確ですか?私は、コード(ここではList.append
と呼んでいます)を寄生させる反復的な表現なしに、アクション(ここではcreate x
と呼んでいます)に焦点を当てたソリューションを探しています。
seq
計算の怠惰の恩恵を受けることができる
のような '[100; 300; 500; 3] |> List.collectは私が投稿の答えのすべてにわたり@JohnPalmerのソリューションを好む –
をcreate' 。これは、ライブラリ関数を最大限に活用しています。 - すべてのポストされたソリューションとは対照的に - 前の計算ステップからの引数( '[100; 300; 500; 3]')を許可します。 –
はい、計算を出発点としてデータの変換として表現し、他の要件(たとえば、パフォーマンス)がそれを要求する場合は、それから離れるようにしてください。 – TheQuickBrownFox