Hello, Crystal

Here’s an anagram-finding program in Ruby:

table = Hash.new { |h,k|
  h[k] = []
}
IO.foreach("/usr/share/dict/words") do |line|
  word = line.chomp
  key  = word.downcase.chars.sort.join
  table[key] << word
end

word     = ARGV[0].downcase
anagrams = table[word.chars.sort.join]
anagrams.map!(&:downcase)
anagrams.delete(word)
if anagrams.any?
  puts "Anagrams for '#{word}': #{anagrams.join(", ")}"
else
  puts "Sorry, no anagrams for '#{word}'"
end

Here's the same program, but in Crystal:

table = Hash(String,Array(String)).new { |h,k|
  h[k] = [] of String
}
File.each_line("/usr/share/dict/words") do |line|
  word = line.chomp
  key  = word.downcase.chars.sort.join
  table[key] << word
end

word     = ARGV[0].downcase
anagrams = table[word.chars.sort.join]
anagrams.map!(&.downcase)
anagrams.delete(word)
if anagrams.any?
  puts "Anagrams for '#{word}': #{anagrams.join(", ")}"
else
  puts "Sorry, no anagrams for '#{word}'"
end

See if you can spot the differences (there are exactly four).

Here are some benchmarks:

$ time ruby anagrams.rb avdi
Anagrams for 'avdi': avid, diva

real    0m0.621s
user    0m0.597s
sys     0m0.020s
$ crystal build --release anagrams.cr
$ time ./anagrams avdi
Anagrams for 'avdi': avid, diva

real    0m0.230s
user    0m0.305s
sys     0m0.017s

8 comments

  1. The phenomenon of a language designed to look like another language but has substantial semantic differences is interesting. Perhaps the most astounding, historically, is that of C++ copying from C, and Java copying from C++, and JavaScript copying from Java, with the result that there is some kind of umbrella concept of “curly brace language” despite the vast semantic differences among these (except for the special relationship between C and C++). But why is there not as much attention spent toward providing alternative syntax for the same language? A lot of people seem to choose a language based entirely on syntax (sort of like only working with people who have a particular style of clothing and hair). What if it were easier to choose your own syntax in your editor/IDE? Elixir is in a way attempting this experiment with Erlang. I once programmed Dylan in S-expression syntax before they switched to infix syntax. McCarthy was originally going to give Lisp an infix syntax. How much of the character of a language is actually in the syntax? I know people who hate Haskell syntax but would be happy to code in Haskell if they could use a Lisp syntax instead, and I know people who go the other way! Clothing and hair do matter. They are suggestive of something. This needs to be explored more in computing, because programmers are human.

  2. While the stated goal for crystal is to look like ruby, I think that goal goes far beyond the character by character syntax. It also includes how classes are defined, methods are called, closures behave, and also what the base classes look like (names and methods).
    The fact that crystal appears to be 10-100x faster is interesting. I’ll be far more interested in seeing how threading behaves.

    1. Yes, a program that’s less than 20 lines and mostly calls into C is not much faster. But the benchmarks on the Crystal site seem to indicate 10-100x speed – which is a little more compelling.

      But – as I said – I’m more interested in threaded performance than raw speed.

    1. Even if jruby+truffle is super fast, there’s the issue that it lacks static type checks. These not only aid in getting a better performance, but in giving confidence when refactoring code and not having “undefined method” exceptions at runtime.

Leave a Reply

Your email address will not be published. Required fields are marked *