5 ms·
Lisp's Influence on Ruby
- pjmlp 4mo agoThat is actually Lisp influence on Smalltalk, and Perl, that eventually influenced Ruby.
- dragonwriter 4mo agoNo, its actual influence from Lisp-family languages (including Scheme). Yes, Lisp also influenced Perl and Smalltalk, but Matz was not ignorant of Lisp with the only influence om Ruby from Lisp being indirect through those other languages.
- Smalltalker-80 4mo agoTotalle agree, I just googled it: "Yukihiro 'Matz' Matsumoto heavily credits Smalltalk as the deepest structural inspiration behind Ruby’s object model. He combined Smalltalk’s beautiful object-oriented architecture and message-passing system with features from other languages to create a tool designed primarily for developer happiness." Including the closures and collection operations.
- riffraff 4mo ago"Some may say Ruby is a bad rip-off of Lisp or Smalltalk, and I admit that. But it is nicer to ordinary people." (Matz speaking at the LL2 conference some 20+ years ago)
- 0xpgm 4mo agoFrom the article > Matz has said as much. He’s described Ruby’s design as starting from a simple Lisp, stripping out macros and s-expressions, then adding an object system, blocks, and Smalltalk-style methods. The features most Rubyists fall in love with aren’t the object-oriented ones. They’re the functional ones, dressed in friendlier clothes.
- wglb 4mo agoBut macros and s-expressions are two of my favorites parts of lisp!
- dismalaf 4mo agoFunny enough Lisp was originally meant to be written in a higher level syntax (with infix operators and everything). But yeah, macros and S-expressions make it easier to write your own DSLs.
- pjmlp 4mo agoWith decades later, Dylan and Julia becoming the only ones that kind of managed to get some adoption doing it. For better or worse, parenthesis aren't that bad with the proper IDE tooling.
- to11mtm 4mo ago> For better or worse, parenthesis aren't that bad with the proper IDE tooling. Hell, even without [0], you can at least count the parenthesis by hand in a pinch. I remember seeing lots of crazy-awesome stuff done in AutoLisp by 'non-programmers', versus 'structure as spacing' in Python which really sucks if the Editor was designed to use the system default (probably non-monospaced, cause other products in the industry had dialogs that broke if you switched to a monospaced) font. [1] [0] - but real talk parenthesis matching in an editor is a lifesaver [1] - oooooold version of a very popular GIS product.
- p_l 4mo agoMatz directly credits Lisp (through Emacs Lisp) as influence in the design of Ruby and its runtime, with Smalltalk influence on the language itself, and IIRC Perl as "what was popular and we tried to replace"
- draegtun 4mo agoThe article doesn't mention Perl at all but it did have some direct influences on Ruby. Even Ruby's trailing blocks syntax are an homage to Perl's block list subroutines: # first Ruby example in article users.select { |u| u.admin? }.map(&:email) # using Perl's block list map {$_->email} grep {$_->is_admin} @users;
- tug2024 4mo ago[dead]
- DonHopkins 4mo agoWhat have the Lisps ever done for us? https://www.youtube.com/watch?v=Qc7HmhrgTuQ https://www.youtube.com/watch?v=Qc7HmhrgTuQ
- BoingBoomTschak 4mo agoAlways fun to remind grugs that LISP invented "if" and GC.
- dismalaf 4mo agoI love Ruby, use it for most of my projects that don't require performance. Nothing I would love more than a Ruby with a Common-Lisp like compiler and runtime. Unboxed types, native compilation, partial compilation, live image (Ruby has this but "faster Rubies" like Crystal don't), etc...
- rjsw 4mo ago... or just use Common Lisp.
- dismalaf 4mo agoWhich is what I do. One can dream though right? Of a world where Ruby stayed just a tad more Lisp-y and less Perl/C/Smalltalk/Unix-y. Also I'm working on a DSL/Macros that give me more Ruby-esque quality of life things in Lisp.
- ralphc 4mo agoCommon Lisp, and even more so Racket, has reader macros. With a little help from LLMs you might be able to get a Ruby-like language that translates into Lisp. As a last resort look at Racket's "Rhombus" language, it's basically an infix, Python-like syntax on top of Racket. You can use that or see how they pull it off and add Ruby constructs to it.
- tmtvl 4mo agoHave you checked out dieggsy's Whisper (<https://sr.ht/~dieggsy/whisper/ https://sr.ht/~dieggsy/whisper/>) yet? It's based on Arne Bab's Wisp (SRFI 119).
- vindarel 4mo agoand the newer Moonli for CL: https://moonli-lang.github.io/ https://moonli-lang.github.io/ (:
- Syzygies 4mo ago
- danlitt 4mo ago> He’s described Ruby’s design as starting from a simple Lisp, stripping out macros and s-expressions Put the macros back! It would be so cool!
- KerrAvon 4mo agoYou kind of don't need them in Ruby, because everything is a method or an object or a closure and you can dynamically create and alter those at runtime. That's why Ruby is really good for ad-hoc DSLs in ways that Rust and Swift really are not.
- yxhuvud 4mo agoCrystal don't have the dynamicity but has macros to get the next best thing. Most meta magic in Ruby in good code are done at startup anyhow so you don't miss out on that much. YMMV.
- bashkiddie 4mo ago> because everything is a method or an object or a closure well, except for pattern matching. That is just syntax.
- shawn_w 4mo agoPut the s-expressions back too.
- matheusmoreira 4mo agoMacros depend on homoiconicity which Ruby sacrificed in order to have familiar syntax.
- ameliaquining 4mo agoHomoiconicity makes macros slightly more syntactically elegant, but is not at all necessary. Rust has macros and isn't homoiconic at all.
- 4mo ago
- evw 4mo agoFor folks that want all of this plus macros (and a lot of other great things), check out Elixir.
- ashton314 4mo ago100% Elixir is much more a Lisp than Ruby is.
- to11mtm 4mo agoAgree that Elixir is closer to a Lisp than Ruby. Heck at least in my brain MLs are closer to a Lisp than Ruby...
- pluralmonad 4mo agoElixir has forever ruined me for other languages. Every new PL I dip my toe into gets measured against it. Jose and the core team seem to always land on the right decisions, or at least very good ones.
- jksmith 4mo agoNow that I'm out of the corporate tyranny and have my own company, I use lisp for everything. There's certain satisfaction in writing config files and persisting data directly in s-expressions. Any json requirements are triggered by exports to foreign systems.
- atcol 4mo agoWhich Lisp, out of interest?
- iLemming 4mo agoDoes it really matter? There's a point in every Lisper's life, a threshold after which the question becomes immaterial - you'd stop thinking about intricacies of whatever Lisp and focus on the platform specifics instead. Any given day I might program in three-four different Lisp dialects, e.g. Clojure/Clourescript, Fennel, Elisp, Janet, etc. and it practically feels like I'm using the same PL. While switching between TS and JS (same family) never feels even close - there's always some mental burden.
- arikrahman 4mo agoEven the Lisps have Lisps. Like Clojure with ClojureScript, CLR, ClojureDart, Jank... etc.
- slifin 4mo agoYes though they're trying to be effectively the same lisp I do love that I learnt Clojure once like 5-7 years ago and more and more dialects keep expanding the choice of runtime I can target
- arikrahman 4mo agoIt's the mustard seed that keeps growing! And without the fragmentation other PL's suffer from, which are reminiscent of the Tower of Babel, conversely.
- hyperrail 4mo agoOne way I find traditional Lisp style more painful for functional code than Ruby is that fully functional-style Lisp pushes me to read and write code the opposite way from how I think about it. In the author's example: orders .select { |o| o.placed_at > 1.week.ago } .group_by(&:customer_id) .transform_values { |group| group.sum(&:total) } the equivalent Lisp code would either be written in imperative style as multiple statements that each write to a temporary variable or (let) binding, or would look like this: (reduce #'+ (map (lambda (o) (getf o 'total)) ; this group_by replacement function ; might be written as hash-table code (my-group-by 'customer-id (remove-if-not (lambda (o) (> (getf o 'placed-at) (- (my-now) (* 60 60 24 7)))) orders)))) where I now have to read from bottom to top to understand the order of operations on the `orders` record set, even though when I wrote the code earlier, I "logically" thought from first operation to last when deciding which high-level operations to use in which order. Other imperative languages that support functional code either make you do things imperatively to get the "logical" ordering of functional operations like I feel Lisp pushes you to do, or they do something like Ruby where things can be chained left to right in a "single" statement even for operations that were not thought of ahead of time by the creators of opaque data structures you later need to operate on. (Everything is a user-extensible object like Ruby, unified function call syntax in D, extension methods in C#, or pipelines of structured objects in PowerShell.)
- evdubs 4mo agoThreading macros are nice, though, right? https://docs.racket-lang.org/threading/introduction.html https://docs.racket-lang.org/threading/introduction.html
- whartung 4mo agoThey're nice, but they're not the same thing. The threading macros are (as I understand it) pure sugar. Turning (-> (gather my-list) uppercase-list sort) into (sort (uppercase-list (gather my-list))). In contrast to, say, Java (I can't speak to the code above): List<Things> things = thingIds.stream() .map(model::findThing) .filter(Objects::nonNull) .toList(); These are streamed. This is pretty much a pipe structure, whereas the threading macros will create a lot of temporary copies of the data (I don't know if that's a universal truth). That is, if you're processing a 1000 items, say `gather` returns a 1000 items, that 1000 item list is passed to `uppercase-list` which return a new 1000 item list to feed to `sort` which returns another 1000 item list (assuming none of these are destructive). I wish CL had something like the Java streams (maybe it does).
- deleted 4mo ago[deleted]
- somewhereoutth 4mo agowas this before or after Lisp's epiphany for lexical binding?
- 0x3444ac53 4mo agoI've never been more thoroughly convinced that I would like ruby more than from this article. I'm currently stuck reaching for python a lot of the time (absolutely love it tbc), but maybe it's worth changing things up and trying to give ruby a shot. It was one of the first programming languages I was introduced to at 16 or so, but an older person that I looked up to told me it would get me stuck in "hobby coder land". He was wrong in so many ways, but even if he was right, I wanna have fun in my hobby code :)
- NuclearPM 4mo agoTbc?
- dmitris 4mo agoto be clear [IMO]
- 0x3444ac53 4mo agoCorrect.
- Kaliboy 4mo agoI've had one job in my life, still at the same company. (8 years). I applied cause the listing mentioned Python, and I was programming in Python at the time. Once I started they were like yeah we put that there to reach a broader public but we use Ruby (on Rails). So that's what I learned. I've just returned to Python via LLM's. I literally have not felt the need nor desire to use Python once I got used to writing Ruby.
- neilv 4mo ago> Both marks come from Scheme, where [...] Reminds me of an email I wish I still had. Circa 2000, I wrote that I was leaning towards moving to Scheme, for more rapid R&D work than I could do in Java. Some nice-sounding person I didn't know emailed me from Japan, to mention a language I hadn't heard of, called Ruby. I don't know whether the person was Yukihiro Matsumoto himself, but it's a small world.
- insumanth 4mo agoAs I read this, all of my favorite things about ruby compared to something like python were influenced by lisp. Ruby is a joy to program and it seems mostly due to design influence from lisp.
- muvlon 4mo agoMost of the points listed are hardly considered lispy anymore these days, Python also has most of these. Where Ruby's lisp lineage really shows is the fact that it's got Kernel#callcc, aka call with current continuation. It doesn't get any lispier than that!
- t0mpr1c3 4mo ago`callcc` was obsoleted about 10 years ago. I don't know if it has been removed yet. https://bugs.ruby-lang.org/issues/10548 https://bugs.ruby-lang.org/issues/10548