Well, being I am unlikely  to gain the benefit of the as yet not fully 
settled specification anytime during this or several possible future 
projects, I was mainly posting these thoughts in part not to address the 
topic of future changes but more so to highlight the considerations anyone 
wanting to implement generic data structures should consider in their 
implementation, when using Go 1.

It didn't occur to me until I was thinking about the issues raised in 
constructing a bundle of compound literals to define the parameters for 
multi-command CLI applications that such declarations really have to be 
sanitised just like any untrusted input. In some cases the errors may be 
entirely trivial and not able to cause unintended effects later on, but 
anything less than an exhaustive validation could conceal a serious 
security hole potentially for a very long time. And thus also, should such 
mechanisms be built into the language, they have to be likewise as 
stringently checked.

It's not that you can't do generics in Go, that's not true, because we have 
the interface{}, it's just that in most cases you have to repeat a lot of 
code to maintain type safety. Exceptions and generics are really 
indispensible mechanisms in programming, but many languages threw them in 
without completely exhausting all the facets of them and create issues both 
in security and stability, as well as the no less important issue of 
diminishing readability and maintainability (it's so bad in some languages 
that holy water and crucifixes are maybe not a bad backup countermeasure!)

People tend to focus on the convenience of novel syntactic constructs and 
forget all the monsters that can spring out from the absence of care in the 
design. The one thing that I want to see, in the end stages of the design 
process, is that what is added doesn't take something away, especially 
something that isn't obvious and explicit. The most dangerous bugs are the 
least visible.

On Tuesday, 26 February 2019 00:37:50 UTC+1, Burak Serdar wrote:
>
> On Mon, Feb 25, 2019 at 3:06 PM Louki Sumirniy 
> <louki.sumir...@gmail.com <javascript:>> wrote: 
> > 
> > I am in the middle of implementing a generic tree type as part of a CLI 
> flags/configuration package, and a key goal in my design is to make the 
> declarations it parses as easy to read as possible, and as far as possible, 
> avoiding too much boilerplate. 
> > 
> > Yes, nothing new there, but in the process, I have noticed something 
> that isn't at the top of people's minds when they think of generic data 
> types: validation 
> > 
> > Actually, default values is another aspect of generics as well, because 
> a generic type also has to have some kind of valid new/empty state, to stay 
> consistent with the way that the builtins are always zeroed before use, but 
> I'll address the former first. 
> > 
> > Well, ok, let's just say that implementation of generic structures, 
> (which implicitly aren't very generic in implementation), works with the 
> interface{} container, which is a very limited Set structure, with one 
> implicit function that when satisfied makes the variable it encapsulates 
> recognised as a complete implementation and permits interchange with other 
> implementations' type. 
> > 
> > So, in Go, this means (and same in all languages though they sugar coat 
> it in various automatic stuff) that before you can call methods on a 
> generic type, the contents of the variable have to be checked. 
> > 
> > From where I am at right now, this is of course my job as the programmer 
> to write these. However, my reason for all the rambling up to this point is 
> that I think that since validation is mandatory for dynamic types, that the 
> proposed generics syntaxes that are under consideration should include 
> constraint/contract type validation. For this, then there must be a 
> constructor and a bounds/validation function that ensures that its methods 
> will find everything that must be there, where it must be, preferably 
> before the main() is invoked. 
>
> Have you seen the contracts draft? This addresses the validation issue 
> you raised, in compile time: 
>
> https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md 
>
> With lots of feedback and alternative suggestions: 
>
> https://github.com/golang/go/wiki/Go2GenericsFeedback 
>
>
> > 
> > On the latter subject, well, I think I already covered that - just 
> simply that when you declare a new type, all zeroed may not actually be a 
> valid new and empty variable. The specifics of a type may mean that certain 
> things must be in certain places, and the things that are in the container 
> are valid members of the set of possible contents and that these members 
> contents are not outside of the bounds that would lead to bugs. 
> > 
> > It does lead me to a thought about a go-idiomatic style of generic type, 
> however - and it all centers around the type declaration syntax. Not all 
> generics are going to need something other than the standard zeroing, so 
> the initialiser function need not be mandatory. This is starting to blend 
> in an unseemly way into some parts of OOP with the concept of a constructor 
> (go dodges the need for destructors mostly, but I would suppose in 
> implementation a destructor might be a good idea especially for resources 
> that need freeing manually). 
> > 
> > Actually, right there might be another issue that might be important 
> with generics, but more generally - if there could be some way to tag a 
> type such that unless you specify otherwise, it runs its closer on 
> implicitly on close of the function scope it lives in, and this also 
> suggests that some means of indicating this relationship between two 
> methods would also make sense. 
> > 
> > So, taking stock, I am saying that a consistent Go styled generic would 
> need to have builtins for initialisation to valid empty state, one for 
> freeing resources locked up during lifecycle, and some way of specifying a 
> valid range off values for the type. 
> > 
> > When you really look at it, implementing generics basically means code 
> generation involving a lot of reflection, or, the likely and better option, 
> that compilation creates tagged sets for every type defined in a package, 
> so that these attributes are available without the expensive parsing of the 
> metadata tied up in the symbol table. If my surmise is correct, it means 
> that creating a complete generics syntax for Go also means creating 
> constructors, destructors, validation/sanitising, and adding the necessary 
> metadata to be efficiently accessible at runtime instead of parsed out of 
> linker metadata. 
> > 
> > It also brings up the issue that there is a more than subtle connection 
> between generic types and exception/error handling, with regard to 
> validation, the construct required for this is structurally similar to 
> error handling, in that, already I have described initialisation, 
> deallocation, and validation, all of these are states, and in 
> implementation it means that one should consider carefully whether there is 
> other things that seem at first blush, peripheral, but should be considered 
> indispensible... 
> > 
> > Namely, the error value. 
> > 
> > I thought a lot about this in the last few weeks, and I had already in 
> practise experimented with creating pipeline-pattern types using 
> interfaces, in which the error was inside the struct containing the 
> variable data (byte slice in this case), and the interface included several 
> methods relating to the examination, setting and resetting of the error 
> value. I didn't quite get to fully codifying in my mind exactly what was 
> mandatory and what you will regret not putting in there (to prevent edge 
> cases and potential injections). 
> > 
> > Think about the situation with the basic, machine-level built-in types. 
> Do ints and floats have an error value? Superficially, one might say 'no' 
> based on what is specified in the Go language definition. But this is 
> entirely incorrect. These types are implemented mostly 100% directly in the 
> CPU, and every operation involving them can affect the Condition Code 
> register. Normally this state information is transparently part of the 
> various comparison operators, but I can see how it would make a lot of 
> sense if you could interrogate these variables and get some representation 
> of the CC, and that this metadata would have to be part of any error 
> handling scheme added to the language. 
> > 
> > And then, if we expose this data in these base types, logically the 
> metadata for errors in compound, especially generic types, has a further 
> set of type-specific states. This also could help a lot with both error and 
> generics handling, for example, one of the flags could indicate that the 
> last thing done to the variable was being zeroed. For some purposes, 
> receiving an unmodified fresh variable could be written in as a constraint 
> in the function header, so you would have !nil and !zero constraints on a 
> generic method parameter, and, well, I'll just finish on this last point - 
> a lot of error handling becomes irrelevant when you can concisely specify 
> constraints on a parameter's values and states, that cuts it off at the 
> pass. 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups "golang-nuts" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an email to golang-nuts...@googlegroups.com <javascript:>. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to