Hacker News new | ask | show | jobs
by maerF0x0 3234 days ago
IMO the language made a mistake by allowing nil to satisfy any interface . When I write a function like

   func DoStuf(i ILoveGoer) { 
     i.LoveGo() // Panic on nil
   }
its hard to reason about because it doesnt look like you have a pointer, looks like you definitely have a value. IMO a nil should not be allowed for an interface. So the only way to create an interface var is in conjunction with assignment.
3 comments

Nil interfaces don't necessarily panic when their methods are called, just when nil variables are dereferenced. This is because the receiver is just another argument. For example, if `i` were this implementation of LoveGoer it wouldn't panic on a nil receiver:

    type JoeLovesGo struct{}

    func (jlg *JoeLovesGo) LoveGo() {
        fmt.Printf("Joe Loves Go! jlg is %v\n", jlg)
    }
( Playground: https://play.golang.org/p/kanq_mSmaI )

Now, if this (admittedly uncommon) use-case is worth it's downsides is a different question, but that's how it's set up now.

this is called a bottom type in a type system. In JVM languages null and the throw expression return the bottom type.

The only other option is to not have nil values.

Or to encapsulate a nil in a Maybe monad, so that you only have to deal with it in contexts where you explicity denote acceptance of nils. Then the type system won't let you get away with ignoring the possibility of a nil.
you can do a maybe monad without nil types by substituting nil with a single-valued singleton type
> The only other option is to not have nil values.

Rust has a bottom type (!)[0] without it implementing all traits by default while using a different type (Result) for error propagation. Plus having nil/null as a a value of the bottom type violates some aspects of bottomness.

[0] https://github.com/rust-lang/rfcs/blob/master/text/1216-bang...

The problem is "null" being a value in all (non primitive) types, not only the bottom type. You specify "String", but you can have "null" too. When everything is optional, how do you specify that function foo really takes a String, not null? (https://stackoverflow.com/questions/4963300/which-notnull-ja...)
> The problem is "null" being a value in all (non primitive) types, not only the bottom type.

Null is not a value of bottom type. Bottom type has no values.

Thanks, you are right, the bottom type has no value. I meant the "Null" type, which contains a single value, "null".
what about `error`?
Emulating the sum type val|err with a product type (val, err) - where val and err are implicitly nilable - is one of Go's biggest design smells in the first place.
Allow an Either monad via allowing sum types, solved.

Once you have an either type, you can also get rid of nil entirely since a Maybe type is trivially created with an Either.

Designing languages without a null value (other than for c-interop via e.g. `C.null`) is a solved problem.

I see no reason that a good proposal and example implementation wouldn't be accepted for addition to go. The Either/Maybe monad is so powerful and is incredibly straight forward to use. So the argument from a language user perspective is already won, it's makes the intention of code much clearer and gives the type checker massive help in verifying that your intention is the only possibility at runtime.

I expect the implementation and grammar/syntax addition would be the most difficult as that seems to be what one of the main focuses was during Go's infancy, make the language as easy as possible to parse/lex.

> I see no reason that a good proposal and example implementation wouldn't be accepted for addition to go.

I'm sorry to bring the age-old "but generics" thing up, but how do you even implement (what Haskell-alikes call) Functor without parametric polymorphism?

The only ways I see are

a) Elm-style List.map/Array.map/Maybe.map

b) Rust-style Functor/Monad operations on specific types like Result

Which of these do you think Go would be more receptive to?

How do you handle IO errors? They almost certainly have to be a open sum type.
You can fix that with exceptions :)
:'(