Types 是";隐式重载“;可能的
我有下面的例子:Types 是";隐式重载“;可能的,types,f#,arguments,overloading,implicit,Types,F#,Arguments,Overloading,Implicit,我有下面的例子: type Stream (capacity) = let data = Array.zeroCreate capacity member private s.position = ref 0 static member private encoder = new Text.UTF8Encoding() static member private write (x, o, a : byte[]) = for i = 0 to 3 do a.[o +
type Stream (capacity) =
let data = Array.zeroCreate capacity
member private s.position = ref 0
static member private encoder = new Text.UTF8Encoding()
static member private write (x, o, a : byte[]) = for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256)
static member private write (x, o, a : byte[]) = for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s)
static member private write (x : string, o : int, a : byte[]) = Stream.encoder.GetBytes(x, 0, x.Length, a, o)
static member format (x : int, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
static member format (x : int16, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
static member format (x : string, s) = let a = Array.create s 0uy in Stream.write(x, 0, a); a
类型流(容量)=
让data=Array.zero创建容量
成员私人s.position=参考0
静态成员私有编码器=新文本。UTF8Encoding()
静态成员私有写入(x,o,a:byte[])=对于i=0到3执行a.[o+i]>>24-i*8)%256)
静态成员私有写入(x,o,a:byte[])=对于i=0到1执行a.[o+i]>>24-i*8)%256s)
静态成员私有写入(x:string,o:int,a:byte[])=Stream.encoder.GetBytes(x,0,x.Length,a,o)
静态成员格式(x:int,s)=让a=Array.creates0uy在Stream.write(x,0,a);A.
静态成员格式(x:int16,s)=让a=Array.create在Stream.write(x,0,a)中创建s0uy;A.
静态成员格式(x:string,s)=让a=Array.creates0uy在Stream.write(x,0,a);A.
首先,很抱歉代码非常混乱,我只是F#的初学者。正如您可能看到的那样,三个格式
重载只因其参数类型不同而不同,而它们的主体是相同的(尽管调用写入
的不同重载)。是否有可能将格式函数减少到一个,可能是内联的
如果我完全没有抓住要点,我很抱歉,但是我找不到关于这件事的更多信息。我认为你写这篇文章的方式可能是最好的选择 如果不想装箱,那么肯定需要重载的
write
函数,因为序列化需要针对不同的类型以不同的方式实现。在这种情况下,使用inline
成员也不起作用,因为inline
函数只能在它获得的某个值上要求特定的实例或静态方法,而不能要求特定的重载
避免某些重复的合理解决方案是只定义一个重载函数(即write
),然后在其他函数需要时将其作为参数显式传递给其他函数。你可以这样写:
type Stream (capacity) =
let data = Array.zeroCreate capacity
member private s.position = ref 0
static member private encoder = new Text.UTF8Encoding()
static member Write (x, o, a : byte[]) =
for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256)
static member Write (x, o, a : byte[]) =
for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s)
static member Write (x : string, o : int, a : byte[]) =
Stream.encoder.GetBytes(x, 0, x.Length, a, o) |> ignore
// Format takes a writer function 'f' as the first argument
static member Format (x, s) f = let a = Array.create s 0uy in f(x, 0, a); a
// When you call 'Format' with 'Stream.Write' as an argument,
// the compiler chooses the right overload for you
Stream.Format (1s, 100) Stream.Write
Stream.Format ("foo", 100) Stream.Write
。。。但这是一个更复杂的解决方案,在调用
格式时还需要编写一些额外的代码,因此我不会真正使用这种方法(但知道它的存在可能会很有用)。我认为您编写它的方式可能是最好的选择
如果不想装箱,那么肯定需要重载的write
函数,因为序列化需要针对不同的类型以不同的方式实现。在这种情况下,使用inline
成员也不起作用,因为inline
函数只能在它获得的某个值上要求特定的实例或静态方法,而不能要求特定的重载
避免某些重复的合理解决方案是只定义一个重载函数(即write
),然后在其他函数需要时将其作为参数显式传递给其他函数。你可以这样写:
type Stream (capacity) =
let data = Array.zeroCreate capacity
member private s.position = ref 0
static member private encoder = new Text.UTF8Encoding()
static member Write (x, o, a : byte[]) =
for i = 0 to 3 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256)
static member Write (x, o, a : byte[]) =
for i = 0 to 1 do a.[o + i] <- byte((x >>> 24 - i * 8) % 256s)
static member Write (x : string, o : int, a : byte[]) =
Stream.encoder.GetBytes(x, 0, x.Length, a, o) |> ignore
// Format takes a writer function 'f' as the first argument
static member Format (x, s) f = let a = Array.create s 0uy in f(x, 0, a); a
// When you call 'Format' with 'Stream.Write' as an argument,
// the compiler chooses the right overload for you
Stream.Format (1s, 100) Stream.Write
Stream.Format ("foo", 100) Stream.Write
。。。但这是一个更为复杂的解决方案,在调用format
时还需要编写一些额外的代码,因此我不会真正使用这种方法(但知道它的存在可能会有用)。重构format
函数是显而易见的;您可以创建通用格式函数并传递不同的流。将函数作为参数写入。首先,将泛型函数置于类的任何成员之前:
static let formatGeneric writeFunc x s =
let a = Array.create s 0uy
writeFunc(x, 0, a)
a
并使用它来实例化不同的格式函数:
static member format (x, s) =
formatGeneric (fun (x: int, i, a) -> Stream.write(x, i, a)) x s
static member format (x, s) =
formatGeneric (fun (x: int16, i, a) -> Stream.write(x, i, a)) x s
static member format (x, s) =
formatGeneric (fun (x: string, i, a) -> Stream.write(x, i, a)) x s
请注意,Stream.write
是以完整形式编写的,并且对x
类型进行了注释,以选择合适的重载。重构格式
函数是显而易见的;您可以创建通用格式函数并传递不同的流。将函数作为参数写入。首先,将泛型函数置于类的任何成员之前:
static let formatGeneric writeFunc x s =
let a = Array.create s 0uy
writeFunc(x, 0, a)
a
并使用它来实例化不同的格式函数:
static member format (x, s) =
formatGeneric (fun (x: int, i, a) -> Stream.write(x, i, a)) x s
static member format (x, s) =
formatGeneric (fun (x: int16, i, a) -> Stream.write(x, i, a)) x s
static member format (x, s) =
formatGeneric (fun (x: string, i, a) -> Stream.write(x, i, a)) x s
请注意,Stream.write
是以完整形式编写的,并且对x的类型进行了注释,以选择合适的重载。这似乎更合适。有没有一种方法可以在不装箱x的情况下执行此操作?这是一个好问题。。。你写这篇文章的方式看起来更像是一个OO程序,而不是一个函数程序。T0yv0在这里使用了一个类型字典来存储序列化函数,但他肯定每个类型都有一个序列化函数:这似乎更合适。有没有一种方法可以不用装箱x来完成它?这是一个好问题。。。你写这篇文章的方式看起来更像是一个OO程序,而不是一个函数程序。这里的T0yv0使用了一个类型字典来存储序列化函数,但他肯定每个类型都有一个序列化函数:非常感谢你的解释和建议的替代方法!非常感谢您的解释和建议的替代方式!