Game of Life in one Ruby statement inspired by APL
zverok.github.io
zverok.github.io
- it looks just easier in python to use c bindings
- python is used in universities, just like java is/was
I think crystal is the better of both, and would be great for this kind of stuff
Python is older than ruby, and matz probably had less ties, and probably uses more JP than guido did Dutch.
So Numeric and then SciPy (2001), numarray (2001), and Numpy (2005) just had a big head start on the other free-software numerical computation libraries, basically because a few early Pythonistas were interested in the field, and it kept accruing more and more powerful stuff: FFTW (1998), SparsePy (1999), the ability to read MATLAB files (1999), matplotlib (2001), IPython (2001), and so on. It got popular enough that dozens of people started contributing code to it, making it grow faster and faster.
At the time, most scientists were still using MATLAB; other alternatives for array-based computing included R, Bell Labs's Lush, and if you were a real masochist, PV-WAVE's IDL. Octave, the free-software MATLAB clone, wasn't yet a reasonable replacement. And all of these languages had the disadvantage that they were sort of trapped in their own little library ecosystems: if you wanted to do Gaussian quadrature or calculate a Kullback-Leibler divergence or plot some data, you were golden, but if you wanted to scrape some data out of some web pages with regular expressions, parse command-line flags, read members of a zip file, or run as a CGI process on a web server, you were shit out of luck. Numpy's syntax for a vector of numbers is pretty shitty compared to Octave or APL, but it's worlds better than R or especially IDL, and most people prefer it to Lush's Lisp syntax, although I have a soft spot for Lush myself. And Python and Numpy have reasonable language semantics too, unlike Octave or R.
(I think Lush may have been a bit late to the free-software party, too, so it wasn't really an option.)
So academia started switching over from MATLAB to Numpy, I think around 2010. The transition isn't over yet; the numerical-methods class I audited last year is still using Octave. R is dominant in statistics and will probably stay that way. But Numpy is pretty broadly adopted.
It basically came down to a head start due to a lot of hard work done in the 1990s that just happened to be done in Python. It's maybe not entirely coincidence that the people whose taste ran to reimplementing Gaussian quadrature were fans of Python and not Perl, Ruby, Lua, or Tcl, but they could have been.
It’s interesting, Ruby can be a bit more performant too. I discovered this when I taught some ML stuff to a ruby group, and converted some Q Learning programs and maze navigating stuff from Python to Ruby, and was surprised to see the Ruby version run around 1.3-1.8x faster depending on what the code was doing. It’s not enough difference to really matter, but it just reinforced my “aww shucks” feeling that Ruby could have served that ecosystem very well.
Ruby like syntax, compiled on LLVM so fast
Ruby has a great liquid hiring pool and can be used to write functional software rapidly. That’s the beauty I see, and it comes at a cost like all languages. There’s nothing especially beautiful about the way that it expresses algorithms; most languages have great aesthetic by leaning into the features and idioms designed into the language. How can a language have aesthetic in a general sense if languages have expressive tradeoff?
Regardless, i’m interested in how the syntax actually supports this. You can build monads in any language to support chaining! I’ve found the block syntax often makes this less readable if you can’t use a method identifier—ruby doesn’t have syntax for anonymous arguments that would allow expressions like `arr.map(someFunc(“arg”, @0))`, so the resulting block is more verbose and distracts. There’s also no currying.
It's sort of not one Ruby statement if it starts with
require 'apl'
and uses some APL::Ary class that, as far as I can tell, isn't in the Ruby standard library. I was hoping to see how Enumerable enabled this, not how you can implement APL in some arbitrarily large amount of Ruby code offscreen, because of course you can do that.It wouldn't be that bad to pull all the library code out into the 'main' command, but it would lose the 'single statement' impact and probably be harder for people to follow along with.
Anyway, I think it probably should lose the "single statement" impact, because in that context it's just misdirection, magician's patter. Yes, a single Ruby statement can invoke an arbitrarily complex piece of library code written for the article, but that doesn't tell you anything interesting about either Ruby or how to use it — the same is true of any programming language that supports programs in multiple modules, even assembly language:
start: CALLQ play_life
Now, the particular statement in question is considerably more illuminating than that, but presumably if you wanted to do almost anything else in an APLish style in Ruby, you'd probably have to implement more operations in apl.rb. I see that it doesn't include, for example, scan, slicing, or any broadcasting operations other than +, &, and |. (*, -, and / are missing, for example.)I mean, I've certainly written worse implementations of APLish operations. You could certainly extend apl.rb into something practically useful. I just don't think it's fair to put four pages of code in one file and then direct people's attention to the single statement in another file that invokes it.
As a Ruby programmer who already knew about APL, I thought the title exactly matched the article. I was pleasantly surprised at how clean he designed the apl library, and the nice explanations.
But there's always today's lucky ten thousand! I hope I didn't make any of them feel condescended to. Welcome to the wonderful world of implicitly parallel vector operations!
I do like the concept of keeping I/O in a more traditional language and the matrix/array code in something closer to APL.
I've written single-statement argument parsers that take up most of a page of code.
I like this because I've barely written more Ruby than APL (none of the latter) but it's perfectly legible to me.
I respect the APL family and think the notation-as-a-tool-of-thought camp has a lot going for it. I'm just illiterate in that language.
I was more surprised by the fact that the GitHub repo containing it actually has quite a few files; I was not expecting it to contain more than 2 or perhaps 3 files.
Though, I don't think there's really a problem with just doing I/O in q directly. The theoretical performance won't be as good, but since I/O is, well, I/O bound, it shouldn't really matter. And besides, I bet that even when doing non-array operations, q is faster than Python or Ruby.
Btw I love that Ruby methods return a value, so method chaining works so good. That‘s something I appreciate in Mathematica‘s postfix notation (for instance `x // Sin`), and also what I love in R‘s pipe operator, Unix‘s pipe. So many other languages like Elixir offer it. Unfortunately this does not work out-of-the box in my beloved Python.
The engineers working at those places represent a non-trivial chunk of the software engineering world, especially in San Francisco, and SWE’s (especially in San Francisco) are a major cohort of HN readers.
Additionally, the Ruby ecosystem had a major influence on many other ecosystems that spun out for various reasons. For example, Sinatra popularized the “minimal REST framework” and has been a major design influence on dozens of others, like ExpressJS and Flask. CoffeeScript, which established “transpile into JavaScript” as a thing, and profoundly influenced the shape of ES6, was heavily adopted and made prominent by the Rails team. Similarly notable projects like Ember, Elixir and Phoenix, were created by former Ruby and Rails core team members, Crystal is inspired by it, and plenty of older projects like SailsJS or Grails for groovy, etc. IIRC Rust’s cargo package management system and JS Yarn were also inspired by and contributed to by Ruby core folks. It’s influence is a lot bigger than its footprint.
So Ruby is a nice, elegant language with a lot of influence in the software world, it’s used by many readers here, and a lot of people here have “warm fuzzy feelings” about it enjoy sharing and discussing interesting news or tidbits about it.
That’s why :)
You needn't use your real name of course, but for HN to be a community, users need some identity for others to relate to. Otherwise we may as well have no usernames and no community, and that would be a different kind of forum. https://hn.algolia.com/?sort=byDate&dateRange=all&type=comme...
May be popular is not the correct word, I still remember when HN ( I didn't have an account then ) was basically an Erlang site. It was hype, and in the grand scheme of things it certainly wasn't "popular" in usage.