6 ms·
Ask YC: Ruby and Lisp devs, please answer this (Not a flame war)
I'm a Ruby guy, I've fallen in love with the language thanks to Rails. I have a Master's in CS and in college we studied mainly Java, along with some Lisp and C, but I try to do all my current programming in Ruby.
In an effort to not be a Blub programmer I have taken another look at Lisp to see what I'm missing, but I'm afraid that I can't really see it. I found this page http://innig.net/software/ruby/closures-in-ruby.rb which explains Closures in Ruby and after looking through that I don't really see what I could do with Lisp that I can't do with Ruby.
Again, I'm not looking for a "OMG Python is better than both" I would just like some honest answers about what the differences are. It's always worth it to learn new languages but would it be a better use of my time to start over and learn Lisp or just learn how to proficiently use Closures in Ruby?
Any comments, questions, etc. would be appreciated.
- apgwoz 19y agoYour likely to get many comments about macros, so I suggest you take a closer look at what macros actually can do for you. That should be a sufficient enough reason to take a closer look at Lisp (be it Common Lisp or Scheme).
- Todd 19y agoThat's it, in a nutshell. The macro facility is what differentiates Lisp from other dynamic languages that have, seemingly, all of the same attributes--dynamic/lexical scope, closures, etc. They allow you to write a true DSL. Paul Graham pretty much wrote the book on the subject (On Lisp) which he graciously offers as a free download since it's out of print.
- pg 19y agoAs a data point, in the source code of Arc and its libraries + the web server + News.YC + all of YC's internal applications, there are 738 calls to def (= CL defun) and 187 calls to mac (= CL defmacro). This isn't a complete list, because there are other defining operators, but it gives you an idea how large a role macros play in a typical Lisp application. If you measured by uses of each type of operator, the role of macros would be even larger. You often write a function that you only call once, but you wouldn't do that with a macro. Here's the last piece of code I wrote. I wrote it because I was curious to see what colors users had chosen for the top bar. (defopa topcolors req (minipage "Topcolors" (tab (each user (sort (compare > [karma _]) (keep [aand (uvar _ topcolor) (isnt it (hexrep orange))] (keys profs*))) (tr (td (link user (user-url user))) (tdcolor (hex>color (uvar user topcolor)) (hspace 30))))))) There are 10 macros used here: defopa, minipage, tab, each, karma, aand, uvar, tr, td, tdcolor. Actually it's a hack that karma is a macro. I wanted it to be settable and was too lazy to define a setter, so I just defined it as a macro. It should be a function, and I should be able to say just (compare > karma).
- Tichy 19y agoI thought that Arc is written in Scheme, not in Common Lisp? Are Scheme Macros equally powerful? Edit: OK, perhaps Arc is written in Scheme, but Arc itself features CL like macros, that would explain it ;-)
- eru 19y agoAs far as I know Arc is written on top of MzScheme. Besides its 'clean' macros - MzScheme supports CL like macros, too. But your explanation could be correct as well.
- pg 19y agoArc is written in Scheme in the sense that it compiles into Scheme, and uses the Scheme read, numbers, etc. But Arc macros are not Scheme macros.
- apgwoz 19y agoScheme also has "CL" like macros that are hygienic. Scheme 48 for instance, supports explicit renaming macros and MIT has syntactic closures. However, most schemes have a library that adds your traditional defmacro style macros, CL users are likely to want, but there use is almost always discouraged.
- pg 19y agoI just entered this variant into the server's repl so everyone can see the range of choices: (defop topcolors req (minipage "Custom Colors" (tab (each c (dedup (map downcase (trues [uvar _ topcolor] (keys profs*)))) (tr (td c) (tdcolor (hex>color c) (hspace 30))))))) Defopa means only admins can use something, but since this is defined with defop, everyone can see this page: http://news.ycombinator.com/topcolors http://news.ycombinator.com/topcolors.
- Tichy 19y agoThat calls for the feature to enable color picking by clicking on the colors ;-)
- gregwebs 19y agoThere is another facility ruby and lisp lack- a good typing system- which you can find in languages like Haskell.
- sspencer 19y agoSome would call that a feature, not a bug.
- sabat 19y agoLack of strong typing in a language is usually on purpose (dynamic typing). But sometimes you want it. I like the idea of optional strong typing in a language. Perl6, may it rest in peace, had that feature in its spec.
- capablanca 19y agoBtw, will Arc ever be open-sourced? I'd love to just sudo apt-get install arc in this lifetime.
- pg 19y agoFor once, I will answer this question: yes, soon. This winter, I hope.
- tjr 19y agoVery exciting. Should we arrange another Lightweight Languages day at MIT for this?
- weel 19y agoMore generally, somebody should arrange another Lightweight Languages day at MIT no matter what. Or maybe a Lightweight Languages days somewhere else. And wherever "they" organize it, it would be awesome if they could manage to webcast it and have people who cannot attend pose questions through IRC. I attended Lightweight Languages once and it was awesome. Informal, a large variety of smart people, but each smart in their own way, that had a lot to genuinely learn from each other. Sadly, conferences, even comparatively small and informal once, take some effort and some money to put together, and frankly it's not going to be me who is capable of coming up with either.
- enigman 19y agoIn theory, it should be possible to get better performance out of a Lisp application, since most versions of Common Lisp include a compiler. Ruby is interpreted at present and can be slower in some contexts. Runtime pauses for garbage collection can be quite noticeable in Ruby.
- damon 19y agoRuby descended from lisp, according to matz. So in order to "see what you're missing" by using ruby, take a look at what he removed or changed from lisp. In particular he removed macros and created syntax. As others have commented, macros are a very powerful language feature. http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/179642 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/...
- brlewis 19y agoIt's not that there's something you can do in Lisp that absolutely can't be done in Ruby. It's just that it's more convenient in Lisp, e.g. real closures instead of seven or eight closure-like constructs. I took a look at that Closures in Ruby page you mentioned. It says about Ruby: "This is quite a dizzing array of syntactic options, with subtle semantics differences that are not at all obvious, and riddled with minor special cases. It's like a big bear trap from programmers who expect the language to just work."
- Zak 19y agoRuby has real closures with semantics similar to Lisp: lambda expressions that reference variables from their enclosing lexical scope. It also has a number of constructs that create closures implicitly, and some others that may or may not be implemented that way, but you're not required to use them. You can use closures just like you would in Lisp.
- jimbokun 19y agoHere's a good comparison: http://markwatson.com/blog/2008/01/cool-common-lisp-elephant-object.html http://markwatson.com/blog/2008/01/cool-common-lisp-elephant... Performance is a big difference: "Common Lisp compiled code runs much faster than Ruby: typical benchmark results are about 30 times faster - but Ruby's slowness is mitigated if a lot of processing is performed in native libraries like Ferret." I don't think Ruby has all of the functionality of CLOS or the Meta Object Protocol. Here's Matz commenting on the lack of multi-methods in Ruby: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/49964 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/... "Most OO langauge includes Ruby see methods as "element of an object" This does not hold for CLOS. You loose the tight relationship but gain a new level of flexibility." Beyond that, I would say pick a programming methodology and there is probably a CL implementation of it somewhere out there built with macros. That's due to the greater maturity of CL and "real macros" (which have been well covered by others already). And beyond macros, the "code as data" paradigm enabled by s-expressions has other uses (I think Steve Yegge mentioned "executable log files" as an example).
- dag 19y agoThe main difference is that Lisp has macros, no other languages' macro systems come close. For the cute version of why Lisp macros are so awesome check out chapter 8 of Practical Common Lisp (http://gigamonkeys.com/book/ http://gigamonkeys.com/book/). For the serious and intense version check out On Lisp (http://paulgraham.com/onlisptext.html http://paulgraham.com/onlisptext.html).
- kyle-burton 19y agoOther features that have piqued my interest (besides the already mentioned, and vitally important, macros) are: - conditoins and restarts - CLOS - reader macros (which are distinctly different from normal macros). If you're talking about other Lisps (besides CL), like Scheme, it's worth looking at define-syntax and syntax-rules and how they deal with some of the intricacies of creating macros with define-macro.
- mnemonicsloth 19y ago1. CLOS and the MOP have some very devoted advocates, and it's obvious that CL's object model contains a strict superset of the behaviors available in other languages. If you don't absolutely hate OOP, they're worth checking out [1]. 2. Macros. Macros, macros, macros. Commonplaces like "code is data" and "program-writing programs" are useful characterizations, but they make it easy to underestimate how much of a productivity booster metaprogramming can be. Despite regular practice and a lot of first-rate reading material, I stayed clueless about macrology until I got stuck with a big ugly infrastructure problem [2] that forced me to use a bottom-up style. At some point I macroexpanded my code out of curiosity and found myself staring at pages and pages of boilerplate. Some of it -- database code in particular -- even reminded me of stuff I previously would have done by hand. Anyway, I guess I recommend the Kool Aid... [1] OOP owes me my Freshman and Sophomore years. [2] I was building a platform, but I can't talk about it.
- vikram 19y agoFrom the Ruby side the difference is the quantity and quality of libraries that are available. You are likely to find stuff that is currently been worked on, with CL this can be a real problem. There are a lot of half done libraries, so you have to be willing to read a lot of code, either make improvements yourself or write some from scratch.
- tx 19y agoAll other Lisp-inspired languages, including Ruby, have added one important feature by introducing their biggest restriction: they went with more complex syntax abandoning Lisp's S-expressions. By doing so, they have created a substantial difference in how code and data are represented: whereas in Lisp everything, including your code, can be treated as data. This is, in my humble opinion, the biggest difference between Lisp and others.
- db4n 19y agoMacros can be used to automate function definition. You can't use blocks and HOFs for that, because definition occurs at compile time. You can also automate definition of other macros. http://paste.lisp.org/display/54227 http://paste.lisp.org/display/54227
- nickb 19y agoTry RLisp, http://chaosforge.org/taw/rlisp/ http://chaosforge.org/taw/rlisp/ "RLisp is a Lisp dialect naturally embedded in Ruby"
- stefan_tilkov 19y agoI know that Ruby's metaprogramming facilities don't equal Lisp's, but does that matter in practice? i.e. is there a convincing number of metaprogramming use cases that can be implemented using Lisp macros, but can't be implemented using the Ruby meta object protocol?