Didn't read, because mouse scroll wheel doesn't work. Honestly, who thinks this stuff is a good idea?
I think it's a good idea, btw :-)
You can run code on your slides, check http://talks.golang.org/2012/concurrency.slide#14
111–120 of 153 posts
Didn't read, because mouse scroll wheel doesn't work. Honestly, who thinks this stuff is a good idea?
I think it's a good idea, btw :-)
You can run code on your slides, check http://talks.golang.org/2012/concurrency.slide#14
Earlier quoted context omitted.
Having trouble picturing a better solution that isn't also morally equivalent to goto. Would you mind providing an example of your preferred approach?
Straight exceptions are also goto-like, but there's the slight improvement that they allow you to (automatically) refactor out the middle of a function without changing the behaviour. The solution I prefer is a monad with some light notation (Haskell do, scala for/yield). So it looks like: def doSomething(): Validation[Whatever] = for { result1 The Is this goto-like? You could argue so - once one computation fails, t…
Odd choice of examples... 1. The file I/O makes the case for including exceptions in the language. Specifically, adding one-off types to deal with exceptions is a bug, not a feature. There is a good case against exceptions but that ain't it. 2. On slide 5, it appears to show that you have to use a switch statement on a generic to get polymorphism because the language doesn't support overloading. Again, looks more lik…
class Gopher:
def dump_binary(self, writer):
"""Write this Gopher to given writer, raise IOError on error."""
binary.write(writer, binary.LittleEndian, len(self.name))
writer.write(self.name)
binary.write(writer, binary.LittleEndian, self.age)
binary.write(writer, binary.LittleEndian, self.fur_color)
I can see the argument for Go-style explicit error handling, but having this as the first best-practice example just doesn't sit right or sell it very well.Edit: Okay, I guess I should have read the next slide before commenting. Still, the "one-off utility type" is longer and more complex than the original error handling (so I wouldn't do it unless you're using it elsewhere as well).
Earlier quoted context omitted.
Short circuit returns are the devil - they make it much harder to factor out part of a function into a smaller function. A function should have one entry point and one exit point; that's the whole point of structured programming. If you're going to return from some random point in the middle of your function you might as well be using goto. (Of course, good programming languages provide a better solution than pyramid…
> Short circuit returns are the devil vi! Naïve, absolutist positions in areas of long-standing debate between programmers of great experience and the highest imaginable competence just makes you look ridiculous.
By and large, the best programmers eschew nesting in favor of early returns. Invariably (in my experience) those who argue against early returns are inferior programmers (and not only by virtue of lacking taste in this particular debate).
Earlier quoted context omitted.
Straight exceptions are also goto-like, but there's the slight improvement that they allow you to (automatically) refactor out the middle of a function without changing the behaviour. The solution I prefer is a monad with some light notation (Haskell do, scala for/yield). So it looks like: def doSomething(): Validation[Whatever] = for { result1 The Is this goto-like? You could argue so - once one computation fails, t…
I don't see how the <- clues you in any better than the error handling that things might exit early. It seems from your response that the goto-ness of the go solution is not what you're really objecting to, because your proposal is equally goto-y. As far as I can tell, it's really the if-else verbosity that you don't like, which is fine (and I agree, exceptions are better), but it has nothing to do with the "whole po…
Compare how smalltalk didn't have a conditional control flow statement. Rather, the boolean type has a polymorphic method that takes a block and then executes it or not.
The other nice thing about this approach is it makes the language simpler and more regular because it's implemented using standard language constructs rather than a special statement. E.g. you can write a "gather" function that takes a collection of monads and returns a monad of the collection, and this is generic in the monad (so the same function works to turn a List of Futures into a Future of a List, a List of Validations into a Validation of a List, etc.)
Earlier quoted context omitted.
> Short circuit returns are the devil No, they're not. > they make it much harder to factor out part of a function into a smaller function They generally make the function smaller, that's what guard clauses are for. > A function should have one entry point and one exit point That's absurd and makes for very ugly and unnecessary code.
> They generally make the function smaller, that's what guard clauses are for. My point is: frequently, one wants to extract a part from the middle of a function to make a new function. This is very easy (and can usually be done automatically) unless said part contains a return.
Earlier quoted context omitted.
No way, the next slide is the very definition of evil unmaintainable code . Go through what is happening quickly: bw := &binWriter{w: w} bw.Write(int32(len(g.Name))) bw.Write([]byte(g.Name)) bw.Write(g.Age) bw.Write(g.FurColor) return bw.err If an error happens on L2, we will still run writes L3-L5. Why is this bad? Because in the future, we might come in and add logic after the writes complete. We have to make sure…
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 ||…
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...
Earlier quoted context omitted.
> Short circuit returns are the devil vi! Naïve, absolutist positions in areas of long-standing debate between programmers of great experience and the highest imaginable competence just makes you look ridiculous.
Naive, absolutist positions in areas of long-standing consensus between programmers of great experience and the highest imaginable competence makes one look even more ridiculous. By and large, the best programmers eschew nesting in favor of early returns. Invariably (in my experience) those who argue against early returns are inferior programmers (and not only by virtue of lacking taste in this particular debate).
Yup.
> Invariably (in my experience) those who argue against early returns are inferior programmers (and not only by virtue of lacking taste in this particular debate).
Yup.
if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
Because the alternative is worse. If you test-and-return after every call, your function has multiple exit points and is far less maintainable. If you nest like this, you at least have a chance of maintaining a single exit point in your function (even though this example fails to do so). This is why the Lord invented exceptions, which it seems that Go does not use. This one example is enough to convince me to never u…
Most of the time when error checking, returns (or in C, gotos) are fine and lead to more readable code that's easy to make sense of and easy to step through with a debugger.
Please don't fall into the trap of believing that I am
terribly dogmatic about [the go to statement]. I have the
uncomfortable feeling that others are making a religion
out of it, as if the conceptual problems of programming
could be solved by a simple trick, by a simple form of
coding discipline!
- Dijkstra (1973) in personal communication to Donald Knuth , quoted in Knuth's "Structured Programming with go to Statements"if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
People end up doing this because code gets written incrementally and often we start out wrong (e.g. here with the wrong/inverted condition). Rewriting large code blocks for a little more clarity is often a PITA. It would help very much if editors supported this better (e.g. single keystroke inversion of an "if"). Go with its easy syntax would be a particularly good target for automatic rewrites for code like the abov…