F# append to list in a loop functiuonally
F# append to list in a loop functiuonally
我希望将此代码转换为使用 F# 列表而不是 C# 列表实现。
我正在连接到一个数据库,运行 通常使用 C# 的查询会创建一个类型的列表,并在数据读取器具有值时继续添加该列表。我将如何将其转换为使用 F# list
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
let transactions = new List<string>()
let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
let json = dataReader.GetString(1)
transactions.Add(json)
transactions
这里的棘手之处在于输入数据源本质上是命令式的(您必须调用 Read
来改变内部状态)。因此,您正在从命令式世界过渡到功能性世界 - 因此您无法避免所有变化。
我可能会使用列表理解来编写代码,它保持类似的熟悉结构,但删除了显式突变:
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
[ let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
yield dataReader.GetString(1) ]
Tomas 的回答是在产品代码中使用的解决方案。但是为了学习 F# 和函数式编程,我用 tail recursion 和 cons operator:
展示了我的代码片段
let drToList (dr:DataReader) =
let rec toList acc =
if not dr.Read then acc
else toList <| dr.GetString(1) :: acc
toList []
这个tail递归函数被编译成命令式代码,因此没有堆栈溢出和快速执行。
另外,我建议您查看 this C# thread and this F# 文档,了解如何正确处理您的命令。基本上,您需要像这样使用 smth:
let queryDb (conn: NpgsqlConnection) (qStr: string) =
use cmd = new NpgsqlCommand(qStr, conn)
cmd.ExecuteReader() |> drToList
如果我们更深入,您还应该考虑异常处理。
我希望将此代码转换为使用 F# 列表而不是 C# 列表实现。
我正在连接到一个数据库,运行 通常使用 C# 的查询会创建一个类型的列表,并在数据读取器具有值时继续添加该列表。我将如何将其转换为使用 F# list
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
let transactions = new List<string>()
let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
let json = dataReader.GetString(1)
transactions.Add(json)
transactions
这里的棘手之处在于输入数据源本质上是命令式的(您必须调用 Read
来改变内部状态)。因此,您正在从命令式世界过渡到功能性世界 - 因此您无法避免所有变化。
我可能会使用列表理解来编写代码,它保持类似的熟悉结构,但删除了显式突变:
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
[ let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
yield dataReader.GetString(1) ]
Tomas 的回答是在产品代码中使用的解决方案。但是为了学习 F# 和函数式编程,我用 tail recursion 和 cons operator:
展示了我的代码片段let drToList (dr:DataReader) =
let rec toList acc =
if not dr.Read then acc
else toList <| dr.GetString(1) :: acc
toList []
这个tail递归函数被编译成命令式代码,因此没有堆栈溢出和快速执行。
另外,我建议您查看 this C# thread and this F# 文档,了解如何正确处理您的命令。基本上,您需要像这样使用 smth:
let queryDb (conn: NpgsqlConnection) (qStr: string) =
use cmd = new NpgsqlCommand(qStr, conn)
cmd.ExecuteReader() |> drToList
如果我们更深入,您还应该考虑异常处理。