Skip to content
  • Yorick Peterse's avatar
    Remove hash map literals · 94ac7d14
    Yorick Peterse authored
    In order to simplify the syntax, hash map literals have been removed.
    Instead, one now creates a hash map using `Map.new`. To make it easier
    to create a map with a bunch of pairs in one expression, we introduce
    the `Map.set` method. This method behaves similar to `Map.[]=`, but
    returns the Map itself instead of the value written:
    
        Map
          .new
          .set('foo', 'bar')
          .set('baz', 'quix')
    
    So why were map literals removed? Well, first of all their syntax was
    not intuitive: `%[key: value]`. This syntax was taken from Elixir, but
    is not used in other languages that we are aware of. Many languages use
    curly braces (e.g. `{key => value}`), but these are already used for
    closures. Some languages reuse square brackets (e.g. `[key: value]`),
    but this makes the meaning of `[]` unclear. We considered using a syntax
    similar to Scala:
    
        Map.new(key -> value)
    
    Here `->` would be a method that returns some sort of tuple, and
    `Map.new` would take this list of tuples and use them to fill the map.
    The method `->` would have to be available for every object, since
    it's perfectly valid to use outside of constructing maps. This means
    `->` would have to be defined on `Object`, or in a trait that is
    implemented for it. Manually implementing the method/trait would be too
    cumbersome. The hypothetical code for this might look as follows:
    
        impl Object {
          def ->!(V)(other: V) -> Tuple!(Self, V) {
            Tuple.new(self, other)
          }
        }
    
    Unfortunately, the Ruby compiler does not support the use of self types
    in generic types well enough to make this work. This is a long standing
    issue [1], but it would require an extensive rewrite of the type system
    to support. Since we want to rewrite the Ruby compiler in Inko, adding
    support for this in the Ruby compiler would be a waste of time.
    
    There are a variety of other approaches, such as passing a closure to
    `Map.new` that can be used to fill up the map. All of these suffer from
    similar problems: the Ruby compiler's type system is a bit buggy.
    
    To work around all of this, we added the `Map.set` method. While the
    resulting code is a bit more verbose, it does not require any compiler
    changes. The API should also feel familiar to those used to immutable
    programming languages, which typically use a similar approach for
    constructing hash maps.
    
    The removal of map literals also allows us to remove various compiler
    optimisations of these literals, simplifying the compiler and making the
    language more predictable.
    
    [1]: #107
    94ac7d14