I'd like to discuss code styling for a minute. It would be good to agree on a general approach of the code we'd like to write. Here are some examples, I'd like to hear more about what you think
##Code styling
Embedded type and optimized struct sizes
type Format struct {
SampleRate uint32
Channels int16
}
type Buffer32 struct {
Format
Data []float32
}
vs pointers and convenient field types
type Format struct {
SampleRate int
Channels int
}
type Buffer32 struct {
Format *Format
Data []float32
}
Convenient but straight forward constructor
func NewBuffer32(format Format, sampleCount int) *Buffer32 {
return &Buffer32{
Format: format,
Data: make([]float32, sampleCount, sampleCount),
}
}
vs DIY approach. (note that in this code, the sample count should probably
multiple by the number of channels which is an easy thing to forget.)
&Buffer32{
Format: format,
Data: make([]float32, sampleCount),
}
Explicit, manually, duplicated functions
func (buffer *Buffer32) Process32(output *Buffer32) error {
// stuff
return nil
}
func (buffer *Buffer64) Process64(output *Buffer64) error {
// stuff
return nil
}
vs interface and type switching
func Process(buf1, buf2 Buffer) error {
switch t := t.(type) {
*Buffer32:
// some stuff
*Buffer64:
// some other stuff
}
return nil
}
vs using go generate for any functions implemented the same way in float32 and 64
I personally like:
2: I don't think the convenience of a having a field in a type we can easily manipulate trumps the memory size gain. Plus using a pointer would allow us to provide predefined formats.
3: Constructors are often convenient, especially as entry points and when the setup isn't trivial. This example is a good example since it was was written by hand and technically has a bug. This bug would be mitigated by a constructor. It does come at a price of a bigger API and potentially surprising behaviors.
Finally 5: It might be a bit of a pain at first but it works better with code completion (easier for people not knowing the API), it can be optimized (custom logic and/or SIMD) but can be the source of more bugs (fix something on the float32 side but not float64 for instance). 7 (code generation) is nice but it always feels a bit clunky to have to move things outside of the code generation path because of some edge cases.
@egonelbre @kisielk @nigeltao what do you think?