Hacker News new | past | comments | ask | show | jobs | submit login
So You Want To Optimize Ruby (headius.com)
126 points by jamesbritt on Oct 15, 2012 | hide | past | favorite | 39 comments



Couldn't we get rid of some "features" that have little practical use and create problems for implementers and make optimisation harder?

For example `$~` and `$_` variables. Yes, they are lazily loaded but they force the VM implementers to jump through so many hops in order to keep track of them.

> In the case of $~ and $_, the challenge is not in representing accesses of them directly but in handling implicit reads and writes of them that cross call boundaries. For example, calling [] on a String and passing a Regexp will cause the caller's frame-local $~ (and related values) to be updated to the MatchData for the pattern match that happens inside [].


Indeed we could, and as a reply mentions some implementations do take liberties with various Ruby features like $~ and $_ (in MacRuby they are thread-local, which sorta works but is often broken behavior).

Part of my challenge as a Ruby implementer is to figure out which features really must be implemented to the letter of the law and which ones can be fudged without impacting anyone. ObjectSpace was an example that could be fudged; it turned out nobody ever used it for anything other than iterating over all classes in the system. I also often make my case to the MRI/ruby-core folks and Matz himself as to features that are an unreasonable performance hit for not enough benefit. Sometimes I win those arguments, sometimes I lose them.


I agree. I would also propose that some esoteric features are separated out into gems. For example, String encoding could be simplified to support only UTF-8, with a gem for the few people who need something else. The Date/Time class also is a monster that supports calendar changes from the 16th century, accurate to the nanosecond.

In general, a standard library that offers a 95% of what most people need, instead of 99%, seems like a good way to go.


I might be wrong here, but I'm pretty sure MacRuby takes the sort of shortcuts you're thinking of.


Warning! I made this comment because I thought this was an amazing and informative blog post, but nobody said anything in the last 7 hours it's been posted... :\

As a result, I've decided to toss out some thoughts I've had about Ruby, programming languages, PL implementations, and Lisp lately.

This is a fairly interesting, dense, but accessible list of aspects of Ruby that make it hard to optimize.

An interesting counter-example in terms of relative expressive power vs. performance would be Common Lisp.

The main differentiator seems to be how accessible the expressive power is. Ruby just really doesn't demand much forethought or precision on the part of programmer in terms of what should be in scope, what data is getting passed around, how to even represent the data, let alone in memory.

That's saying a lot, given that the default data structure in 'classical' lisp is a linked-list, which is a pathologically poor choice for today's hardware for cache predictability. Thus why Clojure has emphasizes the generic sequencing protocols/API and tries to nudge people towards using vectors for everything.

This all adds up to a language that is "easy" and expressive, but not simple.

It leaves one to wonder why we haven't gotten much further in terms of raw expression and concision at a high and low level than Python, Ruby, and Common Lisp. There are others that deserve mention for being interesting and powerful (Haskell, Clojure, Io) but for various reasons/limitations/trade-offs aren't necessarily more concise/more powerful in the small (trivial example) or in the large (managing state, scope, composing code from afar).

Clojure and Haskell pick some smarter defaults for the scale-up to larger codebases, but don't do much to offset the loss in expressive power those trade-offs incur. I think the emphatic focus on immutability and keeping as much immutable as possible as is the case with Haskell and Clojure is the way forward, but only Haskell has really made any attempt to explore how to advance the power of expression in that mode.

Idiomatic Clojure code barely makes use of monads as it is.

To understand the scorn that Common Lispers have (I used to code primarily in CL) for Clojure, Haskell et al, it's important to remember that they principally care about what's possible, not about what's idiomatic, standard to the community/libraries, etc.

It has long been the case that you could write predominantly functional, immutable, expression-based code in Common Lisp. Many did. What Clojure did was formalize it, clean it up, etc.

Clojure didn't bring anything new to the table in terms of power. Not like Haskell's type system. I spoke to David Nolen recently about predicate dispatch and it seems as if progress on that front has even stalled.

The delay in progress on predicate dispatch is disappointing because I was going to use the predicate dispatch work as the "selling point" for Clojure for a few CL'ers I know. It would've been a genuinely distinguishing point as while there has been tons of work on predicate dispatch in Common Lisp, Clojure's core.logic foundation was shaping up to have a better API and be more composable.

Instead I'm left with nothing I'm able to recommend with a straight-face to an experienced Common Lisper who isn't interested in JVM integration.

So what's new? What do you really win with Clojure other than better libraries and community? Not much.

Oh and the uh...concurrency primitives? They're a canard. They're neat, they're designed excellently (being that it's Rich Hickey), but they're just not as impactful as other things are these days.

If single-node/instance performance was important, you wouldn't be able to do it on the JVM. If scalability is important, shared memory on a single node is irrelevant and it becomes a matter of implementing a partition tolerant database.

The concurrency primitives would've been more important in an alternate universe where we didn't use databases/data stores/filesystems for state management and synchronization and instead did Smalltalk stateful servers.

That didn't happen and it was an extremely bad idea and we live in a world where java.util.concurrent exists.

So the CL'er who codes like a bi-polar hermit doesn't care about Clojure.

You want to win the Lisp-community-at-large? Give them more power. It doesn't have to be the trivialized imprecision of expression that comes with something like Ruby. It doesn't have to be the minimalism of Io and Scheme. It doesn't have to be native continuations.

It doesn't even have to be Shen or Haskell-style static typing.

What it does have to be...is more powerful for the lone cowboy. It's going to be hard to convince a lot of them without really hitting a home-run on that one metric. Especially in a post-CLOS/Art of the Metaobject Protocol world.

I think Rich Hickey knew from the beginning he wasn't going to win a huge chunk of the CL'ers over. I don't think it mattered. I think what mattered is that people stuck in the Java enterprise universe could have their sanity-preserving escape hatch.

It's a mistake to believe Clojure was designed for CLers. It was designed to save Python, Ruby, and Java people.

A similar case of mis-targeting is Go. Go itself was ostensibly a "systems" language when it launched. They got called out on the absurdly inaccurate labelling so they've since repositioned it as a general purpose language. Which is accurate.

They thought they were going to compete with C++. That's nearly impossible until someone comes up with a true successor to C and C++. Anything that doesn't enable absolute control over memory and semantics will never succeed them. There always has to be the "bottom" where you can exert near-dictatorial control over the behavior of the computer. Many industries need this.

Go was never designed to enable that, it was designed to make writing simple code simpler. That's all. And it's good at that. I was surprised when people with the cultural wisdom and background such as Rob Pike were surprised that they were getting Python and Ruby people instead of C++ people.

The raw contempt Go programmers have for debugging and interactive programming is appalling. That alone turned me off completely to the community. Partly because the only reason for that attitude is some off-hand statements Ken Thompson made in Coders At Work and elsewhere. Cargo-cult at its most definitive.

Why would a C++ programmer move to Go? They lose control of the memory, for which they have many layers of abstraction they can resort to (malloc/free, new/delete RAII, unique/shared pointers, Boehm's GC which is basically equivalent to pre-Go-1.1 GC, etc.)

They also lose the benefit of their years of investment and learning in C++ which offers them a dizzying depth of choices in abstraction layers. This has obvious disadvantages. C++ is a terror to attempt to write safe and stable code in.

It is however, extremely powerful and the "pay only for what you use" is essential for systems programming. My personal preference is C since I feel like I'm not aiming a bazooka at my face, but as a Common Lisper I understand the appeal of the power they feel they get from C++.

Even if the 'power' in C++ is of a different sort than that which you get from Common Lisp.

People unwilling to recognize and understand the power, advantages, disadvantages, and design trade-offs made by "scary" languages like C++ and Common Lisp will never be able to fully learn the lessons borne.

So no, I'm not surprised Go didn't attract primarily C++ programmers. Not in the slightest.

It's mostly been Java, Python, and Ruby programmers...for various different reasons. Like Clojure.

Most of the programming languages of the last 5-10 years have been "sidegrades". Enhancements of accessibility, of cultural idioms, of extracting a different emphasis on a subset of semantics that previous languages supported.

Have we really advanced beyond Common Lisp, Prolog, Smalltalk, and C++?

What does it mean to make a language more powerful than those? Is there a limit to expressive power? What do languages like REBOL say about "normal" languages? What about APL?

On a parting note, the only language that I've felt has truly expanded my horizons and impressed me in the last ~5 years has been Haskell (although it's much older than that). That said, I feel Haskell is a spiky, uncomfortable urchin of a language that is highly optimized to a local maxima of expressing problems in code. I learned a lot from Haskell, but I'll never be more productive in it than Python or Clojure or Go or anything else.

Too awkward, if enlightening.


I, too, came here to comment just because I thought an excellent article wasn't getting much discussion :(

I think the concurrency - both Clojure and Go trying to fix it - is a big deal. I live in the world of the partition-tolerant databases and multiple nodes and all and its a super-crap horrid world where everything seems permanently fundamentally broken. You can go a long way on a single node if you just have good clean design. I pay a lot of attention to new stuff like Spanner but right now all our choices are flaky. Related blog posts of mine http://williamedwardscoder.tumblr.com/post/18065079081/cogs-... http://williamedwardscoder.tumblr.com/post/16399069781/googl... etc

Regards your point that Rob & co couldn't correctly define "system language"; well, surely their definition ought to trump the interweb? If they consider writing servers 'systems programming', then I'd say it was ;) I mean, they didn't make the claim in a vacuum; its presumably what Google internally calls a 'systems language'?

That C/C++ people don't flock to Go is a shame, because C/C++ is so unnecessary for so many projects. Its really rare to need C, and never necessary to need C++ (and I've worked on C++ kernels back in the day).

There, hopefully my comment is hyperbolic enough for someone to take issue with a point and discuss ;) I do stand by my general thrust though


C/C++ are necessary for a lot of things, things that Go isn't capable of doing or wouldn't be very good at doing.

Go isn't a systems programming language. They called it that because compared to a language like Python it's closer to the hardware.

A systems language has various properties, like strict memory layout and management control, varying degrees control over code output, being able to bootstrap an OS without depending on a wrapper OS / bootstrap VM / extensive stdlib, etc. Go fails to meet any realistic definition of a systems language.

Go is instead a compiled alterative to VM languages like Java and Python.

Black is not white just because Rob Pike said so. He's a brilliant man but he's always been a bit off to the side in terms of not really being in 'sync' with everybody else. This is just an uncommonly concrete and inarguable example of that.

He himself backed off the 'systems' descriptor when he realized his error.

You're fighting a bogeyman that doesn't exist.

>because C/C++ is so unnecessary for so many projects

People don't really default to C/C++ for anything they shouldn't anymore. They live way higher up the stack by default by FAR.

C is generally only used where appropriate (kernel, embedded, drivers, services like Redis, etc.)

C++ is the province of Microsofties, game developers, database coders, browser implementors, and OKCupid employees. (Mild exaggeration)

I mean seriously.

When was the last time you heard of somebody doing a GUI desktop app or web app in C or C++?

Dropbox is Python, most Ubuntu/Gnome/GTK apps are Mono/C#, most web apps are Java/PHP/Python/Ruby, frontend web code is inescapably JavaScript with their ongoing attempts to shoehorn Node.js onto the server-side. Some weirdos and Perl6 hopefuls even use Perl for their primary language these days.

Node.js is as good an example of the "sidegrades" I mentioned in my original comment, except it's spectacularly awful in so many ways that I have to wonder if it's trying to draw even more uninformed and informed detractors than C++.

So who exactly is using C for everything on the planet? It's a strawman. Nobody does that anymore. People have become comfortable with resorting to higher levels of abstraction as appropriate.

Mostly because of Perl, PHP, Java, Python, and Ruby.

In the end, performance and control either matter or they don't.

If they do matter, you need that last-mile escape hatch that will never-fail.

If they don't, pick something "fast enough" that makes sense for your personal tastes that suits the problem and have a ball.

There will always and forever be a place for languages like Fortran, Ada, C, and C++ even if they themselves might not survive the next century.


"When was the last time you heard of somebody doing a GUI desktop app or web app in C or C++?"

Anyone working in Qt has probably done a GUI desktop app in C++, but I whole heartedly agree with the rest of your statement with some caveats as there's still many projects getting written in C++ as it's often better the devil you know.


all good points, well made.

I find it disappointing that we've come to label systems languages as the languages with the properties to implement the 'systems' of yesteryear instead of the systems of tomorrow; Singularity, for example. One wonders if Pike and co were to build a new OS just where they'd put the managed/unmanaged line.

Wikipedia says http://en.wikipedia.org/wiki/System_programming_language "The distinction between languages for system programming and applications programming became blurred with widespread popularity of C and Pascal." and I'd hazard that Pike was smearing that blur wider by saying Go. The Go FAQ http://golang.org/doc/go_faq.html still starts by saying "No major systems language has emerged in over a decade" and implicitly saying Go is to be it.

Now to my point that C/C++ is usually a bad choice. Most C++ projects I've seen have been misguided, legacy choices from the late 90s when C++ was the rage. Then again, I've always been mystified by the appeal of STL, since it only just got a hashtable. I have always ended up building higher-performance custom collections for stuff and found STL with its iterator-instead-of-ranges clunky.

I've written buckets of C/C++ code for OS and multimedia projects, some fairly recently; but even then, I'd rather have written only the innermost mechanics of them in C and lashed them together in something that was nice to work with, good C interoperability (no I don't think python tooling is nice) and didn't throw completely out all performance concerns. And until Go came along, there really wasn't anything. Python and so on are only useful for coordinating stuff when the task is embarrassingly and massively parallel.

Along comes Go; you can still x-ray some Go code and have a pretty shrewd idea what the resulting machine code looks like, just like C/C++. Its within spitting distance of C/C++ code for performance and will improve. And as the concurrent scheduling is all in the hands of wizards, one expects it to scale multi-core rather better than something working at the lib-level that requires more discipline to use.

Having said that, I'm actually using Java for a current no-compromise-performance rewrite-from-Python project now. Its Go but its tried and tested. Still, I am not enjoying myself too much.

FWIW, had a fun bug in production the other day; turns out I must be the biggest user of Python in a sense, since I discovered - via a crash - that multiprocessing is using `select()` internally and will fail if it it gets a descriptor over 1024.. how come nobody else has discovered this? I see only one person has, and the fix is in ... 3.3. Just a fun story.


>Its within spitting distance of C/C++ code for performance and will improve.

No, it is not. I don't want to make too much of this because I know that these sort of performance characteristics seldom matter at all in the kind of programming most of us would do with Go, but - - based on the benchmarks game (http://shootout.alioth.debian.org/u32/which-programs-are-fas...) - Go is 6x slower than Fortran/C and is quite a lot slower than Java as well. The 6g/8g compilers will never be nearly that fast because they are optimized for compile time rather than runtime. gccgo may eventually be nearly that fast.

Go will never be a systems language because it will never be possible to: * control memory directly (kernel, device drivers) * expose a C compatible binary interface (libraries) * dynamically link to libraries (pluggable modules ala Apache httpd)

That rules out a whole heck of a lot of software that could reasonably be considered systems work. Of those issues, by far the lack of an ABI is the biggest turn-off to me. I would really like to be able to optimize critical Ruby code by writing native extensions in Go rather than C, but I can't and never will be able to. Rust is really the only thing that may someday be a more reasonable choice for that than C. Instead what has happened is a lot of Python and Ruby developers have picked up Go and would like to call their work "systems programming". Go is pretty good for a lot of this work, but it is not systems work.


>> based on the benchmarks game <<

fwiw 8g seems to produce slower programs than 6g, so to be charitable --

http://shootout.alioth.debian.org/u64/compare.php?lang=go


I'm sorry to be this blunt, but it's quite apparent that you haven't done any serious systems programming. That you were surprised by the syscall underlying multiprocessing...says a lot although I could point to other indications.

Please don't make assertions as to the necessities of a specialty you haven't delved in, it makes it very difficult for me to be civil and respectful.

There is...no real comparison between C/C++ and Java for last-mile performance at the bleeding edge, even if Java is a VERY good high-performance replacement for Python for stuff like network services.

There are a variety of other use-cases where C/C++/Fortran/Ada are extremely necessary. Also note how abysmal Java has been for Android compared to Obj-C with its ever-present escape-hatch to raw C for making responsive and pleasant mobile apps. Especially games.

That aside, stuff like Singularity is research-grade only for very clear and obvious reasons. It isn't practical yet, if ever it would be.

Losing a lot of potential performance and control over the machine at the universal OS level is pretty...damaging and limiting.

It's bad enough that an entire programming language ecosystem can put a cap on your power over the computer and the performance/behavior thereof, to do that at the OS level except as a research project is unconscionable.

Please don't act as if Wikipedia articles about Microsoft Research projects are some indication of the vanguard of operating systems.

> you can still x-ray some Go code and have a pretty shrewd idea what the resulting machine code looks like, just like C/C++.

Er, maybe in the trivial case. You won't have anything close to a deterministic or real-time model for memory management available to you though. And never will.

Everything Go provides on top of C in terms of extra features essentially requires GC to function. (goroutines, and related features). The only thing it really adds on top of C that doesn't necessitate the GC is most aspects of the type system. That could be reused in a hypothetical systems language.

Go itself, in its current design, has absolutely zero future as a systems-language-of-first-resort outside of tinkering. (Some people will cross-compile Go code to chumbys and stuff.)

However, it has something more excellent available to it. A potential future as the hero that slayed Java and supplanted it. I would rather it did that than focused on trying to compete with C or C++. It's not suited to the task and cannot be reconciled with that goal as a fundamental property of its design.

Go is an excellent language for network services. Like Java. Doubly so once they replace that awful garbage collector in 1.1


now we both came here to get a discussion going; now we've got one, you can drop out of the troll personal attack mode.

So you have made quite clear that you find the various named non-bare-metal languages used for 'systems projects' distasteful. But you can't make them undone. You can say they were the wrong tool for the job in your opinion, too, but you can't say that others are wrong to consider them system languages.


An easy and accessible rule of thumb goes as follows:

Could I use this language for:

Writing an OS for a PDP-11 that was reasonably close to the assembler in performance albeit not compactness?

&&

Writing hard real-time constrained avionics software?

&&

Writing HPC software for scientific purposes that takes advantage of strict memory control and vectorized, hardware-specific instructions for maximum throughput?

With varying degrees of expertise and specialty, C, Fortran, Ada, and C++ all qualify.

Try writing even a simple linear algebra algorithm in Java. You won't get anywhere near Fortran or C++. Try as you might. Even relatively sundry CV work is unpleasant outside of the prototype phase on anything but C++/et al.

I'm sorry you felt attacked, but the scope of experience is relevant to the subject. I realize it's very difficult to discuss one's limitations, or have them pointed out by others, without internalizing it and making it a subject of ego.

I generally stick to the high level tier of languages until I am forced to drop down a layer. Experience and pain have stripped me of all hubris that could lead me to believe humans could overcome the fundamental semantic and informational constraints involved in optimizing code that needs to concern itself with the machine-behavior from a higher abstraction layer. I've done more JVM and GC fiddling than I care to recall.

There's a glass ceiling, you won't escape it. Even Paul Graham, the master Common Lisper himself, took advantage of the relatively easy to use FFI faculties in Lisp to drop down to C to optimize hotspots. This was a common pattern when he was doing ViaWeb, I'm told.

It doesn't have to be that way. I am genuinely sorry if you felt attacked or that I was uncivil. I will find other ways to express myself if I run into another similar situation here. That was a failing on my part, please forgive me.

I'm not wont to pontificate to plumbers as to how they should go about plumbing. I say that as someone who's actually redone the plumbing in a residence from top to bottom with my bare hands before. Despite that, I know I'm not a professional plumber and I don't have the experience necessary to say much about it even if I've technically "dabbled".

I don't let a little experience overstep its bounds.


I didn't feel bruised, I felt pity ;)

People write hard constrained trading software in Java e.g. http://mechanical-sympathy.blogspot.se/ Googling for java avonics has some hits too e.g. http://www.slideshare.net/keugbang/t-50-avionics-embedded-so...

I was pretty familiar with the intracities of real-time called iirc "guaranteed service" back when I worked at Symbian. That was a kernel written in dialect of C++. And I've written camera and video capture software for, among others, Android phones. So fairly general experience, I'd say. Still so much more to learn.

You, on the other hand Chris, keep calling out Rob, me and anyone else who thinks that PDP-11 is not a necessary requirement for the next decade's "system language" ;) What systems projects have you worked on then?


And lets not forget the Oberon family of operating systems I referred to in another thread.


Indeed I used Oberon (both native and windows-hosted) for a few intense months back some summer in the 90s. I still have a fondness, perhaps rose-tinted by time, for Pascal languages.

I particularly remember when someone made an Oberon pcode VM browser plugin as a 'competitor' to the newfangled Java applets. I think it was caled Juice or something.

Interestingly Chrome NaCL is going in the same direction, distributing pcode (well, LLVM IR iirc) and doing final compilation on-target.


Maybe you should have a look at Native Oberon and BlueBottle.

They are both single user destkop operating systems implemented in GC enabled systems programming language, Oberon and Active Oberon respectively.

The only assembly is the boot loader, GC and some low level glue for device drivers.

Everything else is written in plain Oberon or Active Oberon, and you get a fully working desktop environment.

This has been used at ETHZ since the late 90's. http://www.ocp.inf.ethz.ch/wiki/Documentation/WindowManager


>However, it has something more excellent available to it. A potential future as the hero that slayed Java and supplanted it.

If you had to stay on the JVM platform (for argument's sake) and supplant the Java language - would you choose a particular language ? I have read your comments above on Clojure and was wondering what you thought about Scala ?


>was wondering what you thought about Scala ?

For my preference, I'd rather use Haskell or Clojure but, I appreciate the ecumenical attitude it brings to the table and I think it's an excellent choice for Java developers that want to grow and learn.


As you may not know you can develop with C/C++ on Android , there is something called the NDK, that is used in a lot of games.


Your post is too long for me to address all the points :)

Common Lisp, Prolog & Smalltalk all have their issues - fortunately they all deliver on the big idea - a reasonable meta system. But there are an incredible number of incremental improvements that could be done to what we know is good about these systems - this work absolutely needs to be done and IMO Clojure is one such example of this.

As far what does Clojure have to offer CL programmers - there are a few CLers in the Clojure community. Those that have actually put in the time end up liking Clojure just fine as far as I can tell. You should talk to them and find out what they like. For the the rest, I think CL was born of a culture of Lisp infighting. For example, the CL / Scheme rift makes little sense to me and probably has deep historical / political roots that don't interest me that much. It warms my heart that Lisp luminaries whether CL (Richard Gabriel) or Scheme (Dan Friedman & Will Byrd) are looked very highly upon in the Clojure community.

I think it's important to note that the number of users coming from Java is about as large as Ruby & Python combined. Clojure is Lisp after all and the syntax probably won't jive with people attached to surface syntax the way some Ruby & Python devs are. Adventurous Java devs are probably plenty excited about the lack of ceremony ;)

As far as predicate dispatch - I wouldn't say it's stalled so much as it's a project with a few tough pieces to work out. One big hurdle was getting cKanren worked into core.logic. That's now mostly done. So the next step is to clean up core.match. Also, I spend a lot of time on this thing called ClojureScript ;) so I haven't worked on predicate dispatch nearly as much as I would have liked.

I too have little interest in Go, but some hackers I respect really like it. So obviously there's a lot of things that Go gets right.

Finally, I'm not convinced that Clojure doesn't bring anything new to the table. I agree there is no one feature that I can point out that doesn't exist in some other decent PL - but after some four years of Clojure programming - this language still make me smile!


I think CL was born of a culture of Lisp infighting. For example, the CL / Scheme rift makes little sense to me and probably has deep historical / political roots that don't interest me that much.

Well, the former is true; CL was a very successful attempt to unify the existing mainline LISPs and while adding the lexical scoping of Scheme. That process was inherently political, and I'm told the phrase "sufficiently clever [or smart] compiler" was used rather too often, e.g. to get some inherently expensive off of Lisp Machines stuff into it).

Scheme has very different objectives. It started with a clean slate, threw away a lot of historical baggage and it's a Lisp-1 instead of a Lisp-2 (single value for an atom, does not potentially have both a value and function), and since its initial development has stressed simplicity and correctness (i.e. figuring one correct way of doing something), which have never been mainline LISP goals. E.g. look at the mission statement from the beginning of the standard's documents:

Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today.

The premise is debatable (and Scheme has not particularly broken out of the niches of language work and education), but it's very different than mainline's LISP's.

So while their might be a "rift", there never was any chance for anything else. Schemers are not going to add a lot of legacy LISP to their language (let along become a Lisp-2) so that they can run legacy mainline LISP code, Common Lispers, even if they don't have an existing code base, have needs that are not as yet satisfied by Scheme due to its very slow standardization process and the false start at addressing them in the deeply flawed and largely rejected R6RS.


Great comment. Do you have any thoughts why it's so hard for Ruby people to create an efficient implementation of Ruby? There are plenty of efficient Common Lisp implementations, and Ruby implementations are nowhere near close to them. This surprises me, because I didn't get an impression that Ruby is so much more expressive (or even more expressive at all) to justify the slowness of Ruby implementations.


>Great comment.

Thank you very much.

>Do you have any thoughts why it's so hard for Ruby people to create an efficient implementation of Ruby?

The most concise way I can put it, and frankly this is just a rephrasing of Nutter's original linked post but:

Ruby forces you to carry a lot of dynamic buckets of state and context around and make them accessible and mutable in unpredictable, hard to optimize ways.

Ruby isn't that much more expressive so as to justify its slowness, that was part of the point of my top-level comment. The slowness comes from the ease of use of the expressive power and how "accessible" it is.

Common Lisp is much more powerful, especially at "scale", but it's less accessible and trivial and forces you to be more structured and precise in how you pass around state and access data. Despite that, it still enabled powerful ways of manage conditions/exceptions, continuations, predicate dispatch, etc.

Nutter is really the guy to talk to on the nitty-gritty. I'm just speaking from a differential semantic viewpoint of how it compares to a much faster and more powerful programming language.


Aside from the huge benefit it gets by being single-threaded, doesn't javascript have a lot of this same baggage? V8 is so much faster than Ruby for certain algorithms that I would think there still has to be lots of room for optimization if someone poured the money and IQ into it that Google did.


I found the comment more interesting than the article, though it goes in a very different direction :)

As somebody coming from the other end of the spectrum (Java/Python and other dynamic languages), I'm curious to know what you think of Rust as a systems programming language, once it matures. You get a number of high-level/functional idioms, built-in concurrency and either garbage-collected or manually-managed memory.


Rust is a side-grade to C++, but I think its emphasis on immutability first, mutability only when necessary is important regardless of anything else they do.

Rust can elevate itself above the sidegrade moniker once they get regions working.

I think the Rust developers are going to be similarly disappointed as the Go developers were if they think they're going to convince a bunch of C++ programmers to come over.

Most C++ programmers are convinced they've solved their own problems using the same tools Rust purports to offer (unique pointer, shared pointer, etc). You won't be able to convince them to abandon all that knowledge for unfamiliar territory for a language that offers identical pointer semantics with slightly-easier-than-normal baked in concurrency.

There's fundamentally nothing Rust offers that one couldn't do in C++, and I don't mean that in some kind of silly "hurrr turing-complete!" sort of way. I mean it's a realistic fact of modern C++ development that apps written in C++ will bear some measure of resemblance to how Rust enforces it at the compiler level.

With Rust, however, you get immature tooling and maybe region-based memory management.

Maybe.

Feature-based programming language is more than a little silly, but that's how it's going to fly with the C++ devs. They have all the toys in their playpen that they like having available.

No proposition that supposes removing some set of those toys without offering something incredibly substantive in return is going to go over well.

Rust offers a lot less flexibility and control in terms of concurrency as well. If at any point the task-based concurrency should fall apart for your use-case, you're more or less fucked.

No C++ user would ever accept those kinds of constraints for the sake of making it easier to write stable, correct software. The degree of tooling that they have at their disposal already makes it eminently possible to do so.

Rust is a response to the C++ quagmire and the dissatisfaction with that. So was Java. I see Rust as serving the more hardcore flip-side to Java's use-case, whereas Go serves the softer side. Rust will be more suitable for tighter constrained software, but still won't offer the limitless control and power of other systems languages.


Excellent comment, I thoroughly enjoyed reading that.

Would you mind expanding on your last paragraph re: Haskell ? After a few months of casually studying Clojure I've decided to switch my focus to Haskell and so far I'm very impressed and actually finding it to be a bit 'easier' to work with, so I'd be very interested in hearing more about what I should expect from the language overall.


> You want to win the Lisp-community-at-large? Give them more power. It doesn't have to be the trivialized imprecision of expression that comes with something like Ruby. It doesn't have to be the minimalism of Io and Scheme. It doesn't have to be native continuations.

>It doesn't even have to be Shen or Haskell-style static typing.

>What it does have to be...is more powerful for the lone cowboy.

Could you expand on what you think Clojure needs to win over the Common Lisp guys?


>Could you expand on what you think Clojure needs to win over the Common Lisp guys?

I don't think it should even try. I think being the 'practical' Lisp is a good place to be.

That said, there are a few issues that are going to make some CLers irrationally intransigent.

The JVM is a biggie. They hate it, they don't want it, and they definitely don't want to be constantly skimming across the surface built on a foundation of Java libraries.

The dream was the Lisp machine, tur---Lisp all the way down.

Clojure is the refutation and negation of that dream. It is, to some CLers, an insult and a defeat.

You will never win those people.

Those even willing to pay the price of having to learn two programming languages at the same time (Clojure and Java) for the sake of getting a more modern and hip Lisp are still going to have a few sticking points.

1. Inability to produce binaries

2. You don't win anything in terms of individual productivity, nominally. The language is a side-grade.

This goes double if they're eccentric and like implementing predicate-dispatch libraries instead of mobile-social-local web app mash ups.

3. Clojure, semantically speaking, while cleaning up a lot of Lisp warts actually removes and hinders a lot of patterns that CLers relied on via mutation. The last thing a Common Lisper wants is the elimination of the option to do something.

Common Lispers, culturally, have more in common with Haskell than Clojure.

Their Haskell just hasn't been made yet.

Clojure is a cultural mismatch for many Common Lispers, especially the obsessive navel-gazers who to their credit, are the vanguard that advances the standards and research into the languages they use.

There are definitely those types of people in the Clojure community (amalloy wrote a decent article on anaphoric macros in Clojure), but the depth isn't there.

By going from Common Lisp to Clojure, you only lose things irrational as that may seem to normal people.

I mean, you even give up tail-call optimization. Yes yes, I know, (loop ... recur) and trampoline, I know. But it's not me you have to convince.

I'd rather keep the company of somewhat more sane people such as that use Clojure. That doesn't hold a lot of value for a lot of CLers I know though. They don't give a damn and never have.


Basically Clojure is a nice Lisp designed by a Java/C/C++-expert and programmer (!) (Rich Hickey) for himself. Lots of Java developers find it interesting, because they have similar programming needs. Then they joined him.

Common Lisp is a Lisp designed for Lisp programmers. As a Lisp programmer I want more Lisp, not less Lisp. I also want it close to the metal. If I use 'Unix', I want to have access to C and 'Unix'. Not so much Java. On the Mac I want to interface to Objective-C and C - not Java.

It's not that Common Lisp users will give up just because someone comes up with another Lisp derived language. We seen them a few times: Dylan, ISLisp, Newlisp, R6RS, Arc, Clojure, ... some claimed even that Ruby or Javascript were Lisps. There'll be more in the future.


> 1. Inability to produce binaries

This is not true, as there are commercial Java compilers for native available.

Here is one of them, http://www.excelsior-usa.com/jet.html


So one gets down-voted for stating the truth that Java is not constrained to the JVM, great!


I would have thought it'd be obvious. The primary thing Clojure has to offer over CL is egal. You can't have a sane equality predicate in a language where the basic data structures are mutable.

http://home.pipeline.com/~hbaker1/ObjectIdentity.html


Very nice comment. +1

I fully agree with you.


Wow. OP might as well have said, "I haven't used Ruby much, don't understand it, but still don't like it."


By "OP", are you referring to the author of the blog post, Charles Nutter? It doesn't seem like an easy feat to not understand Ruby when you've written a major implementation of it, namely jruby in this case.

It's also pretty hard to spend a very significant amount of your time implementing a language you don't like. Finally, addressing his use of Ruby: https://github.com/headius


Your logical fallacy is ad hominem or appeal to authority. It doesn't matter who he is or what he has built.

The poster seems to favor a more complicated interface with a simpler implementation. That is basically the opposite of what is great about ruby: a simple interface with more complex implementation.

You want a run-down of couple points, fine. These exemplify the misunderstanding of the goal of Ruby.

> Fixnum to Bignum promotion

The entire point of class promotion is to remove the constraints of Java, C, et al. have to the machine architecture. And then there's the transparent and dynamic treatment of variables. Class promotion and dynamic typing allow a more math-like syntax and usability.

> Closures

It is entirely freeing to have blocks treated as they are. Java is no comparison, its overly verbose syntax and lack of dynamic variable scoping is supremely limiting. Similarly, it is a question of brevity, least surprise, transparency, and dynamism.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: