如何使用惯用的 F# 将数据数组转换为记录
How to convert a data array to a record using idiomatic F#
我正在尝试创建一个与硬件交互的通信库。该协议由具有 header(source/destination 地址、命令编号、长度)和命令特定负载的字节数组组成。我正在为每个命令创建记录类型,以使它们更加用户友好。
是否有比
更惯用的方法将数组转换为记录
let data = [0;1]
type Rec = {
A : int
B : int
}
let convert d =
{
A = d.[0]
B = d.[1]
}
当记录大得多时,这会变得非常乏味。
几点评论:
您的记录类型定义是伪造的 - 那里不应该有 =
。我假设你想要
type Rec = {
A : int
B : int
}
您提到了字节数组,但您的 data
值是一个列表。按索引访问 List 项是昂贵的 (O(n)),应该避免。如果您打算将其声明为数组,则语法为 let data = [|0;1|]
但我想知道记录是否适合放在这里。如果您的目标是拥有一个接受字节数组的函数,并且 returns 支持对该数据的各种强类型解释,那么可区分的联合可能是最好的。
也许是这样的:
// various possible command types
type Commands =
| Command1 of byte * int // maybe payload of Command1 is known to be an int
| Command2 of byte * string // maybe payload of Command1 is known to be a string
// active pattern for initial data decomposition
let (|Command|) (bytes : byte[]) =
(bytes.[0], bytes.[1], Array.skip 2 bytes)
let convert (bytes : byte[]) =
match bytes with
| Command(addr, 1uy, [| intData |]) ->
Command1(addr, int intData)
| Command(addr, 2uy, strData) ->
Command2(addr, String(Text.Encoding.ASCII.GetChars(strData)))
| _ ->
failwith "unknown command type"
// returns Command1(0x10, 42)
convert [| 0x10uy; 0x01uy; 0x2Auy |]
// returns Command2(0x10, "foobar")
convert [| 0x10uy; 0x02uy; 0x66uy; 0x6Fuy; 0x6Fuy; 0x62uy; 0x61uy; 0x72uy |]
我正在尝试创建一个与硬件交互的通信库。该协议由具有 header(source/destination 地址、命令编号、长度)和命令特定负载的字节数组组成。我正在为每个命令创建记录类型,以使它们更加用户友好。
是否有比
更惯用的方法将数组转换为记录let data = [0;1]
type Rec = {
A : int
B : int
}
let convert d =
{
A = d.[0]
B = d.[1]
}
当记录大得多时,这会变得非常乏味。
几点评论:
您的记录类型定义是伪造的 - 那里不应该有 =
。我假设你想要
type Rec = {
A : int
B : int
}
您提到了字节数组,但您的 data
值是一个列表。按索引访问 List 项是昂贵的 (O(n)),应该避免。如果您打算将其声明为数组,则语法为 let data = [|0;1|]
但我想知道记录是否适合放在这里。如果您的目标是拥有一个接受字节数组的函数,并且 returns 支持对该数据的各种强类型解释,那么可区分的联合可能是最好的。
也许是这样的:
// various possible command types
type Commands =
| Command1 of byte * int // maybe payload of Command1 is known to be an int
| Command2 of byte * string // maybe payload of Command1 is known to be a string
// active pattern for initial data decomposition
let (|Command|) (bytes : byte[]) =
(bytes.[0], bytes.[1], Array.skip 2 bytes)
let convert (bytes : byte[]) =
match bytes with
| Command(addr, 1uy, [| intData |]) ->
Command1(addr, int intData)
| Command(addr, 2uy, strData) ->
Command2(addr, String(Text.Encoding.ASCII.GetChars(strData)))
| _ ->
failwith "unknown command type"
// returns Command1(0x10, 42)
convert [| 0x10uy; 0x01uy; 0x2Auy |]
// returns Command2(0x10, "foobar")
convert [| 0x10uy; 0x02uy; 0x66uy; 0x6Fuy; 0x6Fuy; 0x62uy; 0x61uy; 0x72uy |]