Hacker News new | ask | show | jobs
by Someone 4698 days ago
I would prefer to see something like (probably not legal Go, but would work in C, if err is of type bool):

   err = Write(int32(len(g.Name)))
   err |= Write([]byte(g.Name))
   err |= Write(g.Age)
   err |= Write(g.FurColor)
   return err;
If err is of type int with 0 == noError, this will require some new syntax if you want to return the correct error code (which you should want to do). I would suggest introducing

   x ||= y    <===>    x = x || y
In English: if x (still) equals its default, evaluate y and assign the result to x"

One could even shortcut this to

   err = Write(int32(len(g.Name)))
         || Write([]byte(g.Name))
         || Write(g.Age)
         || Write(g.FurColor)
   return err;
Advantage: that's how the shell works, too. Disadvantage is that 'logical or' is not what one associates with "run items until first failure", but that can be learned.

An alternative could be to have a language construct that takes a sequence of lambda's, executes them in sequence until the first one that fails (if any) and returns the index and the result code of the failing lambda. That would get you something like:

   index,err = SEQ([
           Write(int32(len(g.Name)))
           , Write([]byte(g.Name))
           , Write(g.Age)
           , Write(g.FurColor)
         ]);
I like the first idiom better, though.
4 comments

I've used a pattern such as this in my code [1]:

   	do := func(n int, err error) {
		if err != nil {
			panic(err)
		}
	}

        do(string.Write(/* 1 */))
        do(string.Write(/* 2 */))
        // ...
        do(string.Write(/* n */))
In fact, the pattern I've found is to declare throw-away lambdas [2] that I then call (few lines later). I haven't looked at all the pros/cons of doing this, but so far I find it's a very versatile way of doing.

[1]: https://github.com/aybabtme/graph/blob/master/digraph.go#L61 [2]: https://github.com/aybabtme/graph/blob/master/digraph.go#L10...

> An alternative could be to have a language construct that takes a sequence of lambda's, executes them in sequence until the first one that fails (if any) and returns the index and the result code of the failing lambda.

You could write a function in Go as it is that takes a sequence of lambdas and does that, so why would you need a language construct?

> You could write a function in Go as it is that takes a sequence of lambdas and does that, so why would you need a language construct?

You'd want generics if you wanted the chain to return a result though (or if you wanted intermediate steps to thread results through).

You can panic inside Write() and recover at the top of the DumpBinary() function. This has been demonstrated by Rob Pike and Andrew Gerrand in a talk at Google IO.

As long as you don't leak panics outside of your package, it's OK to use them for non-local error returns.

Yes, but that would work best if the culture was to panic to signal errors. If it is not (as IIRC in go), you need to wrap common library calls to do so.
So basically, monads.