Live data from Hacker News

Replacing Clever Code with Unremarkable Code in Go

vividcortex.com

111–120 of 140 posts

Re: Replacing Clever Code with Unremarkable Code in Go

#111
post #109
post #106

Earlier quoted context omitted.

> No, not just for the implementers. For the users too. You haven't bothered to address option types. This sort of unqualified assertion may lead people to believe Go's questionable design decisions were, in fact, made out of ignorance. A language with null references is exactly like a language with option types, where every reference value is by default optional. Removing this default does not increase complexity fo…

> A language with null references is exactly like a language with option types, where every reference value is by default optional. Yes. > Removing this default does not increase complexity for the user. Yes, it does. They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. They must also perform checks when converting values from optiona…

Null references do make reading code more complex for the user since every function call must be prefaced with a null check. If I make a function call in every line of my code adding all the null checks would easily double my line count, burying my code in Java-like verbosity (ok not that much but you get the idea). I suppose a good IDE could help with this if option types remain unavailable.

Another common complaint with null references is that there is no compile-time type safety that you get with option types. The go team could mitigate this by having the compiler check for possible null references that may not have been caught and emit warnings or refuse to compile.

Re: Replacing Clever Code with Unremarkable Code in Go

#112

Earlier quoted context omitted.

If anything, generics reduce the mental expense of reading code, because if a container has a generic value type I know that it isn't going to be doing something interesting to those values behind the scenes.

I would like to add on to this: Generics may not be the correct solution, but I would really like a way to make collections which are general enough to be used by any datatype. As of now, I cannot do that without doing the typical `interface{}` approach. The built-in data structures + channels are able to handle this, but if I just want a set of elements, what do I do? Make a `map[foo] bool`? If I see such a piece of…

Your puzzling "generic set" isn't what is usually meant by a generic set in a statically typed language.

A generic set would be defined disregarding the type of its elements: "set of ?s". However, a single instance of a generic set would only be allowed to contain members of a single type: "set of foos". This is called parametric polymorphism.

Re: Replacing Clever Code with Unremarkable Code in Go

#113
post #111
post #109

Earlier quoted context omitted.

> A language with null references is exactly like a language with option types, where every reference value is by default optional. Yes. > Removing this default does not increase complexity for the user. Yes, it does. They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. They must also perform checks when converting values from optiona…

Null references do make reading code more complex for the user since every function call must be prefaced with a null check. If I make a function call in every line of my code adding all the null checks would easily double my line count, burying my code in Java-like verbosity (ok not that much but you get the idea). I suppose a good IDE could help with this if option types remain unavailable. Another common complaint…

> Null references do make reading code more complex for the user since every function call must be prefaced with a null check.

Well, the Go code I see doesn't look like this, so that can't be right.

Re: Replacing Clever Code with Unremarkable Code in Go

#114
post #106
post #105

Earlier quoted context omitted.

> For code to be correct in the presence of null references, the programmer must remember to check every nullable value of uncertain status, without support from the compiler. If you don't have null pointers then you need to push the responsibility for checking for initialization somewhere. You seem to be advocating that place is in the type system. That's fine, but you can't say it wouldn't make the type system more…

> No, not just for the implementers. For the users too. You haven't bothered to address option types. This sort of unqualified assertion may lead people to believe Go's questionable design decisions were, in fact, made out of ignorance. A language with null references is exactly like a language with option types, where every reference value is by default optional. Removing this default does not increase complexity fo…

The main Go authors come from a C background, and they despise C++ and Java. It seems that those languages are their main experience, and hence, Go does not look too different from them.

Go was originally presented as a "systems" programming language, and as a C++ replacement. It failed to attract C++ and other systems programmers, while attracting Python and Ruby coders. In retrospect, it seems to make sense.

I suspect the reason adding generics is hard in Go is a due to its weird composition system (they loathe object hierarchies too, remember?)

I concur, that we should be using and developing languages that have strong, expressive type systems. Furthermore, these languages are not "complex" to use or understand. I really admire what the Rust people are doing. They are writing a browser engine while developing the language, so they can continually evaluate their design choices, and if needed, change things as they go.

Go looks like it has been designed into a corner, but it is too late to back up now. The main driving force it has is that it has Google as a brand name behind it, unfortunately. Otherwise, it most likely wouldn't have gone anywhere.

Re: Replacing Clever Code with Unremarkable Code in Go

#115
post #110
post #109

Earlier quoted context omitted.

> A language with null references is exactly like a language with option types, where every reference value is by default optional. Yes. > Removing this default does not increase complexity for the user. Yes, it does. They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. They must also perform checks when converting values from optiona…

> They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. Being aware of the semantics of the option mechanism is exactly like being aware of the semantics of null references. You've just agreed one is like the other with a default. Specifying whether a value is optional is less complex than the usual way of specifying whether a referenc…

> Surely you mean the other way around?

Yes, I had it backwards. Corrected.

> Specifying whether a value is optional is less complex than the usual way of specifying whether a reference can be null — a documentation comment.

Is it? I agree there's definite virtue in having this property checked by the compiler, but I think you and I will have to disagree on the notion of complexity here.

Re: Replacing Clever Code with Unremarkable Code in Go

#116
post #109
post #106

Earlier quoted context omitted.

> No, not just for the implementers. For the users too. You haven't bothered to address option types. This sort of unqualified assertion may lead people to believe Go's questionable design decisions were, in fact, made out of ignorance. A language with null references is exactly like a language with option types, where every reference value is by default optional. Removing this default does not increase complexity fo…

> A language with null references is exactly like a language with option types, where every reference value is by default optional. Yes. > Removing this default does not increase complexity for the user. Yes, it does. They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. They must also perform checks when converting values from optiona…

[deleted]

Re: Replacing Clever Code with Unremarkable Code in Go

#117
post #115
post #110

Earlier quoted context omitted.

> They need to be aware of the semantics of the option mechanism, how to specify whether a type is optional, and when that is appropriate. Being aware of the semantics of the option mechanism is exactly like being aware of the semantics of null references. You've just agreed one is like the other with a default. Specifying whether a value is optional is less complex than the usual way of specifying whether a referenc…

> Surely you mean the other way around? Yes, I had it backwards. Corrected. > Specifying whether a value is optional is less complex than the usual way of specifying whether a reference can be null — a documentation comment. Is it? I agree there's definite virtue in having this property checked by the compiler, but I think you and I will have to disagree on the notion of complexity here.

The beauty of Option types is that they are mostly used as return types. Most function arguments are non-nullable pointers or references; only ones that might be None are passed as options. This makes reasoning about code much easier. I just look at the function signature, and I know the types of arguments it expects. I also don't have to litter the beginning of each function call with if !null checks to each reference parameter.

> They must also perform checks when converting values from optional to non-optional types.

There are multiple ways to manipulate option type variables. The following comment from a Redditor sums it up very nicely:

"What is interesting is that (coming from scala and haskell) you almost never pattern-match on option types. The power of option, imho, is that you don't have to care whether it is Some or None, you write the same code regardless. If you are pattern-matching the whole time, you haven't gained all that much over checking for nil/null.

Option is a container, and we can use my_var.chain(...) and my_var.map(...) to update the things in the container. And the joy of it is that these methods will automatically do the right thing, with repect to Some/None, so you can string a bunch of these calls together, and if my_var is Some(...) is will apply all of the specified functions. If it is None, it will remain None."

source: http://www.reddit.com/r/rust/comments/1ewrhz/pattern_matchin...

Re: Replacing Clever Code with Unremarkable Code in Go

#118
post #117
post #115

Earlier quoted context omitted.

> Surely you mean the other way around? Yes, I had it backwards. Corrected. > Specifying whether a value is optional is less complex than the usual way of specifying whether a reference can be null — a documentation comment. Is it? I agree there's definite virtue in having this property checked by the compiler, but I think you and I will have to disagree on the notion of complexity here.

The beauty of Option types is that they are mostly used as return types. Most function arguments are non-nullable pointers or references; only ones that might be None are passed as options. This makes reasoning about code much easier. I just look at the function signature, and I know the types of arguments it expects. I also don't have to litter the beginning of each function call with if !null checks to each referen…

What I get from your comment is that option types work well in Haskell and Scala. This doesn't surprise me, as both languages places a strong emphasis on the type system, and so they are easily supported.

For option types to work well in Go you would need to add more support to the type system. But we don't want a more complex type system. That's a tradeoff we made.

Again, I'm not really sure why people keep getting bent out of shape about this. Haskell, Scala, and Rust exist for people who want to write that kind of code. I prefer to write Go code.

Re: Replacing Clever Code with Unremarkable Code in Go

#119
post #113
post #111

Earlier quoted context omitted.

Null references do make reading code more complex for the user since every function call must be prefaced with a null check. If I make a function call in every line of my code adding all the null checks would easily double my line count, burying my code in Java-like verbosity (ok not that much but you get the idea). I suppose a good IDE could help with this if option types remain unavailable. Another common complaint…

> Null references do make reading code more complex for the user since every function call must be prefaced with a null check. Well, the Go code I see doesn't look like this, so that can't be right.

So "right" Go code ignores checking references that can be null so that it can blow up at run time? That can't be safe.

Re: Replacing Clever Code with Unremarkable Code in Go

#120
post #119
post #113

Earlier quoted context omitted.

> Null references do make reading code more complex for the user since every function call must be prefaced with a null check. Well, the Go code I see doesn't look like this, so that can't be right.

So "right" Go code ignores checking references that can be null so that it can blow up at run time? That can't be safe.

No, it's just that's not how it works.

For instance,

    s, err := server.New()
    if err != nil {
      // handle error
    }
    s.Foo()
You're not going to check that s != nil before calling s.Foo, even though s is probably a *server.Server and could be nil. But it won't be, if the New function is correct. Yes, the compiler doesn't guarantee that New gives you a non-nil pointer, but it also doesn't guarantee a lot of things about the behavior of the program.
Post reply on HN