I feel happy!

Continuing from my last post, here is day 2 at Ruby Kaigi!

(The talks are being live streamed on the Internet, you can find the links at the middle of the Ruby Kaigi homepage.)

Matz’s Keynote

It's Matz!

Matsumoto-san gave a keynote address in the morning to kick off the second day of Ruby Kaigi 2014.

In the first half of the keynote, Matz did a very detailed analysis of all the keynotes he has given in previous years at Ruby Kaigi, RubyConf and elsewhere – a meta-keynote, perhaps. Matz recounted all the new ideas that he proposed at the previous keynotes vs. when they were actually implemented and shipped, if at all.

For example, Matz talked about “staby lambda” (i.e. ->{ ... }) in the RubyConf 2005 keynote and was implemented in Ruby 1.9 that shipped in 2007. (Matz recalled that the feature was initially met with some backlash when he first proposed it but turned out to be one of the most liked features when it was finally shipped.) Similarly, keyword arguments and a redesign of local variables scoping was proposed in 2004. The former made it 9 years later in Ruby 2.0, and the latter was ultimately abandoned due to backwards-compatibility concerns.

As you can see, some of these ideas took a long time to complete. Some of them never made it. So far, 7 out of the 22 ideas that were proposed still haven’t been implemented, yielding a “false rate” of ~32%.

Perhaps partly due to this, Matz took a break from announcing new feature ideas in his keynotes from 2011 to 2014. Meanwhile, the Ruby core team has focused on stabilizing the 2.x release series (and have been doing that amazingly well).

However, Matz said that “OSS community is like a shark, must move forward or we will die”. With Ruby 2.x cruising along a stable and steady trajectory, Matz thinks that it’s about time to dream big again and start thinking about the features that would ultimately lead us to Ruby 3.0. This might take 10 years again, but we must fuel ourselves with the desire to move forward because without it Ruby 3.0 will not happen.

With that said, Matz proposed some grand ideas: concurrency, a JIT compiler (and potentially adopt the LLVM infrastructure) and static typing.

Static Typing

The first two of those probably aren’t very controversial, but static typing …?!

Well, all the new kids in the street these days, like Scala, TypeScript, Dart and Go, they are all static typed language, so why not Ruby?

This was proposed by Davide D’Agostino as feature #9999 under the name “Type Annotation”. It looks like this:

def connect(r -> Stream, c -> Client) -> Fiber
  ...
end

It turns out that our long-time rival Python has a similar proposal under PEP #3107 called Function Annotations. It looks like this:

def connect(r: Stream, c: Client) -> Fiber:
  ...

As you can see, the two proposals are quite similar in their syntax (the Python syntax conflicts with keyword arguments in Ruby, so the -> form was proposed).

It is worth noting that in the Python proposal, this is purely a form of documentation – the specification does not require the implementations to enforce the types at runtime (Dart doesn’t either). There is also an optional type checker called “mypy” that uses these annotations to perform static type checking.

Why static typing?

Before going any deeper into this, perhaps it would be worthwhile to understand the problems that static typing is supposed to solve. The follow reasons are usually thrown around to support static typing:

  • Performance: the type information will allow the implementations to perform more optimization which would lead to increased performance.
  • Compile-time check: to discover bugs early on.
  • Documentation: the type information is important to the consumer of the APIs so it is better to have this explicitly conveyed rather than implied from the method/argument names and so on.

Performance

While no one would complain about a faster Ruby, Matz noted that we don’t really need static typing for good performance. For example, V8 and LuaJIT are both highly performant VMs for dynamically typed languages (JavaScript and Lua, respectively).

While it is true that techniques such as specialization can help improve performance, it is possible to achieve that to a certain degree without explicit type information, and we still haven’t explored that (and many other kind of possible optimizations) yet.

So overall, performance alone is not a good reason for introducing static typing to Ruby.

Compile-time check

Having the type information available allows for static analysis of the code and would make refactoring easier as well.

(Matz made a comment about test coverage here, but after translation I wasn’t sure if it was sarcastic or not :P)

Documentation

Matz thinks that there is a value to the self-documenting nature of the type annotation. It is much better than comments, because it will not get out of sync with the code and contradicts how the code actually works. Furthermore, when learning to use a library or when debugging some code that you didn’t write (this morning), it spares you from having to dig deep into the internals just to figure out what the method returns.

This point is the primary intention of PEP #3107 as well.

Why not static typing?

With all that said, are there any reasons to not introduce static typing? Matz gave a few things to consider:

  • It works™ without it
  • It is against duck typing
  • It will be optional
  • DRY

Duck typing

Perhaps one of the biggest drawback with static typing is that it works against duck typing. Currently, it is possible to pass a string-like object that doesn’t inherit from String. With static typing, this is not possible.

A Ruby without duck typing… is that really still Ruby?

Optional

Naturally, if such a feature is introduced, it will have to be optional to maintain backwards compatibility with existing code. However, Matz asserts that optional typing has no use as the compiler’s hands are tied as soon as you call into an untyped method. (TypeScript has the same problem.)

DRY

Rubist, especially Rails developers, like to avoid duplication. To Matz, the type information seems like a lot of duplication (between the code and the declaration, a problem that is more evident in small functions). Matz hates writing types.

Soft-typing / Type inference

Matz also mentioned a related technique that is perhaps more suitable for Ruby.

Soft-typing is a kind of best-effort type checker that works based on the code structure and duck typing, so no declaration is required.

For example, consider the follow code:

a = 1 # type of a is integer

def foo(a)
  print a.to_int
end

foo(1) # OK: 1 has to_int
food("a") # NG: "a" doesn't have to_int

As you can see, the compiler can deduce from the code structure that anything passed into foo must respond to to_int and can reject anything that doesn’t have that method.

In this case, a “type” is really a represented by classes as well as a set of methods (name + aguments type + return value type). This is going to be very difficult to do in Ruby because of dynamic requires (require some_variable), dynamicly defined methods (defined_method) and meta-programming features like method_missing.

Subset

It is possible to target this feature for just a subset of the Ruby language (for example, exclude programs that use dynamic requires). This fits nicely into Ruby’s philosophy as backwards compatibility is valued very highly by Matz and the Ruby team.

With that, we will have “two languages in one” – a soft-typed language (the “subset”) and the dynamically typed language (the “superset”). The use of the former will be highly encouraged, but it could fall back into the superset if necessary.

Conclusion

All of these things mentioned here are just ideas that might or might not happen. However, it is time to start building new things that would pave the way to Ruby 3.0.

You can read more about this in Matz interview in the next volume of the Japan Linux magazine. I highly recommend that you watch this talk when it becomes available!

Other talks

Besides Matz’s keynote, there are many other talks worth watching too. Here are some of the talks I attended today.

  • A Just in Time compiler for CRuby

    In this talk, @imasahiro showed us how he built an experimental JIT compiler called RuJIT.

    RuJIT is a Trace-based JIT compiler, similar to the approach taken by Firefox’s JS VM. It is based on the current version of CRuby, and resulted in ~2-5X speedup compared to trunk (and up to 100X in some cases).

    In his talk, @imasahiro covered the details of his design, so if this sounds interesting to you, definitely go catch it online when it becomes available.

  • Archeology of Ruby: Removed Features

    This is a short (and sweet!) talk from @znz that tells us about the history of Ruby by going through the features that were removed from the Ruby language.

    Attending this talk was like learning about a city’s history in a museum. If that’s something you enjoy doing, I think you will probably like this talk too!

  • Going the distance

    @schneems talked about how he learned to use the Levenshtein distance algorithm to solve his typo problem, which resulted in a pull request to Rails that gives helpful suggestions when you mistyped a command.

    If you always wondered what “algorithms” are about and were afraid to learn them, this talk is for you!

Wrapping Up

That about wraps up my notes for Day 2 of Ruby Kaigi 2014. Of course, there are many other talks that are equally interesting. I encourage you to check out the conference schedule for a full list of talks.

Stay tuned for part 3!

Let's Work Together

Find out why our transparent, collaborative process is the best way to make well-loved products.

Get in touch today
comments powered by Disqus