2009-11-17

Unix in 14 lines of Ruby (it's trivial)



Anyone under 17 knows that Ruby is so extremely dynamic, that Google's complete Map.Reduce framework can be implemented in one line of code:
data.map.reduce
(Note the expressive and elegant object-orientedness that lies at the core of Ruby's efficient syntax...)

But now R is giving Ruby a run for it's money: Map/Reduce has been ported to R with just one line of code, too!

So clearly, we need to raise the bar here: I will show you how to implement Unix in a couple of lines of Ruby.

Yes, you heard that right. Ruby is so elegant and dynamic, that Unix takes just a couple of lines of code. Take that, C.

Other languages, like LISP, have lambdas and closures, but Ruby not only has these, but also continuations, blocks, procs, scopes, dos, and bacon! Mmmmh, bacon. (And btw, Ruby can implement Common LISP in a couple of lines.)

(There are a lot of articles that explain the differences between these, but as of Ruby 2.1.003m the schemantics of most of these have changed slightly, so the articles are out of date. As a rule of thumb: a continuation is a block that has been captured inside a scope where a do is in effect, and cannot be passed to a proc, only to a lambda. It's really quite simple. Matz has recently proposed a ten-year moratorium on Ruby development, so that we'll finally be able to understand all these.)

So here it is!



A sample run of this Unix for you're pleasure:
You have no mail.
$ uname
Runix 1.0
$ halt
All it takes to implement Unix in Ruby is 14 lines of elegant code.

It doesn't do processes yet, and it has no filesystem, but apart from that, it's a fairly complete Unix.

Ruby is a butterfly.

6 comments:

nassrat said...

R u trying to be funny? I usually find comments with that level of intellect comical, but this is just too sad.

Petri said...

R is clearly more expressive than Ruby. To provide a specific example I have written Unix in a single line of R:

print("You have no mail");r<-T;while(r){c<-scan(n=1,what="character",quiet=T);if(c=="uname"){print("RUnix 1.1")}else if(c=="halt"){r<-F}else{print("Command not found.")}}

Alcides Fonseca said...

Petri, you can write any program in one line of almost any language, but using the delimiters like ";". But whitespace in important in code readability, something people actually do a lot.

Here is my version in Scala with two less lines: http://wiki.alcidesfonseca.com/blog/unix-scala/

CJ said...

Or, better:

while gets do
'$ '.display
$_.each do |e|
... etcetera...
end
end

For max awesome/laziness , just do:

while gets { system($_) }

vroemer said...

I can top that in C


---
int main(int argc, char **argv) {
while(gets(argv[0])) {
if( !strcmp(argv[0], "uname"))
printf("fake *nix .001\n");
if( !strcmp(argv[0], "halt"))
exit(0);
else
printf("cmd not found\n");
}
return;
}


---

make of this what you will however, it is legit. :)

Prof3ta said...

Unix in Erlang, then:

-module(unix).
-export([go/0]).
loop() -> loop(io:get_line("$ ")).
loop("uname\n") -> io:format("EUnix 0.1~n", []), loop();
loop("halt\n") -> ok;
loop(_) -> io:format("command not found.~n", []), loop().
go() -> io:format("You have no mail.~n", []), loop().