GADSWAD

Recently, on the Python-Dev mailing list, Guido van Rossum said the transition to Python 4 won’t be like the transition to Python 3 (“we’ve learned our lesson”).

Yukihiro Matsumoto has said similar things (without the cheap shot at Perl, naturally) recently at RubyConf 2015 and at Full Stack Fest 2015 when he talked about Ruby 3.0. In both of those talks, he gave a pretty thorough outline of the similar transitions that Perl, Python, and Ruby have gone through over the last 10 or 15 years. He talks about how Perl started over from scratch, Python made a set of backwards-compatiblity breaking changes all at once, and Ruby made backwards-compatiblity breaking changes gradually over several minor versions.

Python 3 was released nearly seven years ago, yet a majority of Python users are still on Python 2. It looks as though some might never switch. Ruby users, on the other hand, gradually transitioned from 1.9.1 to 1.9.2 to 1.9.3. They find themselves at Ruby 2 without really noticing.

Both GvR and Matz are looking at it like this

Perl 5   -> Perl 6
Python 2 -> Python 3
Ruby 1.8 -> Ruby 2

and feeling pretty good about themselves. Perl 6 isn’t even out yet, so they both did okay, right? And now they’re looking ahead at things like concurrency and performance that will be necessary for the future.

Perl 5   -> Perl 6
Python 2 -> Python 3  -> Python 4
Ruby 1.8 -> Ruby 2    -> Ruby 3

But despite its decline in popularity, I think Perl 5 has maintained feature parity with Python and Ruby. Since Perl 5.10 opened the floodgates, the updates to Perl are collectively known as Modern Perl. I use Modern Perl every day at my job and it’s fine. While Python 3 and Ruby 2 have kept up with it, more or less, they are not a quantum leap ahead by any stretch of the imagination. So I think the situation today looks more like this:

Perl 5   -> Modern Perl
Python 2 -> Python 3
Ruby 1.8 -> Ruby 2

Perl 6 is threatening to finally come out later this month and it is already prepared for the future. That is, I believe we should be comparing Perl 6 to Python 4 and Ruby 3.

Perl 5   -> Modern Perl -> Perl 6
Python 2 -> Python 3    -> Python 4
Ruby 1.8 -> Ruby 2      -> Ruby 3

Of course, there’s still the whole issue of adoption. If Perl 6 is adopted as slowly as Python 3 (or even more slowly!), then it may never matter how futuristic it is.

I think concurrency is going to matter a great deal in the near future, so my recreational programming time lately has been dedicated to things like Clojure, Elixir, Go, and Rust. I’m betting my professional programming time will go that way soon too. Sequential programming is doomed. We’re going to have to figure out concurrency or find another profession.

Advertisements
GADSWAD

Ruby’s Lonely Operator

I enjoyed Matz’s closing keynote address at RubyConf 2015! In particular, I adored his description of the lonely operator:

Lonely_operator.png

“Look at this figure…and then…you can see…someone sitting on the floor looking at a dot. On the floor. By themself. Now you don’t forget. Yeah.” – @yukihiro_matz

He’s right, I think I will never forget this. It’s ossum! I intend to download Ruby 2.3 the minute it is available and write something that uses this operator. Just because.

Ruby’s Lonely Operator

Regexes > regular expressions

I absolutely loved Hsing-Hui Hsu’s talk about parsers at RubyConf 2015 last week. It’s a terrific talk and it’s well worth your time to watch it.

But I did have one little nit to pick. What we call regexes in Ruby (and many other programming languages) are much more powerful than the original definition. In addition to regular languages, Ruby regexes can express context-free languages, and even some context-sensitive languages.

ab_language.png

For example, Ruby has no trouble with the “ab” language in the presentation:

#!/usr/bin/env ruby

%w(ab aabb aaaaabbbbb aaaaaa abb aab ababab).each do |s|
    printf "%10s - %-8s\n", s,
         /^(?<ab>a(\g<ab>)?b)$/.match(s) ? 'valid' : 'invalid'
end

Running the above gives:

$ ./ab.rb 
        ab - valid   
      aabb - valid   
aaaaabbbbb - valid   
    aaaaaa - invalid 
       abb - invalid 
       aab - invalid 
    ababab - invalid

Easy peazy! We can even use the x modifier to make a more readable regex.

#!/usr/bin/env ruby

pat = /^
       (?<ab>         # start a capture named ab
         a            # look for a literal 'a'
           (\g<ab>)?  # optionally re-execute ab recursively
         b            # followed by a literal 'b'
       )              # end of capture; this is ab
       $/x

%w(ab aabb aaaaabbbbb aaaaaa abb aab ababab).each do |s|
    printf "%10s - %-8s\n", s, pat.match(s) ? 'valid' : 'invalid'
end

This is clear as can be: we look for ‘a’ followed by ‘b’, or ‘ab’ preceded by ‘a’ and followed by ‘b’ (‘aabb’), or that preceded by ‘a’ and followed by ‘b’ (‘aaabbb’), and so on.

Regular expressions regularly (har, har) get slagged for being line noise, but it’s sometimes unfair. If you try to re-write a gnarly regex in Ruby (or your favorite language) without using regexes, you often find it’s even worse! Regexes are very powerful. And they’re pretty cool. Don’t dismiss them!

ab_language_terrible.png

Regular expressions are one of my favorite programming languages, but they’re not the best tool for everything. Like @SoManyHs says, parsers are awesome. And for many tasks, they’re more appropriate than regexes. We should use them.

Just keep in mind, regexes are more than (historical) regular expressions.

Regexes > regular expressions