I’ve got the following example:
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
First of all, sorry for the terribly messy code, I’m only a beginner in F#. As you may see the three format overloads differ only for their argument type, while their body is the same (although calling different overloads of write). Is it possible somehow to reduce the format functions to one, maybe inlined?
I apologize in case I’m completely missing the point here, but I couldn’t find much information about the matter.
I think that the way you wrote it is probably the best option.
If you don’t want to do boxing, then the overloaded
writefunction is definitely needed, because the serialization needs to be implemented differently for different types. Usinginlinemember also doesn’t work in this case, becauseinlinefunction can only require a specific instance or static method on some value it gets, but not a specific overload.A reasonable solution that avoids some duplication is to define just a single overloaded function (i.e.
write) and then pass it explicitly as an argument to other functions if they need it. You could write something like:This avoids some code duplication at the definition side, but it makes the usage longer. If you don’t need many functions like
Format, then the best way may be to define an overload with some code duplication as you did originally.Regarding
inline, you can use that to specify that a type of the argument should implement some specific member (either instance or static), but you cannot say that there should be a specific overload. If you wrote wrappers for all three types (int16,string, …) that had a static memberWrite, then you could write:… but that’s even more complex solution that also requires writing some additional code when calling
format, so I wouldn’t really use that approach (but it may be useful to know that it exists).