
Option and null in dynamic languages - luu
https://codewords.hackerschool.com/issues/one/option-and-null-in-dynamic-languages
======
NateDad
I;m sorry there wasn't more talk of Go, I think the author might like some of
what Go has to offer.

For example, the comparison about maps at the bottom would benefit from seeing
the way Go maps work.

There's the single assignment form:

    
    
        foo := myMap[key]  
    

This returns the zero value of the value type in the map if the key doesn't
exist in the map.

and the two valued assignment:

    
    
        foo, ok := myMap[key] 
    

This returns true or false in ok based on whether the value exists, zero value
for foo if it doesn't exist.

This is actually very like an option type, but what go is missing is the
compilation-requirement that you check ok before using the value.... however,
go _does_ have the compilation requirement that the ok value gets used
_somehow_ , or it'll give you an unused variable compilation error. In
practice, this works quite well as a more flexible option type for the simple
either/or types (either there was a value or an error).

~~~
jmgao
Go is quite possibly the worst possible language for this example. You don't
have generics, so the best you can do with an option type is return an
interface {}, and any error checking you have to do has to be done manually.
The problem is not that there is no way to do it properly in other languages
(well, except lua), the problem is that the most natural way to do it is
wrong.

~~~
NateDad
Go has effectively built in option types - multiple returns... And almost
every function that can fail uses them. That's what I was trying to say. No,
you can't implement actual option types in any kind of reasonable way, but you
don't need to.

~~~
Dewie
> Go has effectively built in option types - multiple returns...

They're more like a tuple than an Option type. An Option is a sum type, and a
tuple type is a product type... and Option types are never represented as a
product type (like tuple) in languages like Haskell, ML, etc. for a good
reason.

(Aside: why does Go have multiple returns, instead of just using tuples? Or
just use structs? They could even call tuples "anonymous structs" if "tuple"
is too _academic_...)

Yes, I guess you meant that they _can be used_ like an Option type, somewhat
incidentally and indirectly.

~~~
NateDad
Go doesn't have tuples because they aren't very compatible with compile-time
type safety. You _could_ using []interface{} as a tuple, but why would you?

Go _does_ have anonymous structs, they're just only of moderate use in a
statically typed language (given that you need to specify the types for
function arguments and return types)

You can do something like this:

    
    
        // make a list of anonymous structs 
        // often useful for table driven tests
        tests := []struct{ Name string, count int }{
            {
                Name: "First test", Count: 5
            },
            {
                Name: "Second test", Count: 7
            }
        }
        
        for _, test := range tests {
            if test.Count > 5 {
                t.Errorf("%s: expected <= 5, got %d", test.Name, test.Count)
            }
        }

~~~
dragonwriter
> Go doesn't have tuples because they aren't very compatible with compile-time
> type safety.

That's...amusing. ML-family languages use tuples extensively (Haskell, because
of its preference for currying, somewhat less than others), and yet are light
years ahead of Go when it comes to compile-time type safety.

~~~
NateDad
Sorry, you're right. I was thinking of tuples without defined types for the
slots, like "this function returns a tuple of two objects", not "this function
returns a tuple of (string, int)".

------
zallarak
> If a language makes it easy to conflate nil and absence, to write code that
> does not reliably distinguish between success and failure, then bugs are
> sure to follow.

This is why after working on large apps in Ruby and Python, I strongly prefer
Python. Accessing a non-existent key in a Ruby dictionary returns nil, whereas
in Python a KeyError exception is thrown.

If you store nil in a Ruby dictionary, then you can't test for membership
unless you use hash.fetch.

~~~
Pxtl
Yup. Python is how I learned to stop worrying and love exceptions.

------
wsh91
We need more approachable introductions to types--they're all over this issue.
Good stuff.

------
finishingmove
I could swear I read the exact same article somewhere else a couple of months
ago.

Anyway, I fail to see how either raising an exception or returning None (which
the author recognizes as Python's version of null/nil) is anything at all like
an Option value (as opposed to "null-like")...

~~~
chcokr
I sense a connection, for example, between Rust's `fn foo<T>() -> Result<T,
E>` and Java's `void foo<T, E>() throws E` (this might be incorrect Java
syntax). I'm not entirely confident though.

~~~
barosl
I find Java's checked exception similar to Option type, because they are all
part of the function's type. You cannot pass alone without checking the
possible failure case.

------
dschiptsov
_Just None_ , like _Just Nothing_ is nonsense.

If you have a special marker for something, just explicitly check for it each
time.

~~~
tome
The article explains exactly why it is useful to be able to distinguish
`Nothing` from `Just Nothing`.

~~~
dschiptsov
Yeah, instead of having only "nothing" \- NIL - they prefer to have "nothing-
in-a-box", and "nothing-in-a-bag", and "nothing-in-a-suitcase". Nothing-in-a-
container-of-this-kind.

Due to such over-abstraction madness for sake of abstraction they end up with
Java or Javaesque Haskell code.

------
VeejayRampay
I guess I would have written the Ruby version as

    
    
        def values_in(keys, dict)
          dict.slice(*keys).values
        end
    

Though I suppose it's not the point of the article.

