I think one thing especially for people coming to web development from other angles in programming is getting used to the fact that you have to know so many technologies / languages to get the job done.
In the early days of web apps, you could mostly get by with Perl, SQL, HTML and a little bit of Javascript for mouseovers and whatnot. Framework? CGI.pm, baby.
Now you generally need HTML, CSS, Javascript, a Javascript framework, a backend language of choice, a framework of choice in that language, a high-performance backend language of choice for the critical bits, and SQL.
I did web apps from 1997 to 2001 and then picked back up in early 2008. It was pretty dizzying at first just knowing where to start. In the systems / multimedia world where I lived in the 7 years between it was C or C++ and a framework.
So what's the connection to the story? I think it's in the web world, perhaps as a result of its relative infancy, we apparently have to get used to the fact that the right solution to a problem is often using mixed-mode programming where individual tools are selected for individual tasks -- that development abilities in the web world is as much a question of breadth as depth. We shouldn't be so disenfranchised that our tools aren't general purpose.
I'd take this one step further to point out that web programming is a different beast from desktop programing in that you are attempting to tie a fault-tolerant, low-bandwidth channel (the internet) to a strict, high-bandwidth channel (the CPU/RAM). Add to that impedance mismatches from latency, and I think anyone who expects to have a full stack written using only one language is kidding themselves!
You don't need frameworks. You can still use CGI.pm if you want to. But doing so will make your web app look and behave like a 1998 dinosaur, and using a framework is just so much easier, more comfortable and less error-prone.
While frameworks add complexity as far as the computer is concerned, they remove complexity as far as the human developer is concerned. I can write a web app in Ruby on Rails much faster than I could ever have with mod_perl, and the result is better-looking and easier to maintain.
"Ruby is probably the most powerful programming language on the planet for creating DSLs, or domain specific languages."
If Ruby has anything over Lisp in the DSL domain (besides popularity), I'd love to know.
"A web development platform as powerful and syntactically concise as Rails could only have been done in Ruby."
Idem.
"This power does not come without a price. Ruby is slow. Ruby is generally recognized as being twice as slow as Python, and at least an order of magnitude slower than C++ or Java. Charles Nutter, one of the creators of the JRuby VM for the Ruby language, recently posted an article about optimizations that could be made to the VM, and he improves Ruby performance by as much as twenty times by removing much of Ruby’s power and breaking compatibility. If anything, it shows us skeptics that there is no such thing as a free lunch."
Lisp has all (?) the crazy features you love so much about Ruby and more, yet it's very fast (try SBCL, it compiles to native x86).
Many programmers like syntax, since coding AST-style can be tedious sometimes. Sure, you can create your own reader macro with Lisp, but that is harder than overriding some methods in Ruby. Rails is an example that opinionated software has an edge sometimes and Ruby compared to Lisp is opinionated in terms of syntax.
There are indeed some people who say "uh, nice syntax, readability, uh, big deal". Those are the folks who fail to grasp the point that programming is a human endeavor and that having your code read by other humans is a crucial element.
Lisp may indeed attract a large group of nice, intelligent people who don't get this. That is a further, fatal problem in the language.
Ruby has many problems itself but it gets that readability is important and it gets that, by extension, the humans relations that a programming language generates are important. Lispers don't seem to see the problem in an exclusive attitude and essentially closed community. The ruby community understands the need to have a good community open to people even if the Ruby community doesn't always succeed at this.
It all comes together
I don't see how the fact many programmers like syntax makes it better.
I also don't see how "coding AST-style" can be tedious, especially since it's so much easier to automate the process with macros. Granted, you'll want an editor with support for s-expressions.
This (and the rest of the article) is just ignorant cheerleading — an attempt to justify the lackings of the author's chosen technology, and thus resolve cognitive dissonance.
Lisp isn't quite as dynamic as Ruby, but Javascript certainly is, and it can be as fast as Java.
I agree that Lisp is a better choice for DSLs than Ruby. If you want a very dynamic (late bound) language that is also fantastic for DSLs, have a look at Io (http://iolanguage.com/).
I did pull that out of my ass, but Nitro and V8 perform polymorphic inline caching. Many execution paths are inlined as machine code -- java won't be any faster for these execution paths.
Sorry that sounded as snarky as it obviously did. I thought I was just drawing an analogy. Anyways...
The semantics of javascript are so different to Java (javascript functions are not like java functions everything is dynamic etc.) that you can't really expect the performance of javascript code to be comparable to Java just because it's hosted on the JVM, even if it did compile to Java byte code.
The Javascript equivalent would have to do so much more work than the Java version to support all the crazy crap you can do in javascript (ad hoc adding of properties to almost any object at any time).
Yeah, I noticed that as well... Kind of bizarre. Especially since Rhino was a pretty good educated guess; I went and took a look at it as well since I know there are some pretty performant languages running on the JVM that aren't Java.
For whatever it's worth, I think the problem Javascript is going to have with speed is that it is so dynamic that it makes it difficult for compilers to optimize. If it ever got type hints it would probably be much easier to make fast.
This power does not come without a price. Ruby is slow. Ruby is generally recognized as being twice as slow as Python, and at least an order of magnitude slower than C++ or Java.
The last two statements don't mean the first is true. Ruby's power is not the reason it's slow. Smalltalk VMs are proof by existence that the Ruby model can be fast. (See: Self, Strongtalk, Gemstone.) MagLev showed that Ruby is basically just an alternative Smalltalk syntax.
Charles Nutter, one of the creators of the JRuby VM for the Ruby language, recently posted an article about optimizations that could be made to the VM, and he improves Ruby performance by as much as twenty times by removing much of Ruby’s power and breaking compatibility.
"Remove much of Ruby's power"? Around 0.2% of Charles's speed-up came from removing the ability to override the primitive math operations. Other than that, his speedups removed none of Ruby's power.
(And nit-picking: Ruby is probably the most powerful programming language on the planet for creating DSLs, or domain specific languages. It can do this because any class or object can be extended, any method overridden, any constant undefined and redefined, and so on, and so forth.
This power does not come without a price. Ruby is slow.
ARRRRGH! Why do the expectations of guys from the 80s and early 90s still rule us? There are Lisp and Smalltalk VMs out there that are something like 70X as fast as Ruby 1.8! If you add Traits (library for Mixins) to Smalltalk, it is equivalent to Ruby in power. (1)
The one of the biggest misconceptions we have to face in the Computer programming and related professions, is that programmers are on the forefront of technology. Actually, culture lags technology. And in that, I specifically include the culture of computer programmers.
The foundations of OO languages like Ruby and Python were set forth in the 70s and 80s. WYSYWIG word processing, ethernet LANs, desktop publishing existed then in pretty much their current forms at Xerox PARC, only slower. The concepts embodied in Dot-NET and Microsoft's Singularity were bandied about in the 60s, 70s, and 80s.
The sad thing about our profession is, is that to learn what's coming next, and what's possible you still have to do some digging into history. Things have improved, but because programming is also a cultural artifact, it lags technology like any other cultural artifact.
I keep posting this. I used to wonder why it seemed like tilting at windmills. After writing this post, I now realize why.
Alan Kay: "The Computer Revolution Hasn't Happened Yet."
(1) - In fact, it is homomorphically equivalent. This is precisely why something like Maglev can work. Another interesting thing -- many Lisps are also homomorphically equivalent to at least 90% of the languages out there. And one could probably take just about any Lisp and give it the power of the other 10% (like Erlang) with moderate effort.
There are NOT SmallTalk libraries out there that are 70x faster than Ruby - that would be faster than raw C (Ruby is about 30x slower). Are you trying to say that SmallTalk is faster on average than raw C? So why isn't everything written in SmallTalk?
And I'll believe Maglev's outlandish performance claims if and when I ever see them realised. If they are anything like those claimed at RailsConf 2008 (50x or thereabouts), I'll eat my hat and any other hats anyone cares to send me.
I say this as someone who would probably seriously consider murder if it would make my Rails apps run 10x faster. I want it to be true. I just don't think it is, unfortunately.
And one could probably take just about any Lisp and give it the power of the other 10% (like Erlang) with moderate effort.
I keep hearing things like this, but no-one ever does it.
That's strange, I never said anything about the speed of Smalltalk libraries.
And actually, I know that some Smalltalk routines have run faster than the same routine implemented in C. By 3% actually. This was over 5 years ago, and it was a block cipher -- yes, low-level bit slinging. The DLL was the RSA reference implementation. (1)
Also, you should be careful about reasoning about benchmarks as if they applied the same across the board. Anyone who knows a little about them knows that they are very contextual.
BTW, in the Smalltalk community, spelling the language name with a capital T is considered a mark of the PHB.
But if you want a Smalltalk library that's much faster than Ruby 1.8, there are a variety of benchmarks around. Just take some of that code, and declare it to be a library. QED.
(1) - This is the magic of generational GC. if you know what you're doing, this is like getting a Buffer Cache you didn't even have to implement. Also, the implementor got the help of the VM engineer, who provided primitives for handling 32 and 64 bit arrays.
Oops, sorry for the faux pas - I thought that it had a capital T - and no idea why I wrote libraries either. I meant VM, or even better, implementation. Sorry, I was tired, and now I've wasted your time defending against something I didn't even mean to say. I was also trying to agree with you about the unreliability of specific benchmarks.
I'll try to restate. You said this:
"There are Lisp and Smalltalk VMs out there that are something like 70X as fast as Ruby 1.8!"
That is what I was trying to argue with. I have never seen any proof, beyond a few cherry-picked examples of Ruby at its worst and Smalltalk at its (presumable) best, where anything like a 70x speed difference is observable. On average, ST (is that ok?) seems to be a mere 5x as fast (or so), coming in at somewhere between 5 and 10 times slower than C.
Ruby 1.8 is in the average case around 30x slower than C. So if Smalltalk can be 70x faster than that, then it is generally twice as fast as C, on average, in everyday use. This is not the case, as far as I am aware. I see this "Smalltalk is SO fast" meme again and again but it just doesn't seem to be grounded in reality.
Sorry for my idiotic error earlier, and for sounding like a PHB ..
True, 70X as fast as in benchmarks doesn't mean that much in the real world, because in real world apps, you are bound by memory use, network, DB backends, disk access, etc.
The real gain for Ruby, once there are reliable VMs that have good JIT capabilities is the following:
A dynamic web page can then be compiled into a JIT-ed method, with static HTML as data in arrays interspersed function/procedure calls. At this point, you can increase the JIT memory cache so that it can contain your entire web site, and at that point your web pages are machine language routines!
VisualWorks has a framework that does this. It's called Smalltalk Server Pages.
Look, no. I am not talking about "real world" bottlenecks like disks, databases, etc. I am talking about ideal mainstream applications written in community-accepted idiomatic code, no external bottlenecks. Smalltalk will still not be 70x faster, no way, no how.
If it was, it would be faster - much faster - than C, and if that was the case, games, graphics drivers, hell, operating systems - would be using Smalltalk. They are not. QED.
Smalltalk is great and its VMs are highly advanced. I accept that. I still use Ruby and eat the performance cost because I prefer its syntax and "world". But man, let's keep the performance comparisons grounded in reality. 70x faster is ludicrous.
So long we we're saying, "Look, no I am not talking about..."
My point is that VMs that have been around for decades capable of supporting languages of equivalent power, and that these are some silly multiplier faster than Ruby 1.8. This is going to be something like halfway to two orders of magnitude for some silly benchmarks, and much less in real life. Really, there's not much of a problem in practice, especially with the embarrassing wealth we have lying around in terms of processing power.
The real problem -- the thing I am making a point about -- is people going around saying that, "Oh well, you have to give something up to get the power..."
No. You. Do. Not!
Ruby is not that advanced. Yes, I would say that it's a lovely language. It has everything I want, but it's not doing anything that hasn't been done before. It's unique in that it combines lots of elements in a way that's really dandy, but there's nothing magic about it. There's certainly nothing so esoteric, that it couldn't be made to run fast. (There are a few things that were just bad design decisions, like making every Object behave like a little hashtable, which could've been left out and made it much easier to run faster without losing power and expressiveness.)
Oh, and people did implement OSes in Smalltalk and Lisp way back when. Also, ever hear about something called Singularity? That's a recent OS built on top of a VM. In fact, I think that more people should be doing just that -- building OSes that are "turtles all the way down" and built to not only support a particular VM, but to have every single atom of it available to tweaking by a high-level language. (Lua would be great for this.) But this is a digression.
Again, going back to my original point -- the real ludicrous thing is that the programmer community as a whole is still in the thrall of expectations about speed vs. programming language power that date from the 70s. And anyone who thinks you have to give up as much speed as Ruby has to get that power is very much in the thrall of such an idea.
ever heard of Lisp Flavored Erlang? Ever heard of the Common Lisp Object System (inspired originally by Smalltalk)? Ever heard of Clojure (Haskell inspired STM, and lazy data structures)? ever heard of GOAL (Lisp assembly)? etc., etc. etc., etc., etc.
Like above I didn't make myself clear at all. Let me try again, by your leave.
I wasn't claiming you can't tack feature X onto lisp, of course you can, you can implement anything in anything. The point I wanted to make was that "power" is not just some object feature bullet points, it's about ease of use and syntax and libraries as well.
"If you add Traits (library for Mixins) to Smalltalk, it is equivalent to Ruby in power. (1)"
Only for your definition of "power".
Yes, everyone loves Ruby's super-flexible objects and mixins etc but that is only the start of the story. Its syntax is terse, intuitive and good-looking. The rubygems packaging system is effective and ubiquitous. Irb is excellent and "live coding" techniques are invaluable. To me, these are very much part of the real "power" and the main reason I prefer it over, say, Python. You might be able to emulate the object behaviour but it's still "incomprehensible mess of brackets" Lisp.
You might be able to claim that Lisp is 90% "homomorphically equivalent", a phrase I don't think I've heard since Mathematics 2, but who gives a shit? Go ahead and add the last 10% of whatever it is that Ruby has and Lisp doesn't. Now you have just as much power as Ruby? So go ahead and type "require activerecord" (don't forget to compile!) and just try to tap into that power. Oops.
"Language power" is not just some reductive theoretical idea of what features a language has, or could implement. It's the whole package, and how you use it. Sure you can add Ruby's features to C. But a better way is to implement Ruby in it.
Lisp might well be the infinitely flexible meta-language which can be used to describe all others, but that isn't actually useful in itself, as used today. Lisp may be an incredibly powerful tool for something, but it has little advantage for conventional end-user code, not any more anyway. It's pretty exciting to think where it might end up, though.
"And one could probably take just about any Lisp and give it the power of the other 10% (like Erlang) with moderate effort."
Again, only for your definition of "power", which is not what the average programmer who is just interested in getting stuff done is thinking about.
You might be able to claim that Lisp is 90% "homomorphically equivalent", a phrase I don't think I've heard since Mathematics 2, but who gives a shit?
Well, for those who actually have a little intellectual curiosity, the implications are:
1) Not only can you do anything in langauges X and Y
that you do in Ruby, you can express it about as
concisely
2) Any libraries in Ruby could be just as beautifully
expressed in languages X and Y
3) There's no reason something that closely resembles
Ruby but runs *a lot faster* shouldn't exist
4) Speed is just one factor among many. There are lots
of other things Ruby could learn from.
Sho, there are some who have enormous cognitive dissonance at the thought that their pet language is not the ultimate in the universe. Then there are others that are actually curious about what else is out there, and how the languages they know the most about fit into that continuum. Therein is some valuable and useful information for those who are forward looking.
(For the others, Ruby is awesome, it is the ultimate, there shall be nothing better, yada yada. Now you can rest easy.)
There has been a bajillion hours of awesome work that's gone into Ruby and Rails. There are ways that Ruby and Rails can be changed such that the next bajillion can be several times more awesome. All I'm saying is -- look around and be curious. There's a lot out there to learn!
In Ruby can you connect to the running web application and debug it on the fly via a REPL? You can do this with Common Lisp and Clojure (PLT Scheme?). It definitely helps with "getting stuff done."
I'm not sure, but I think your counterexample is meant to show you can't replace `Array#pop`. However, that's not what you show -- you show that irb depends on `Array#pop` for its normal usage.
is really outstanding. It shows you exactly why a language like Ruby is inherently slower than a language like Java. Mainly, because Ruby does a lot more work to give you the cool, dynamic capabilities that make people like Ruby in the first place. Of course, much of the cool work on speeding up dynamic languages like Javascript and Ruby is all about analyzing code to find places where you can safely make assumptions about the code (+ is not overridden here, so I can use the built in integer addition operator, etc.).
(I probably oversimplified that, but I hope it captures the general idea.)
The "Duby" language at the end makes me think of Common Lisp and how you can optionally declare types the compiler can use to compile faster code. Would it be worthwhile to add optional typing to Ruby?
It varies naturally per application. When I was doing a little prototyping before deciding to write the core of our ranking algorithm in C++ I took the tightest inner loop and compared C++, Java, Python, Ruby and Perl. For floating point numerics and lots of list traversal the results were:
As a result, we're using C++ where it really matters, Java where it kind of matters and Ruby where it doesn't. This was more than a year ago though, so any performance gains since then naturally aren't included.
To take the article in the right light, consider that in Ruby-land, syntax is important, it matters. For example, optional parentheses. Spaces are mostly disregarded unless they aren't in a few cases. Switches that support almost any type, even though when folks play with entire Hashes as keys things can fail to work even more during the 1.8 to 1.9 transition...
Multiple ways to create literal strings so you can save escaping things inside of them or save some other action.
Closures with one block shortcut per method so you can save a little more characters there.
These things encourage the developer to revisit their implementations and cut the redundancies much more.
The p method coupled with the inspect feature that gives you the description of a certain object so you can debug it or at least see its content very easily.
No use comparing Ruby to LISP and Smalltalk in some "power subjectivity"... Ruby is hackish and used by "hackers" alike. It's not perfect of course...
And I liked this article for it put into better words what I wrote in some comments on the original article.
Yes, Ruby is OK - buuut: I would like a language that is good for everything. I don't really understand the argument that "Ruby was only replaced for stuff it wasn't appropriate for". Some languages are good for everything, so why make the effort to learn languages that can not do everything? Yes, there is the DSL stuff, but atm I am not sure if I really care so much for it.
For example, yesterday I caused an infinite loop in my Rails controller because I forgot the "@" in front of a variable that had the same name as the action - so Ruby interpreted it as a method call, not a variable reference. Being able to call methods without "()" is part of the Ruby-DSL stuff, but I wonder if typing "()" would not actually be the lesser pain in the end. I probably lose much more time to hunting such bugs than I lose time typing ().
The "()" thing is something that personally clicks with me in python. I absolutely love methodname as reference always, methodname() as function call always. I'm fetishistic about predictability though.
To your main point, all general purpose languages are good enough at everything. That's how they get to be called "general purpose". But, I would argue that there are 0 languages that are great for everything. There is no language that can be shown to have 0 tradoffs when compared to all other languages.
The thing that often gets over-looked with Ruby is the trade off that many other languages make of developer time and enthusiasm (happiness, comfort, engagement, morale, etc). If you don't believe those factors exist or that they have little value then the trade off the language makes to afford those features is lost in translation.
To make a crude analogy: if I were hiring to get a company off the ground I would love to find a single person to do all of the product concepts, design, implementation, sales, accounting, legal work and support. The problem is that the jack of all trades is master of none and you're likely to get some creative concepting all over your accounting. Languages specialize in thousands of ways over the growth of the language (and hopefully consciously) - much like people do with education and career development. Even at times under the guise of general purposeness.
This is all to say that unfortunately your wanting a language that is great for everything is impossible. But, you might find a language that is good enough at all of the trade-offs you care about without ever trading off all the other things you care about and for all projects for all time.
It may be true that there is no language to rule them all, or it might not be true. Just because people typically are not good designers, good coders and good admins in one person does not prove that programming languages can't be good at everything (they are all Turing complete, after all).
Of course there are always tradeoffs, but some tradeoffs might not matter (that is, there might be no situations in which the tradeoffs would matter.)
I am not yet convinced that Ruby is so much more pleasant than other languages. I don't know Scala yet, but what if Scala is actually pleasant to use? Then Scala might be better than Ruby in every respect. (Not saying it is, I don't know Scala).
Good point. There could be a language that made 0 trade-offs "that matter" vs all other languages. The problem remains that there will likely still exist at least one person for whom some trade-off of little or no substance is important (even essential).
When people talk about power, elegance and abstraction of a language (not compiler, VM, libraries, etc) they are talking about the language platformed on the human brain (something unique to the individual). Ruby targets a certain brain platform while C targets a different one and Scala yet another. Twitter engineers sound like they have brains appropriate for both Ruby and Scala. Scala makes less technical trade-offs toward their end and so there arises a clear winner (for them).
The day we're all using the same brain platform then there could be argued to exist a best language.
A situation like the OP's would run in an infinite loop even in Scala. There's no compile-time error in Scala when you have a method call itself, which is what the OP is describing, and his variable also wasn't named the same as the method: "@name" vs "name".
The syntactic ambiguity between method calls and variable references is intentional. It's not about saving 2 characters. It allows you to swap one for the other without editing the rest of the code.
I would say though that Ruby is a bit more complex of a language that people advertise. A novice will be bitten by these things, but someone who's worked with it full time for a couple weeks will not.
A language that excels at everything is an incoherent concept. There certainly are languages that are adequate at most things however.
I forgot the "@" in front of a variable that had the same name as the action - so Ruby interpreted it as a method call, not a variable reference.
It sounds like ruby did exactly what it should have done. There was a typo and you ended up calling a method. Even if ruby required parens for methods, you could have a typo missing the parens which would make it a local variable reference.
I would guess that a more common confusion with naked ruby methods is that they can be indistinguishable from local variables, and this isn't helped when people completely omit parens when passing params. This is why, despite some critisim of the practice, I pretty consistently use self and, when passing params, use parens.
The typo mistake and the "forget parens" mistake are quite different in quality, though. If I mean method call, it is very unlikely that I would forget the parens in a language that always has parens for method calls.
"If I mean method call, it is very unlikely that I would forget the parens in a language that always has parens for method calls."
If I mean instance variable, it is very unlikely that I would forget the @ in a language that always has an @ for instance variables. :-\
Maybe I'm missing something, but I don't see a fundamental distinction between the two purely on the basis of consistency. I think an argument could be made that the parens on a method are a more meaningful and representative syntax element than an @ on an instance variable, making it easier to remember. Then again, someone could argue that braces are a more meaningful syntax element than indentation, and we all know how that goes. :-)
> I would like a language that is good for everything.
And how about a pony while you are at it?;-) No language does everything, what you want to aim for is one that does as broad a range of things as possible:
I think Ruby is 'pretty good' in those terms. Better than Java, IMO, because it lets me do small/quick things easily, something I've always found unpleasant in Java.
I really liked this article, and remember reading the original article and thinking that it does a good job of explaining an engineering approach that invariably needs the ability to skillfully use many technologies.
Just to make sure you are measuring the right thing:
You made your measurements after passing a few hundred thousand messages through the system to give the JIT in the JVM enough information to act upon? And using a server VM?
With which GC?
I put tens of thousands of messages through it before noticing it was slow. And yes, using a server vm (sun's latest)...
I haven't given up on it... just posted the above comment b/c I had assumed that Kestrel would just be way faster b/c it's java, which turned out to be quite an erroneous assumption.
In the early days of web apps, you could mostly get by with Perl, SQL, HTML and a little bit of Javascript for mouseovers and whatnot. Framework? CGI.pm, baby.
Now you generally need HTML, CSS, Javascript, a Javascript framework, a backend language of choice, a framework of choice in that language, a high-performance backend language of choice for the critical bits, and SQL.
I did web apps from 1997 to 2001 and then picked back up in early 2008. It was pretty dizzying at first just knowing where to start. In the systems / multimedia world where I lived in the 7 years between it was C or C++ and a framework.
So what's the connection to the story? I think it's in the web world, perhaps as a result of its relative infancy, we apparently have to get used to the fact that the right solution to a problem is often using mixed-mode programming where individual tools are selected for individual tasks -- that development abilities in the web world is as much a question of breadth as depth. We shouldn't be so disenfranchised that our tools aren't general purpose.