[HN Gopher] Ruby 3.4.0
       ___________________________________________________________________
        
       Ruby 3.4.0
        
       Author : aaronbrethorst
       Score  : 393 points
       Date   : 2024-12-25 06:40 UTC (1 days ago)
        
 (HTM) web link (www.ruby-lang.org)
 (TXT) w3m dump (www.ruby-lang.org)
        
       | omoikane wrote:
       | I am most excited about the parser change, previously discussed
       | here:
       | 
       | https://news.ycombinator.com/item?id=36310130 - Rewriting the
       | Ruby parser (2023-06-13, 176 comments)
       | 
       | I remember being taught to use yacc in our compiler course
       | because "writing it by hand is too hard". But looks like Ruby
       | joins the growing list of languages that have hand-written
       | parsers, apparently working with generated parsers turned out to
       | be even harder in the long run.
       | 
       | That said, replacing a ~16k line parse.y[1] with a 22k line
       | prism.c[2] is a pretty bold move.
       | 
       | [1] https://github.com/ruby/ruby/blob/master/parse.y
       | 
       | [2] https://github.com/ruby/prism/blob/main/src/prism.c
        
         | PittleyDunkin wrote:
         | I'm pretty sure the only reason people ever used parser
         | generators is that it allows a language that vaguely resembles
         | the formal description of the target language. I always found
         | them very confusing to write, confusing to debug, and much less
         | efficient than writing your own. It's actually pretty
         | straightforward once you get the tokenization and lookahead
         | working.
        
           | pests wrote:
           | Agreed. Parser generators are a magic black box. Parsing is
           | not too difficult, there is some actual computer science in
           | some spots, but I think parsing should be a core complacency
           | of a programming language to unlock full potential.
        
             | capitol_ wrote:
             | A very very long list of CVEs disagrees with that parsers
             | are "not too difficult".
        
               | supriyo-biswas wrote:
               | Binary format parsing != Programming language parsing.
        
               | Blackthorn wrote:
               | Binary formats are rarely context free.
        
               | PittleyDunkin wrote:
               | Agreed, but there are different things being prioritized
               | with each approach.
        
             | debo_ wrote:
             | "core complacency" was an excellent typo in the context of
             | this conversation.
        
               | emptiestplace wrote:
               | It's rather compelling even without the context. :(
        
         | psychoslave wrote:
         | Number of line is as any metrics, it gives you a quick idea of
         | some amount, and that's it. To start having a sense of what it
         | means, you need to be more acquainted with the topic at end.
         | 
         | It's not that uncommon to have an implementation with code that
         | is lengthier but with an obvious pattern, while the smarter
         | compressed implementation whose understanding is not necessary
         | trivial to grab even for people seasoned to metaprogramming,
         | reflexivity and so on.
         | 
         | Not to say that is what happen here, the point here was to
         | recall that number of lines is not an absolute linear metrics.
        
         | IshKebab wrote:
         | It's not a "growing list" - the vast majority of languages use
         | hand-written parsers.
        
         | viraptor wrote:
         | It seems like you're ignoring the context/environment. Ruby has
         | enough advanced developers, large enough test suite and enough
         | people who care about performance, that it can tackle the
         | parser as a longer project regardless of its complexity. The
         | same thing will apply to other popular languages. But it won't
         | apply to smaller projects with very localised parser use. In
         | those cases writing anything custom would be a waste of time
         | (and potential introduce bugs solved years ago in generators).
        
           | lolinder wrote:
           | Having tried both on solo projects, I disagree: like other
           | commenters here, I've found parser generators to be a big
           | waste of time.
           | 
           | Writing a parser by hand requires understanding the theory of
           | parsing and understanding your implementation language.
           | Writing a parser with a parser generator requires
           | understanding the theory of parsing, your implementation
           | language, and a gigantic black box that tries unsuccessfully
           | to abstract away the theory of parsing.
           | 
           | The time spent learning and troubleshooting the black box is
           | almost always better spent putting together your own simple
           | set of helper methods for writing a parser and then using
           | them to write your own. The final result ends up being far
           | easier to maintain than the version where you pull in a
           | generator as a dependency.
        
             | plranw wrote:
             | The big plus of parser generators is that they report
             | ambiguities. Handling conflicts is a pain but explicit.
             | 
             | Do people who write predictive recursive descent parsers
             | (LL(k)) really calculate first/follow sets by hand? What if
             | the grammar requires backtracking?
        
               | lolinder wrote:
               | There's nothing to stop you from writing out a grammar in
               | some form that is intelligible to a verification tool and
               | then implementing the grammar by hand. I almost always
               | write out the grammar anyway because that's the design--
               | without it I'm flying blind. The cost of the generator
               | isn't writing out the grammar, it's in using the runtime
               | code it generates, which is optional even if you want to
               | use it for verification.
        
               | int_19h wrote:
               | Arbitrary backtracking in a recursive descent parser is
               | very easy with exceptions.
               | 
               | However, there's also an argument here that if the
               | grammar is too complicated to be parsed with recursive
               | descent, it's probably just too complicated in general
               | and should be simplified if possible. Obviously you don't
               | always have this option when you're dealing with an
               | external grammar, but for your own PL, you can design
               | around that. Most Wirth's languages are good examples;
               | Pascal is famously LL(1).
        
               | haberman wrote:
               | Recursive descent parsers can have ambiguities, but like
               | PEGs, they just resolve the ambiguity by arbitrarily
               | picking one of the alternatives.
               | 
               | A famous example is ALGOL 60, which had the dangling else
               | ambiguity (https://en.wikipedia.org/wiki/Dangling_else),
               | but this was not discovered until the language had
               | already been published. If they had been using a parser
               | generator tool, it would have warned them that the
               | grammar was not LL or LR.
               | 
               | Overall I do still prefer hand-written recursive descent
               | parsers, but I do find this to be one of the biggest
               | downsides of not using parser generators.
        
               | fanf2 wrote:
               | Of course the Algol 60 committee could not have used a
               | parser generator tool because they were not invented
               | until later in the 1960s, but your point is valid for
               | anyone developing a language after that time.
        
             | wenc wrote:
             | Parser generators handle a lot of edge cases for you and
             | are battle tested.
             | 
             | Unless I had a relatively simple grammar or had very strict
             | performance requirements (like in the case of Ruby), I
             | would not trust a hand rolled parser on a CFG by someone
             | who isn't dedicated to the craft. (PEGs are simpler so
             | maybe).
             | 
             | I've written recursive descent parsers by hand and they
             | look very simple until you have to deal with ambiguous
             | cases.
        
           | ljm wrote:
           | Ruby's syntax is also not trivial to parse and isn't set in
           | stone either. At some point it was simply decided that trying
           | to maintain the status quo was worse than attempting a
           | rewrite which could bring in some extra gains, either through
           | performance or having an easier time tweaking the grammar.
        
         | badsectoracula wrote:
         | > I remember being taught to use yacc in our compiler course
         | because "writing it by hand is too hard". But looks like Ruby
         | joins the growing list of languages that have hand-written
         | parsers, apparently working with generated parsers turned out
         | to be even harder in the long run.
         | 
         | I've been writing parsers for simple (and sometimes not so
         | simple) languages ever since i was in middle school and learned
         | about recursive descent parsing from a book (i didn't knew it
         | was called like that back then, the book had a section on
         | writing an expression parser and i just kept adding stuff) -
         | that was in the 90s.
         | 
         | I wonder why yacc, etc were made in the first place since to me
         | they always felt more complicated and awkward to work with than
         | writing a simple recursive descent parser that works with the
         | parsed text or builds whatever structure you want.
         | 
         | Was it resource constraints that by the 90s didn't really exist
         | anymore but their need in previous decades ended up shaping how
         | parsers were meant to be written?
        
           | junek wrote:
           | My hot take is that the allure of parser-generators is mostly
           | academic. If you're designing a language it's good practice
           | to write out a formal grammar for it, and then it feels like
           | it should be possible to just feed that grammar to a program
           | and have it spit out a fully functional parser.
           | 
           | In practice, parser generators are always at least a little
           | disappointing, but that nagging feeling that it _should_ work
           | remains.
           | 
           | Edit: also the other sense of academic, if you have to teach
           | students how to do parsing, and need to teach formal grammar,
           | then getting two birds with one stone is very appealing.
        
             | zelphirkalt wrote:
             | It is not academic. It is very practical to actually have a
             | grammar and thus the possibility to use any language that
             | has a perser generator. It is very annoying to have a great
             | format, but no parser and no official grammar for the
             | format available and being stuck with whatever tooling
             | exists, because you would have to come up with a completely
             | new grammar to implement a parser.
        
               | junek wrote:
               | > It is very practical to actually have a grammar
               | 
               | I fully agree that you need to have a grammar for your
               | language.
               | 
               | > and thus the possibility to use any language that has a
               | perser generator.
               | 
               | See, this is where it falls down in my experience. You
               | can't just feed "the grammar" straight into each
               | generator, and you need to account for the quirks of each
               | generator anyway. So the practical, idk, "reusability"...
               | is much lower than it seems like it should be.
               | 
               | If you could actually just write your grammar once and
               | feed it to any parser generator and have it actually work
               | then that would be cool. I just don't think it works out
               | that way in practice.
        
           | majewsky wrote:
           | Parser generators will tell you whether the grammar given to
           | it is well-formed (according to whatever criteria the parser
           | generator uses).
           | 
           | When hand-rolling a parser, there could be accidental
           | ambiguities in the definition of your grammar, which you
           | don't notice because the recursive descent parser just takes
           | whatever possibility happened to be checked first in your
           | particular implementation.
           | 
           | When that happens, future or alternative implementations will
           | be harder to create because they need to be bug-for-bug
           | compatible with whatever choice the reference implementation
           | takes for those obscure edge cases.
        
             | xigoi wrote:
             | > When hand-rolling a parser, there could be accidental
             | ambiguities in the definition of your grammar, which you
             | don't notice because the recursive descent parser just
             | takes whatever possibility happened to be checked first in
             | your particular implementation.
             | 
             | Is that a problem? Just use a grammar formalism with
             | ordered choice.
        
         | zelphirkalt wrote:
         | I can only imagine working with generated parsers to become
         | more difficult, if the syntax of a language is highly ad-hoc or
         | irregular, not elegant like concattenative, or lispy languages,
         | or Smalltalk style, which is ironic, given Ruby's history.
         | Maybe they added too many bells and whistles.
         | 
         | In every other case having a grammar in form of parser
         | generator macros should be better and preferrred, since it is
         | well portable to other languages and tools and lends itself to
         | be more readable (with good naming).
        
         | jjice wrote:
         | Good error reporting gets really tricky with generated parsers.
         | That said, it can be a nice time saver for smaller things like
         | DSLs and languages early on.
         | 
         | Even then, yacc and bison are pretty solid overall. I believe
         | Postgres still uses a yacc grammar today, as another high
         | profile example. I'd arguebthr parsing of SQL is one or the
         | least interesting thi.gs an RDBMS does, though.
        
           | ljm wrote:
           | To reinforce your point on good error reporting, though, SQL
           | errors are notoriously unhelpful.
           | 
           | "Yeah there's an unbalanced parentheses...somewhere near this
           | point... might actually be unbalanced, or you missed a comma
           | or semicolon. You tell me."
        
       | ciconia wrote:
       | Ruby is getting more and more awesome these last few years,
       | especially when it comes to performance. Since 3.3 I've been
       | running all my apps with --yjit, it makes a tremendous
       | difference!
        
         | Alifatisk wrote:
         | Wait until you hear about TruffleRuby
        
           | phoronixrly wrote:
           | Thanks, but no thanks. Never touching anything by oracle.
        
             | Alifatisk wrote:
             | No wait, I know Oracle has a bad rep which is deserved, but
             | TruffleRuby and GraalVM is truly open-source, not open-
             | core. They actually did something great this time.
             | 
             | Someone pointed this out
             | https://news.ycombinator.com/item?id=42323293
        
               | tekknolagi wrote:
               | GraalVM tends toward open core. They have entire test
               | suites and test tools that are internal-only that make
               | developing it kind of difficult.
        
               | phoronixrly wrote:
               | > You will need to sign the Oracle Contributor Agreement
               | (using an online form) for us to able to review and merge
               | your work.
               | 
               | Read my lips:
               | 
               | N. O.
               | 
               | Read the CLA. This is a trap, do not get yourself or your
               | company caught in it. It is open-source for now, until it
               | gets enough traction. Then the rug will be pulled, the
               | code will be relicensed as well as any further
               | development or contributions.
               | 
               | This is _insane_ , I cannot believe anyone can read and
               | understand this and not consider the abuses of power it
               | allows:
               | 
               | > 2. With respect to any worldwide copyrights, or
               | copyright applications and registrations, in your
               | contribution:
               | 
               | > ...
               | 
               | > you agree that each of us can do all things in relation
               | to your contribution as if each of us were the sole
               | owners, and if one of us makes a derivative work of your
               | contribution, the one who makes the derivative work (or
               | has it made) _will be the sole owner of that derivative
               | work_ ;
               | 
               | > you agree that you _will not assert any moral rights in
               | your contribution against us_ , our licensees or
               | transferees;
               | 
               | > you agree that _we may register a copyright in your
               | contribution and exercise all ownership rights associated
               | with it_ ; and
               | 
               | > you agree that neither of us has _any duty to consult
               | with, obtain the consent of, pay or render an accounting
               | to the other for any use_ or distribution of your
               | contribution.
               | 
               | I would go as far as to state that anyone who contributes
               | any code to this works _against_ open source (by helping
               | out an obvious rugpull /embrace-extend-extinguish scheme
               | that diverts adoption and contribution from cruby/jruby)
               | and _against_ their fellow developers (by working _for
               | free_ for Oracle).
        
               | ksec wrote:
               | I mean Java and MySQL are from Oracle as well.
        
               | phoronixrly wrote:
               | MySQL was forked and the fork is the defacto standard
               | shipped by linux distros. To me the only MySQL that
               | existed was the one by Sun, now MariaDB has completely
               | succeeded it.
               | 
               | Do you see the licensing/distrubution clusterfuck with
               | Java as a good example of open-source stewardship by
               | Oracle? Which Java disto are you using?[1]
               | 
               | Do you see the Google v. Oracle Java API copyright case
               | as a good example of open-source stewardship by Oracle?
               | 
               | You know what else is prudently (/s) stewarded by Oracle?
               | ZFS. That is why it is _still_ not a part of the Linux
               | kernel. A company that is basically a meme with the
               | amount of lawyers it imploys would easily find a safe way
               | to allow integration into the Linux kernel if only they
               | wanted to contribute.
               | 
               | The examples above show _exactly_ why Oracle has a
               | decidedly bad reputation. On top of that, their CLA
               | enshrines their shit treatment of the open-source
               | movement and their free slave labour^W^W^W open-source
               | contributors.
               | 
               | [1] https://en.wikipedia.org/wiki/OpenJDK#OpenJDK_builds
        
               | pjmlp wrote:
               | > Do you see the Google v. Oracle Java API copyright case
               | as a good example of open-source stewardship by Oracle?
               | 
               | 100% YES, given the clusterfuck support of standard Java
               | on Android.
               | 
               | It is no different from what Microsoft has made with J++
               | on Windows, and like they came up with .NET, Google came
               | up with Kotlin migration, ironically they keep relying on
               | the standard Java that they don't support, for InteliJ,
               | Gradle, and everything else that powers Android SDK on
               | the desktop.
               | 
               | Google could have avoided the lawsuit if they bought Sun,
               | after torpedoing it with Android, they thought no one
               | would buy the company and were safe from paying anyone,
               | wrong call.
        
               | Alifatisk wrote:
               | Oh wow! Thanks for the clarification! Is the case same
               | with JRuby?
        
               | phoronixrly wrote:
               | JRuby -- no CLA.
               | 
               | Java is problematic though. See my other comment.
        
               | psychoslave wrote:
               | For what it worth, in France so called moral rights are
               | "innalienables", so you legally can't get rid of them,
               | and I wouldn't be surprised this holds in most Roman
               | civil law countries (most countries in the world). Just
               | like you can't decide to get rid of all your civil rights
               | and become a slave of the nice company that promised to
               | treat you well and free you of the hurdle to take
               | decisions by yourself. So IANAL but this contract is not
               | only ignominious but is actually trying to require
               | authors to make promises that they can not legally make.
               | 
               | https://en.m.wikipedia.org/wiki/Civil_law_(legal_system)
        
               | lakomen wrote:
               | Thank you. Never trust Oracle, ever. They will betray
               | you.
        
               | lmm wrote:
               | That's completely normal for cathedral-style open source
               | development. The FSF themselves required copyright
               | assignment (not just a CLA) if you wanted to contribute
               | to GNU projects (e.g. GCC) for many years; several GNU
               | projects still do.
               | 
               | You only need to sign the CLA if you want to contribute
               | to upstream, you can maintain your own fork if you want,
               | and the code that is open source today will always be
               | open source. Frankly I'd say Oracle is less likely to
               | close it up in a scramble to try to monetise their open-
               | source assets than smaller companies like Redis Labs -
               | Oracle has plenty of products and makes their money from
               | consulting rather than from selling code directly.
        
               | phoronixrly wrote:
               | How can you compare the FLA with Oracle's CLA??? From the
               | FSFA:
               | 
               | > An FLA offers a special clause against this kind of
               | situation, in order to protect the Free Software project
               | against potentially malicious intentions of the Trustee.
               | According to this provision, if the Trustee acts against
               | the principles of Free Software, all granted rights and
               | licences return to their original owners. That means that
               | the Trustee will be effectively prevented from continuing
               | any activity which is contrary to the principles of Free
               | Software.
               | 
               | You can name a few more rugpulls made possible by
               | contributor agreements that permitted blatant abuse of
               | power, and Oracle is also not innocent in this. Off the
               | top of my head I remember the VirtualBox extensions
               | fiasco. Oracle changed the license then started sending
               | bills to companies.
        
       | evjan wrote:
       | 'it' is a welcome addition!
        
         | ciconia wrote:
         | Don't say that word!
         | 
         | https://www.youtube.com/watch?v=RZvsGdJP3ng
        
         | ilvez wrote:
         | Truly is, much nicer than that lonely `_1`
        
           | rubyfan wrote:
           | _2 can be as bad as _1
        
           | BoingBoomTschak wrote:
           | I'd have thought allowing _ as a synonym for _1 would have
           | been more aesthetically consistent. That's the path I went
           | with when designing my CL #l reader macro, personally.
        
         | JasserInicide wrote:
         | I don't understand the point of it when the `.map(&:upcase)`
         | syntax is shorter. This just seems like yet another syntactic
         | sugar Rubyism that doesn't really add anything.
         | 
         | If it's an alternative to the `|x|` syntax when using only one
         | block variable, then I like that.
        
           | graypegg wrote:
           | That only works when calling a method on the things you're
           | iterating thru, it is a replacement for the single variable
           | block example you gave there
        
           | Trasmatta wrote:
           | `arr.map { it.thing.blah.stuff }`
           | 
           | The `&:` doesn't work in that context
        
             | ilvez wrote:
             | Not to point any fingers, but shows that the previous
             | commenter have not struggled with this :)
             | 
             | &: is very nice, but not enough.
        
         | zachrose wrote:
         | Does `it` conflict with Rspec's `it`? Surely they've thought of
         | this, but to my eye it looks like it would get confusing.
        
           | prh8 wrote:
           | Nope it doesn't, they did take that into account during
           | development.
        
       | shortrounddev2 wrote:
       | What does ruby do well that other languages don't? What is the
       | niche it's trying to fill?
        
         | cyberpunk wrote:
         | It's a general purpose language with some very mature
         | frameworks.
         | 
         | I don't think it needs a niche. :)
        
         | speleding wrote:
         | It's the language with the highest ratio of (useful work /
         | LOC), so it's the least verbose language. This makes it very
         | suitable to write and understand complex scripts, because the
         | reduced boilerplate means less cognitive overhead for the
         | programmer. As a result, experienced programmers can be
         | extremely productive with it.
         | 
         | The well-known Rails framework uses this to great effect,
         | however, some people argue that the choice of "convention over
         | configuration" and extensive use of meta-programming,
         | derisively called "magic", make it less suitable for
         | inexperienced teams because they get too much rope to hang
         | themselves and the lack of explicitness starts working against
         | you if you're not careful.
        
           | continuational wrote:
           | Experienced teams love magic?
        
             | dochne wrote:
             | Experienced teams know to be careful and sparing with its
             | use.
        
             | psychoslave wrote:
             | It depends which kind of magic. Everybody love some magic
             | to be in its life, as long as it doesn't reveal to be a
             | curse unintentionally coming out from a good willing wish.
             | 
             | Also you don't want all and everything being the results of
             | spells you don't have a clue how they are cast.
        
           | nix-zarathustra wrote:
           | >It's the language with the highest ratio of (useful work /
           | LOC), so it's the least verbose language
           | 
           | Why doesn't clojure fit the bill here?
        
             | psychoslave wrote:
             | )))))))))))))))))
        
           | lucasoshiro wrote:
           | I see some people saying that Ruby is too much "magic", while
           | what is magic is Rails. Ruby itself can have its high useful
           | work / LoC ratio thanks to its syntax. For example, you can
           | spawn a thread with:
           | 
           | thread = Thread.new do # thread code end
           | 
           | ...
           | 
           | thread.join
           | 
           | In this example we can see that it's not magic, only concise.
           | 
           | I wrote more about it here:
           | https://news.ycombinator.com/item?id=40763640
        
             | Kwpolska wrote:
             | Creating a new thread is equally simple in Java:
             | var thread = new Thread(() -> {           // Thread code
             | });         thread.start();         // ...
             | thread.join();
        
               | speleding wrote:
               | Yes, but it's a good example of how Java is about twice
               | as verbose to do the same work. The Ruby version of that
               | can be written as simply:
               | 
               | Thread.new{ ... thread code ...}.join
               | 
               | The extra verboseness quickly adds up if every statement
               | takes twice as much code.
        
               | lucasoshiro wrote:
               | Fair. I must admit that I'm not aware of the recent
               | features of Java. Last time I really needed it was the
               | time that we needed to instance an anonymous class for
               | callbacks. I still find the block syntax in Ruby cleaner
               | though.
               | 
               | Kotlin is another language that has this Ruby-style
               | blocks for callbacks.
        
         | tyre wrote:
         | Not really a niche language. Fantastic web server development.
         | A more flexible and powerful language than python--the
         | metaprogramming can be ridiculously powerful (when done
         | well)--without the nonsense of white space sensitivity.
         | ActiveRecord is perhaps the best ORM out there. Rails has tons
         | of functionality to get running.
         | 
         | Overall, a pleasant and expressive language with an incredible
         | community. Python ends up "winning" because of pytorch +
         | pandas, but is (imo) a worse language to work in + with.
        
           | codesnik wrote:
           | ...but ruby is whitespace sensitive too. It's hard to notice,
           | because rules mostly follow intuition, but there're cases
           | when not only a missing newline, but absense or addition of a
           | space changes resulting syntax. Currently I remember only
           | difference in parsing unary vs binary operators, like + and
           | *, and ternary operator ? : vs : in symbols, but there're
           | certainly more other cases.
        
             | psychoslave wrote:
             | Sure, like `a ?b :c` is nothing like `a ? b : c` (I guess
             | the former is actually invalid), but that's obviously not
             | what the previous message was referring to when speaking of
             | Python which uses spaces as main facility to determine
             | block scope.
        
             | mdaniel wrote:
             | There was a recent thread about parsing Ruby wherein I
             | learned that the % quoting character accepts _any_
             | character following it as the opening /closing delimiter
             | <https://news.ycombinator.com/item?id=42032212> Crazypants.
        
         | t-writescode wrote:
         | Rails has some very, very good features that make standing up a
         | CRUD app with an administrative backend _very easy_.
         | 
         | It's also got a bunch of semi-functional-programming paradigms
         | throughout that make life quite a bit easier when you get used
         | to using them.
         | 
         | Honestly, if it had types by default and across all / most of
         | its packages easily (no. Sorbet + Rails is pain, or at least
         | was last I tried), I'd probably recommend it over a lot of
         | other languages.
        
           | FBISurveillance wrote:
           | I love Rails and spent a good chunk of my career using it -
           | and I'd recommend it more if only the frontend story wasn't
           | that bumpy over the years with all the variations of asset
           | pipelines.
           | 
           | I wish the TypeScript/React integration was easier. Say what
           | you will but there's no way you can achieve interactivity and
           | convenience of React (et al) UIs with Turbo/Hotwire in a
           | meaningful time.
        
             | block_dagger wrote:
             | Try React on Rails [1]. I've found it to be a very pleasant
             | development experience.
             | 
             | [1] https://github.com/shakacode/react_on_rails
        
             | jherdman wrote:
             | Agreed re asset pipelines. I definitely have Webpacker
             | related scar tissue.
             | 
             | Have you tried either Inertia
             | (https://github.com/inertiajs/inertia-rails) or vite-ruby
             | (https://vite-ruby.netlify.app/)? Both look very promising.
        
               | ysavir wrote:
               | I converted from webpacker (or rather shakapacker, the
               | continuation after rails moved away from webpacker) to
               | vite_rails recently, and it's been such a breath of fresh
               | air. It's easy to set up, and easier to maintain.
               | Strongly recommended.
        
             | TheSmoke wrote:
             | I definitely suggest using vite and the vite ruby gem.
             | Create your Rails app, Create your TS + React app with
             | vite, add the vite gem and done. It does not get better
             | than that. Super fantastic.
        
             | ajmurmann wrote:
             | Can you elaborate more in this? Years ago, I used to
             | primarily do Rails development. Recently I built some web
             | apps that use a JVM backend (one app uses Java & Spring and
             | the other Kotlin & Micronaut) and a React frontend. One
             | thing I ended up really missing issue the the frameworks,
             | especially with disjointed fronted, don't solve the
             | standard issue of a request sending an invalid form entry
             | and showing the validation errors on the form. I ended up
             | building my own implementation of that which of course also
             | requires a convention on message format. Since most apps
             | need to solve this it's so weird to be that frameworks
             | nowadays don't solve this out of the box.
        
           | viraptor wrote:
           | If you're happy to trade the ecosystem and a bit of
           | compilation speed for types, then Crystal is a perfectly
           | cromulent choice.
        
             | jbverschoor wrote:
             | Except it's not because:
             | 
             | 1) It has differences in behavior with certain classes and
             | is not a drop-in replacement.
             | 
             | 2) It _always_ compiles, so it 's kind of slow to compile-
             | test
        
               | viraptor wrote:
               | It's not a 100% compatible replacement, but I've ported a
               | few things with only trivial chances. I didn't say it's a
               | drop in, just that it's a fine choice.
               | 
               | Compile/test time is ok. It's a few extra seconds to run
               | tests, but hasn't been an issue in practice for me.
        
             | t-writescode wrote:
             | I've heard good things, yeah :)
             | 
             | I've tend to have found Kotlin to be the direction I'm more
             | happy going with. It speaks to my particular itches for me
             | personally, more effectively. I can absolutely see how it's
             | a very effective choice.
        
         | john_the_writer wrote:
         | It was a niche for a time, but now it's way more a general
         | purpose lang.
         | 
         | Where it shines now is in it's width and depth. There are
         | thousands of well documented libraries built by millions of
         | dev's.
         | 
         | If you want to do something; near anything, ruby has a gem for
         | it. It's power today is that it is omni.
        
         | nickserv wrote:
         | You'll need to learn it if you want to use Rails.
        
         | oezi wrote:
         | Ruby has the nicest object-oriented design (everything is an
         | object) outside of smalltalk (IMHO).
         | 
         | In contrast to the mess that is Python. For instance, in Ruby
         | it is natural that each or map are methods of Array or Hash
         | rather than global functions which receive an Array or Hash
         | argument.
         | 
         | This goes as far as having the not operator '!' as a method on
         | booleans:
         | 
         | false.! == true
         | 
         | Once you have understood it, it is a very beautiful language.
        
           | cyberpunk wrote:
           | It's very powerful though which is a bit terrifying. You can
           | literally monkey patch Object at runtime and add methods to
           | every single instantiated object! (I believe this is how
           | rspec works..)
           | 
           | Awesome, but with great power come great responsibility ;)
        
             | tuyiown wrote:
             | Actually, learning ruby is great way to see the light and
             | stop trying to be creative when writing code.
             | 
             | You end up feeling and steered to the the right idiomatic
             | way of doing things is the satisfying way.
        
             | codesnik wrote:
             | RSpec moved from that quite some time ago. Monkey patching
             | nowadays is usually frowned upon, even refinements, which
             | could simulate monkey patching in a limited scope, are
             | rarely used.
        
               | cyberpunk wrote:
               | Oh I'm extremely out of date, I was into ruby back when
               | Why's guide was a thing. Maybe I'll revisit it someday if
               | I ever get bored of go paying the rent.
        
           | psychoslave wrote:
           | Yes, but it is not fully OO. Something like `if.class`
           | generates an error, as opposed to returning some type such as
           | "Syncategoreme".
           | 
           | That might looks really anecdotal, but on practice for
           | example that's is probably the biggest obstacle to providing
           | fully localized version of Ruby for example.
           | 
           | The second biggest challenge to do so would probably be the
           | convention of using majuscule to mark a constant, which thus
           | requires a bicameral writing system. That is rather ironic
           | given that none of the three writing system of Japanese is
           | bicameral (looks fair to exclude romaniji here). Though this
           | can be somehow circumvented with tricks like
           | 
           | ``` # Define a global method dynamically
           | Object.send(:define_method, :lowercase_constant) do "This is
           | a constant-like value" end
           | 
           | # Usage puts lowercase_constant ```
        
           | int_19h wrote:
           | Everything is an object in Python, as well.
           | 
           | Stuff like map() is _generic_ iteration, over any structure
           | that exposes iteration. When it 's a member function, it
           | means that every collection has to implement map itself
           | basically. When it's separate, the collections only need to
           | provide the interface needed to iterate over it, and the
           | generic map() will just use that.
        
             | Maledictus wrote:
             | Still looks much less beautiful. Python feels to me like it
             | can't make up its mind.
        
               | int_19h wrote:
               | I'll take "properly generalized" over "looks beautiful"
               | any time. At the end of the day, the purpose of the code
               | is to do something, not to be pretty.
               | 
               | FWIW you can have both in this case; you just need to
               | make dotted method calls syntactic sugar for global
               | function invocations.
        
             | lucasoshiro wrote:
             | > over any structure that exposes iteration
             | 
             | Taking OOP more seriously, this kind of thing should be
             | implemented through inheritance, interfaces, mixins, etc.
             | Even though I've got used to it, Python has these
             | inconsistencies that sometimes it wants to be more OOP,
             | sometimes it wants to be more FP.
             | 
             | Ruby has chosen OOP as its size, and implements nicely
             | those functional operations as methods (same for Kotlin,
             | for example). That makes easy for composing them:
             | 
             | # Sum of the square of even elements of a list, in Ruby
             | 
             | my_list.filter{|x| x % 2 == 0}.map{|x| x * 2}.sum
             | 
             | Python could do something like that, but we quickly fall in
             | a parentheses hell:
             | 
             | # The same code, in Python
             | 
             | sum(map(lambda x: x * 2, filter(lambda x: x % 2 == 0,
             | my_list)))
             | 
             | Languages that have chosen the FP path more seriously
             | implement function composition. They could do the same way
             | as Python, but composition makes it more readable:
             | 
             | # The same code, in Haskell
             | 
             | sum . map (^ 2) . filter (\x -> x `mod` 2 == 0) $ my_list
             | 
             | PS: I know that I it would be better to use comprehensions
             | in both Python and Haskell, but these are general examples
        
               | int_19h wrote:
               | Kotlin is still rather different though in that it still
               | implements stuff like map and filter _outside_ of
               | specific collection classes. If you look at the
               | definition of, say, List, there 's no map & filter there,
               | only iterator. Instead, map & filter are defined as
               | extension functions that work on any Iterable.
               | 
               | So semantically it's actually closer to Python, with the
               | only difference that, since Python doesn't have extension
               | methods, it has to use global functions for this, while
               | Kotlin lets you pretend that those methods are actually
               | members. But this is pure syntactic sugar, not a semantic
               | difference.
        
         | Naru41 wrote:
         | As the name suggests, it's just a Perl alt... everyday chores,
         | data analysis, some automation tools.
        
         | vidarh wrote:
         | Being concise and pleasant to work with.
         | 
         | I wouldn't have had this much control of my own environment
         | with another language, so that all of these are pure Ruby:
         | 
         | - My window manager - My shell - My terminal, including the
         | font renderer. - My editor - My desktop manager
         | 
         | That's less than 10k lines of code. I've taken it a bit to the
         | extreme, but I wouldn't have had the time to if I had to fight
         | a more verbose language.
        
           | codesnik wrote:
           | huh. I'm not sure if I understood you right, do you script
           | and configure those in ruby, or have you written them in ruby
           | from scratch? Are the sources available to read/learn from?
        
             | vidarh wrote:
             | They're written in Ruby from scratch. Some are available,
             | e.g. the window manager is here:
             | 
             | https://github.com/vidarh/rubywm
             | 
             | Beware that one of the joys of writing these for my own use
             | is that I've only added the features I use, and fixed bugs
             | that matter to me, and "clean enough to be readable for me"
             | is very different from best practice for a bigger project.
             | 
             | I'm slowly extracting the things I'm willing to more
             | generally support into gems, though.
        
               | codesnik wrote:
               | thanks! I love ruby but I'd be afraid to do anything but
               | web backends and shell scripting with it. it's people
               | like you who move language adoption!
        
               | Maledictus wrote:
               | wow, thank you for publishing this!
        
               | lucasoshiro wrote:
               | Nice!
               | 
               | That's something that you could submit as a post here in
               | HN
        
               | vidarh wrote:
               | The wm was actually discussed on HN way back. I think
               | once some of my other projects, like the terminal, is a
               | bit more mature (it works _for me_ and I use it for 99%+
               | of my terminal needs) I might post those too.
               | 
               | The biggest issue with these projects is that I feel
               | uncomfortable pushing a few of them because I make a
               | living of providing development and devops work, and my
               | personal "only has to work on my machine and certain bugs
               | are fine to overlook" projects are very different to work
               | projects in how clean they are etc... But as I clean
               | things up so they're closer to meeting my standards for
               | publication I'll post more.
        
         | lucasoshiro wrote:
         | Ruby is something like a "improved" Python, with a better OO
         | system, a code block syntax that makes it easy to use
         | callbacks, more consistent standard libraries, etc. It could be
         | what Python is today.
         | 
         | I wouldn't say niche, but the killer app of Ruby is Rails, a
         | web framework similar to Django. In fact, many people treat
         | them as they are the same. But there are big projects that use
         | Ruby and that are not related to Rails. As far as I remember:
         | Metasploit, Homebrew, Vagrant and Jekyll.
         | 
         | Personally I think Ruby is amazing language for writing shell
         | scripts. I write a blog post about it, you can see it and its
         | discussion here: https://news.ycombinator.com/item?id=40763640
        
           | yyyyz wrote:
           | Can you name one way Ruby has parity with Python? Ruby is a
           | dead language that uses sponsored posts here. Nobody actually
           | uses this since like 2018 but some people are paid to hype it
           | up. Just look at the empty praise. No real applications
           | mentioned.
        
             | pawelduda wrote:
             | Yes, nothing real, just some githubs and shopifys
        
             | mpbart wrote:
             | The yearly ruby release announcement getting to the top of
             | hackernews every year certainly seems to imply that it's
             | not a dead language
        
             | latexr wrote:
             | > Nobody actually uses this since like 2018 but some people
             | are paid to hype it up.
             | 
             | What's the conspiracy theory here? Why would anyone be
             | paying people to hype Ruby? What could possibly be the end
             | goal?
        
               | empthought wrote:
               | > Why would anyone be paying people to hype Ruby? What
               | could possibly be the end goal?
               | 
               | Hiring increasingly disinterested junior devs.
        
         | phamilton wrote:
         | The language is incredibly flexible and allows for "DSLs" that
         | are just ruby libraries.
         | 
         | A simple example: `3.days.ago` is a very commonly used idiom in
         | Rails projects. Under the hood, it extends the base Number
         | class with `def days` to produce a duration and then extends
         | duration with `def ago` to apply the duration to the current
         | time.
         | 
         | Taking that concept to a bigger extreme is this mostly
         | unnecessary library: https://github.com/sshaw/yymmdd
         | 
         | `yyyy-mm-dd(datestr)` will parse a date str that matches yyyy-
         | mm-dd format. It looks like a special DSL, but it's just Ruby.
         | `dd(datestr)` produces a `DatePart`. Then it's just operator
         | overloading on subtraction to capture the rest of the format
         | and return the parsed date.
         | 
         | That library feels unnecessary, but the entire thing is 100
         | lines of code. The ease of bending the language to fit a use
         | case led to a very rich ecosystem. The challenge is consistency
         | and predictability, especially with a large team.
        
         | zem wrote:
         | it's by far the best language I've found for writing a quick
         | bit of code to explore a problem, or to do a one-off task.
         | perhaps something about it just fits the way my brain works,
         | but I find it incredibly easy to convert ideas to working ruby
         | without having to think too hard about "okay, how do I actually
         | express this in code".
        
         | nuancebydefault wrote:
         | If you write if 0... end around your code, it runs!
        
       | tuananh wrote:
       | Shopify strategy aka the story of YJIT
       | 
       | If I cannot refactor my services, I shall refactor Ruby instead.
        
         | FBISurveillance wrote:
         | Since when contributing back to the community is considered a
         | bad faith move?
        
           | t-writescode wrote:
           | That's certainly not what I get out of what they said.
           | 
           | Shopify has introduced a bunch of very nice improvements to
           | the usability of the Ruby language and their introductions
           | have been seen in a very positive light.
           | 
           | Also, I'm pretty sure both Shopify for Ruby and Facebook for
           | their custom PHP stuff are both considered good moves.
        
         | pjmlp wrote:
         | That has been the story of every dynamic language since
         | forever, thankfully the whole AI focus has made JITs finally
         | matter in CPython world as well.
         | 
         | Personally I have learnt this lesson back in 2000's, in the age
         | of AOLServer, Vignette, and our own Safelayer product. All
         | based on Apache, IIS and Tcl.
         | 
         | We were early adopters of .NET, when it was only available to
         | MSFT Partners and never again, using scripting languages
         | without compilers, for full blown applications.
         | 
         | Those learnings are the foundations of OutSystems, same ideas,
         | built with a powerful runtime, with the hindsight of our
         | experiences.
        
           | rapind wrote:
           | > Personally I have learnt this lesson back in 2000's, in the
           | age of AOLServer, Vignette, and our own Safelayer product.
           | All based on Apache, IIS and Tcl.
           | 
           | Woah, your mention of "Vignette" just brought back a flood of
           | memories I think my subconscious may have blocked out to save
           | my sanity.
        
           | Chetan496 wrote:
           | Hey, I have worked on the Outsystems platform. Developed some
           | applications. Do you work at Outsystems?
        
             | pjmlp wrote:
             | No, I worked with the founders at a previous startup,
             | Intervento, which became part of an EasyPhone acquisition,
             | which got later renamed into Altitude Software alongside
             | other acquisitions.
             | 
             | They eventually left and founded OutSystems with what we
             | learned since the Intervento days, OutSystems is of the
             | greatest startup stories in the Portuguese industry.
             | 
             | This was all during dotcom wave from the 2000's, instead I
             | left to CERN.
        
           | rat87 wrote:
           | What's a scripting language? Also I'm not sure for TCL
           | (https://news.ycombinator.com/item?id=24390937 claims it's
           | had a bytecode compiler since around 2000) but the main
           | python and Ruby implementations have compilers (compile to
           | bytecode then interpret the bytecode). Apparently ruby got an
           | optional (has to be enabled) jit compiler recently and python
           | has an experimental jit in the last release (3.13).
        
             | igouy wrote:
             | "... the distinguishing feature of interpreted languages is
             | not that they are not compiled, but that any eventual
             | compiler is part of the language runtime and that,
             | therefore, it is possible (and easy) to execute code
             | generated on the fly."
             | 
             | p57 https://www.lua.org/pil/#1ed
        
             | pjmlp wrote:
             | https://en.m.wikipedia.org/wiki/Scripting_language
        
           | zahlman wrote:
           | >thankfully the whole AI focus has made JITs finally matter
           | in CPython world as well.
           | 
           | Isn't most of the work in Python AI projects done in C or C++
           | extensions anyway?
        
             | pjmlp wrote:
             | Yes, but not everyone loves to have dual stack development,
             | I surely didn't, back in the Tcl days, eventually we ask
             | ourselves for how long.
        
               | nerdponx wrote:
               | That's not how it works in Python.
               | 
               | The C/C++ is shipped in the form of well-established
               | libraries like Numpy and PyTorch. Very few end users ever
               | interact with the C/C++ parts, except for specialists
               | with special requirements, and library contributors
               | themselves.
        
               | pjmlp wrote:
               | It is definitely how it works in Python.
               | 
               | As if there is nothing else to chose from regarding
               | Python performance issues and libraries used by folks.
               | 
               | Not everything is fashionable AI.
        
               | zahlman wrote:
               | Can you name specific "un-fashionable" AI projects that
               | are dependent on Python code for things that have any
               | significant performance impact, which are seeing
               | significant benefits from Python JIT implementations?
        
           | maccard wrote:
           | HHVM has raised its head.
        
             | pjmlp wrote:
             | Which happens to have a JIT compiler, and contributed to
             | standard PHP having one as well.
        
           | nerdponx wrote:
           | > AI
           | 
           | The push for Python performance and JIT compilation has
           | little to do with AI and more to do with Python's explosion
           | in adoption for backend server applications in the 2010s, as
           | well as the dedication of smaller projects like PyPy that
           | existed largely because it was possible to make them exist.
           | The ML/AI boom helped spread Python even farther and wider,
           | yes, but none of the core language performance improvements
           | are all that relevant for ML or AI.
           | 
           | As another commenter pointed out, the performance bottlenecks
           | in AI specifically have essentially to do with the CPython
           | runtime performance. The only exception is in the pre-
           | processing of very large text corpora, and that alone has
           | hardly been a blip on the radar of the people working on
           | CPython performance.
           | 
           | Moreover, most of the "Python performance" projects that do
           | sit closer to machine learning use cases (Cython-Numpy
           | integration, Numba, Nuitka) are more or less orthogonal to
           | the more recent push for Python interpreter performance.
           | 
           | Cython itself and MypyC are mainly relevant because they are
           | intended to be general-ish purpose performance boosters for
           | CPython, and in doing so helped fill the need for greater
           | performance in "hot and loopy" code such as network
           | protocols, linters, and iterators. Cython also acted as a
           | convenient glue layer for ad-hoc C library binding. But
           | neither project is all that closely related to AI _or_ to the
           | various JIT compilers that have arisen over the years.
        
             | pjmlp wrote:
             | Not at all, given Facebook and Microsoft involvement into
             | making CPython folks finally accept a JIT has to be part of
             | the story, coupled by NVidia and Intel work on GPU JIT DSLs
             | for Python.
        
         | neonsunset wrote:
         | During their black friday / cyber monday load peak, Shopify
         | averaged between ~0.85 and ~1.94 back-to-back RPS per CPU core.
         | Take from that what you will.
         | 
         | Reference: https://x.com/ShopifyEng/status/1863953413559472291
        
           | kstrauser wrote:
           | Ouch. I had no idea it was that much of a resource hog.
        
           | cristianbica wrote:
           | Obviously you meant for the whole infrastructure: ruby /
           | rails workers, Mysql, Kafka, whatever other stuff their app
           | needs (redis, memcache, etc), loadbalancers, infrastructure
           | monitoring, etc.
        
             | neonsunset wrote:
             | This is correct! I thought this was clear but I guess
             | not...
        
               | ksec wrote:
               | It is not because this is the first time I heard about
               | back to back RPS. Which when come to think of it isn't
               | too bad of a metric from a business POV.
               | 
               | We can also infer that into how much saving YJIT
               | provides. At this point Shopify is likely already getting
               | a return of investment from YJIT.
        
           | PhilippGille wrote:
           | You seem to imply that everything they run is Ruby, but
           | they're talking about 2.4 million CPU cores on their K8s
           | cluster, where maybe other stuff runs as well, like their
           | Kafka clusters [1] and Airflow [2]?
           | 
           | [1] https://shopify.engineering/running-apache-kafka-on-
           | kubernet...
           | 
           | [2] https://shopify.engineering/lessons-learned-apache-
           | airflow-s...
        
           | phoronixrly wrote:
           | Just to reiterate stuff said in the other comments because
           | your comment is maybe deliberately misrepresenting what was
           | said in the thread.
           | 
           | Their _entire_ cluster was 2.4 million CPU cores (without
           | more info on what the cores were). This includes not only
           | Ruby web applications that handle requests, but also _other
           | infrastructure_. Asynchronous processing, database servers,
           | message queue processing, data workflows etc, etc, etc. You
           | cannot run a back of the envelope calculation and say 0.85
           | requests per second per core and that is why they 're
           | optimising Ruby. While that might be the end result and a
           | commentary on contemporary software architecture as a whole,
           | it does not tell you much about the performance of the Ruby
           | part of the equation in isolation.
           | 
           | They had bursts of 280 million rpm (4.6 million rps) with
           | average of 2.8 million rps.
        
             | neonsunset wrote:
             | > It does not tell you much about the performance of the
             | Ruby part of the equation in isolation.
             | 
             | Indeed, it doesn't. However, it would be a fairly safe bet
             | to assume it was the slowest part of their architecture. I
             | keep wondering how the numbers would change if Ruby were to
             | be replaced with something else.
        
               | phoronixrly wrote:
               | Since we're insinuating, I bet you that Ruby is not their
               | chief bottleneck. You won't get much more RPS if you wait
               | on an SQL query or RPC/HTTP API call.
               | 
               | In my experience when you have a bottleneck in the actual
               | Ruby code (not speaking about n+1s or heavy SQL queries
               | or other IO), the code itself is written in such a way
               | that it would be slow in whichever language. Again, in my
               | experience this involves lots of (oft unnecessary)
               | allocations and slow data transformations.
               | 
               | Usually this is preceded by a slow heavy SQL query. You
               | fix the query and get a speed-up of 0.8 rps to 40 rps,
               | add a TODO entry "the following code needs to be
               | refactored" but you already ran out of estimation and
               | mark the issue as resolved. Couple of months later the
               | optimization allowed the resultset to grow and the new
               | bottleneck is memory use and the speed of the naive
               | algorithm and lack of appropriate data structures in the
               | data transformation step... Again in the same code you
               | diligently TODOed... Tell me how this is Ruby's fault.
               | 
               | Another example is one of the 'Oh we'll just introduce
               | Redis-backed cache to finally make use of shared caching
               | and alleviate the DB bottleneck'. Implementation and
               | validation took weeks. Finally all tests are green. The
               | test suite runs for half an hour longer. Issue was traced
               | to latency to the Redis server and starvation due to
               | locking between parallel workers. The task was quietly
               | shelved afterwards without ever hitting production or
               | being mentioned again in a prime example of learned
               | helplessness. If only we had used an actual real
               | programming language and not Ruby, we would not be
               | hitting this issue (/s)
               | 
               | I wish most performance problems would be solved by just
               | using a """fast language"""...
        
               | neonsunset wrote:
               | Here comes the "IO" excuse :)
               | 
               | Effective use of IO at such scale implies high-quality DB
               | driver accompanied by performant concurrent runtime that
               | can multiplex many outstanding IO requests over few
               | threads in parallel. This is significantly influenced by
               | the language of choice and particular patterns it
               | encourages with its libraries.
               | 
               | I can assure you - databases like MySQL are plenty fast
               | and e.g. single-row queries are more than likely to be
               | bottlenecked on Ruby's end.
               | 
               | > the code itself is written in such a way that it would
               | be slow in whichever language. Again, in my experience
               | this involves lots of (oft unnecessary) allocations and
               | slow data transformations.
               | 
               | Inefficient data transformations with high amount of
               | transient allocations will run at least 10 times faster
               | in many of the Ruby's alternatives. Good ORM
               | implementations will also be able to optimize the queries
               | or their API is likely to encourage more performance-
               | friendly choices.
               | 
               | > I wish most performance problems would be solved by
               | just using a """fast language"""...
               | 
               | Many testimonies on Rust do just that. A lot of it comes
               | down to particular choices Rust _forces_ you to make.
               | There is no free lunch or a magic bullet, but this also
               | replicates to languages which offer more productivity by
               | means of less decision fatigue heavy defaults that might
               | not be as performant in that particular scenario, but at
               | the same time don 't sacrifice it drastically either.
        
               | phoronixrly wrote:
               | > There comes the standard "IO" excuse :)
               | 
               | You know, if I was flame-baiting, I would go ahead and
               | say 'there goes the standard 'performance is more
               | important than actually shipping' comment. I won't and I
               | will address your notes even though unsubstantiated.
               | 
               | > Effective use of IO at such scale implies high-quality
               | DB driver accompanied by performant concurrent runtime
               | that can multiplex many outstanding IO requests over few
               | threads in parallel. This is significantly influenced by
               | the language of choice and particular patterns it
               | encourages with its libraries.
               | 
               | In my experience, the bottleneck is mostly on the 'far
               | side' of the IO from the app's PoV.
               | 
               | > I can assure you - databases like MySQL are plenty fast
               | and e.g. single-row queries are more than likely to be
               | bottlenecked on Ruby's end.
               | 
               | I can assure you, Ruby apps have no issues whatsoever
               | with single-row queries. Even if they did, the speed-up
               | would be at most constant if written in a faster
               | language.
               | 
               | > Inefficient data transformations with high amount of
               | transient allocations will run at least 10 times faster
               | in many of the Ruby's alternatives. Good ORM
               | implementations will also be able to optimize the queries
               | or their API is likely to encourage more performance-
               | friendly choices.
               | 
               | Or it could be o(n^2) times faster if you actually stop
               | writing shit code in the first place.
               | 
               | Good ORMs do not magically fix shit algorithms or DB
               | schema design. Rails' ORM does in fact point out common
               | mistakes like _trivial_ n+1 queries. It does not ask you
               | "Are you sure you want me to execute this query that seq
               | scans the ever-growing-but-currently-20-million-record
               | table to return 5000 records as a part of your artisanal
               | hand-crafted n+1 masterpiece(of shit) for you to then
               | proceed to manually cross-reference and transform and
               | then finally serialise as JSON just to go ahead and blame
               | the JSON lib (which is in C btw) for the slowness".
               | 
               | > Many testimonies on Rust do just that. A lot of it
               | comes down to particular choices Rust forces you to make.
               | There is no free lunch or magic bullet, but this also
               | replicates to languages which offer more productivity by
               | means of less decision fatigue heavy defaults that might
               | not be as performant in that particular scenario, but at
               | the same time don't sacrifice it drastically either.
               | 
               | I am by no means going to dunk on Rust as you do on Ruby
               | as I've just toyed with it, however I doubt that I could
               | right now make the performance/productivity trade-off in
               | Rust's favour for any new non-trivial web application.
               | 
               | To summarise, my points were that whatever language you
               | write in, if you have IO you will be from the get go or
               | later bottlenecked by IO and this is the best case. The
               | realistic case is that you will not ever scale enough for
               | any of this to matter. Even if you do you will be
               | bottlenecked by your own shit code and/or shit
               | architectural decisions far before even IO; both of these
               | are also language-agnostic.
        
               | ljm wrote:
               | Shopify invest heavily in Ruby and write plenty of stuff
               | in lower level languages where they need to squeeze out
               | that performance. They were heavily involved in Ruby's
               | new JIT architecture and invested in building their own
               | tooling to try and make Ruby act more like a static
               | language (Sorbet, Bootsnap).
               | 
               | Runtime performance is just one part of a complex
               | equation in a tech stack. It's actually a safe bet that
               | their Ruby stack is pretty fucking solid because they've
               | invested in that, and hiring ruby and JS engineers is
               | still 1000x easier than hiring a C++ or Rust expert to do
               | basic CRUD APIs.
        
         | htunnicliff wrote:
         | For a stranger to the Ruby ecosystem, what are the benefits of
         | YJIT?
        
           | Malp wrote:
           | Just-in-time compilation of Ruby allowing you to elide a lot
           | of the overhead of dynamic language features + executing
           | optimized machine code instead of running in the VM /
           | bytecode interpreter.
           | 
           | For example, doing some loop unrolling for a piece of code
           | with a known & small-enough fixed-size iteration. As another
           | example, doing away with some dynamic dispatch / method
           | lookup for a call site, or inlining methods - especially
           | handy given Ruby's first class support for dynamic code
           | generation, execution, redefinition (monkey patching).
           | 
           | From https://railsatscale.com/2023-12-04-ruby-3-3-s-yjit-
           | faster-w...,
           | 
           | > In particular, YJIT is now able to better handle calls with
           | splats as well as optional parameters, it's able to compile
           | exception handlers, and it can handle megamorphic call sites
           | and instance variable accesses without falling back to the
           | interpreter.
           | 
           | > We've also implemented specialized inlined primitives for
           | certain core method calls such as Integer#!=, String#!=,
           | Kernel#block_given?, Kernel#is_a?, Kernel#instance_of?,
           | Module#===, and more. It also inlines trivial Ruby methods
           | that only return a constant value such as #blank? and
           | specialized #present? from Rails. These can now be used
           | without needing to perform expensive method calls in most
           | cases.
        
           | weaksauce wrote:
           | it makes ruby code faster than c ruby code so they are moving
           | toward rewriting a lot of the core ruby stuff in ruby to take
           | advantage of it. run time performance enhancing makes the
           | language much faster.
        
           | dismalaf wrote:
           | Same as the benefits of JIT compilers for any dynamic
           | language; makes a lot of things faster without changing your
           | code, by turning hot paths into natively compiled code.
        
         | janice1999 wrote:
         | Classic story. Didn't Dropbox do the same for Python? ANd
         | Facebook for PHP (and then forked it)?
        
           | tuananh wrote:
           | Roblox did the same with luau https://luau.org/performance
        
           | rurban wrote:
           | And cPanel for perl
        
       | thdhhghgbhy wrote:
       | Why did NodeJS take off on the backend while Rails was still
       | popular? I'll never understand it.
        
         | fastball wrote:
         | Using the same language to write your frontend and backend is
         | desirable for many people / teams.
        
           | t-writescode wrote:
           | To add, front-end developers and other people that learned in
           | Javascript (because a web browser is something everyone has,
           | turns out it's a pretty great runtime environment, has live
           | editing with dev tools, etc. It's honestly a fantastic way to
           | 'get into programming) could write the icky backend code to
           | make their slick websites, SPAs and games have internet-based
           | savestate
        
           | malthaus wrote:
           | but why does that language have to be one as braindead as
           | javascript. path-dependency is the root of all evil.
        
             | fastball wrote:
             | Because nobody championed another language for the browser.
             | 
             | Good news is we have WASM now, so you can write backend and
             | frontend code in basically whatever language you want.
        
         | briandear wrote:
         | Because of the JavaScript Everywhere crowd. When you have a
         | hammer, everything looks like a problem for JavaScript.
        
           | psychoslave wrote:
           | To be fair, js interpreters are available out of the box in
           | all digital devices out there that embed a browser. That's a
           | huge deal, as far as portability is concerned.
           | 
           | That said you do have things like https://opalrb.com/
        
           | wiseowise wrote:
           | God forbid we reuse knowledge instead of drudging lives
           | through never ending learning of same concepts with different
           | syntax's and 10x costs for supporting every special native
           | snowflake toolchain.
        
             | ericb wrote:
             | If that's the goal, the problem itself has been re-
             | implemented by the Javascript ecosystem.
        
             | xigoi wrote:
             | That's why you use a language where the build tool of
             | choice changes every month?
        
             | blandflakes wrote:
             | And of course the right way to do that is to take an
             | extremely mediocre, rushed, incomplete language that is
             | currently constrained to the browser, and make it run
             | everywhere else, ironically having to reinvent many wheels
             | and re-learn very old lessons the hard way along the way.
             | Mission "reuse knowledge" is a hearty failure in node.js-
             | land.
        
             | never_inline wrote:
             | > knowledge
        
         | zarzavat wrote:
         | Google hired all the best JIT engineers and set them to work on
         | v8. If you want better performance you'd have to choose an AOT
         | compiled language.
        
           | Lio wrote:
           | That seems like a meme from 10 years ago. I don't think
           | that's really true anymore is it?
           | 
           | I mean Truffle Ruby is as fast as V8 already and MRI yJIT and
           | jRuby are catching up fast.
           | 
           | It could also be argued that JVM is the gold standard JIT.
           | 
           | I think that shows that Google doesn't have a monopoly on
           | great JIT engineers.
        
             | masklinn wrote:
             | > I mean Truffle Ruby is as fast as V8 already
             | 
             | v8 and node are 15 years old. That's when this actually
             | mattered and js on the backend took off.
        
             | attractivechaos wrote:
             | > _Truffle Ruby is as fast as V8 already and MRI yJIT and
             | jRuby are catching up fast_
             | 
             | According to which benchmark? At my hand [1], node is ~60%
             | faster than TruffleRuby and over an order of magnitude
             | faster than yjit v3.3.0.
             | 
             | [1] https://github.com/attractivechaos/plb2?tab=readme-ov-
             | file#a...
        
           | neonsunset wrote:
           | OpenJDK HotSpot and .NET RyuJIT both produce much faster code
           | :)
           | 
           | And the latter lets you operate on the same level of
           | abstraction as Rust and C++ compilers do.
        
             | dismalaf wrote:
             | > OpenJDK HotSpot and .NET RyuJIT both produce much faster
             | code :)
             | 
             | For dynamic languages? Stuff like Clojure, JRuby, Boo, are
             | definitely not faster than V8 JavaScript...
        
           | petre wrote:
           | Google also made Dart which is better than Js in every
           | regard.
        
         | Tainnor wrote:
         | nonblocking IO
        
         | ninkendo wrote:
         | People say frontend/backend parity, and that's true, but I also
         | remember there was a time in 2011 or so where single
         | thread/async was this new hot thing.
         | 
         | Nginx was starting to get popular and overtake Apache on
         | installs, and people were enamored with its performance and
         | idea of "no blocking, ever" and "callbacks for everything",
         | which the nginx codebase sorta takes to the extreme. The c10k
         | problem and all that.
         | 
         | When JavaScript got a good engine in v8, Node was lauded as
         | this way to do what nginx was doing, but automatically and by
         | default: you simply couldn't write blocking code so waiting on
         | I/O will never bottleneck your incoming connections. Maximum
         | concurrency because your web server could go right back to
         | serving the next request concurrently while any I/O was
         | happening. But no "real" multithreading so you didn't have to
         | worry about mutexes or anything. I remember being _slightly_
         | jealous of that as a Rails developer, because webrick
         | /unicorn/etc had a worker pool and every worker could only
         | handle one request at a time, and fixing that could only happen
         | if everything was async, which it basically wasn't.
         | 
         | JavaScript becoming a popular language in its own right due to
         | frontend was certainly the most important factor, but it wasn't
         | the only one.
        
           | loloquwowndueo wrote:
           | "Node makes it impossible to write blocking code" reminds me
           | of this classic and hilarious piece by Ted Dziuba:
           | 
           | http://widgetsandshit.com/teddziuba/2011/10/node-js-is-
           | cance...
        
             | petre wrote:
             | Heh, he's so right in every regard although I use Node.
             | 
             | Worst of all, they made npm packages dead easy, so most of
             | them don't even have a readme file, not to mention inline
             | docs like POD or RDoc. This is how you end up with spam
             | pacakges, malware in npm and lpad disasters.
        
               | Vaguely2178 wrote:
               | > most of them don't even have a readme file
               | 
               | Given the popularity of Github, and the fact that a
               | readme file is the first thing you see when pulling up a
               | project on Github, most projects these days do in fact
               | have readme files.
               | 
               | > inline docs like POD or RDoc
               | 
               | JSDoc is relatively popular.
        
             | Vaguely2178 wrote:
             | Not sure why this is considered a "classic" piece. It reads
             | as if the author has just discovered the difference between
             | preemptive vs cooperative scheduling, but hasn't yet found
             | the words to describe his "discovery". Yes, you can write a
             | `while(true){}` loop and block the event loop. That's not
             | some damning indictment of Node. The point is that you
             | don't have to block on IO, so your program doesn't have to
             | halt the entire world, and sit around doing nothing while
             | you're waiting for a hard drive to spin or a network
             | request to complete.
        
         | syockit wrote:
         | Because Node.js is the most bad ass rock star tech to come out,
         | since Ruby on Rails.
        
         | mrcwinn wrote:
         | Because it's not as good. Why would I want two languages and
         | two runtimes when I can just have one, all while delivering a
         | demonstrably better user experience?
        
         | gedy wrote:
         | Rails wants to be the UI framework, and a lot of devs didn't
         | want to do server side UI and state, especially OOP style. So
         | it was easier to do JS for your APIs, etc. DHH's opinions kind
         | of made it an all or nothing choice for many folks.
        
         | Zanfa wrote:
         | Node is web scale.
        
       | dragonwriter wrote:
       | Already outdated: https://www.ruby-
       | lang.org/en/news/2024/12/25/ruby-3-4-1-rele...
        
         | mtkd wrote:
         | I had just hit this issue (3.4.0 showing as 3.4.0dev in rbenv)
         | and am having a coffee before looking at what is going on --
         | thanks for posting
        
       | pjmlp wrote:
       | I am liking all the performance improvement goodies on JIT and GC
       | level.
        
         | ksec wrote:
         | 1. Wondering 3.4 JIT performance vs 3.3 JIT on production
         | rails.
         | 
         | 2. Also wondering what upside could Ruby / Rails gain on a
         | hypothetical Java Generational ZGC like GC? Or if current GC is
         | even a bottleneck anywhere in most Rails applications.
        
           | pjmlp wrote:
           | Most likely not yet there, but for applications implemented
           | in Ruby it is certainly an improvement for overall usability
           | experience.
        
           | neonsunset wrote:
           | > Also wondering what upside could Ruby / Rails gain on a
           | hypothetical Java Generational ZGC like GC? Or if current GC
           | is even a bottleneck anywhere in most Rails applications.
           | 
           | Ruby's GC needs are likely to be very far from the needs of
           | JVM and .NET languages, so I expect it to be both much
           | simpler but also relatively sufficient for the time being.
           | Default Ruby implementation uses GIL so the resulting
           | allocation behavior is likely to be nowhere near the
           | saturation of throughput of a competent GC design.
           | 
           | Also, if you pay attention to the notes discussing the
           | optimizations implemented in Ruby 3.4, you'll see that such
           | JIT design is effectively in its infancy - V8, RyuJIT (and
           | its predecessors) and OpenJDK's HotSpot did all this as a
           | bare minimum more than 10 years ago.
           | 
           | This is a welcome change for the Ruby ecosystem itself I
           | guess but it's not going to change the performance ladder.
        
           | vidarh wrote:
           | There's TruffleRuby (built on Graal) and JRuby if you want to
           | explore that. They're not viable for everything, but they can
           | be much faster.
        
           | viraptor wrote:
           | I would expect some measurable improvement given how object-
           | happy rails programming is. It's not uncommon to see 3 layers
           | of models just wrapping a single variable - "objects that
           | could've been functions". Some kind of tiers like generations
           | or per-request pools would be amazing.
        
           | sosodev wrote:
           | https://speed.yjit.org/
           | 
           | Railsbench is 5.8% faster with 3.4 over 3.3
        
             | ksec wrote:
             | Turns out YJIT is already 100%+ faster than non JIT in
             | RailBench and ActiveRecord.
        
           | riffraff wrote:
           | There's ongoing work to allow pluggable GCs, and specifically
           | to allow using MMTk which would be IBM's Jikes GC
           | 
           | https://bugs.ruby-lang.org/issues/20470
           | 
           | https://www.mmtk.io/
        
             | pjmlp wrote:
             | Not quite, MMTk was rewriten from Java into Rust.
             | 
             | So already something else from Jikes days.
        
       | fithisux wrote:
       | Congratulations guys. Thank you for the hard work.
        
       | 0xferruccio wrote:
       | Always looking forward to the Christmas tradition of Ruby
       | releases
        
         | saghm wrote:
         | Years back I took over the ownership of the third-party Arch
         | Linux package for ruby-build because the maintainer at the time
         | wasn't using it anymore and was looking to pass it off. At the
         | time, I had no idea that Ruby did released every Christmas, but
         | I found out a few months later when I got an email mentioning
         | the package was out of date that day. Even though I haven't
         | done much Ruby dev for years now, it's been a small little
         | tradition of mine since then to update the package first thing
         | every Christmas morning and push out the update (basically,
         | just updating the version number in a file in a git repo and
         | then running a couple commands to update the checksums and push
         | the changes; nothing anywhere close to the amount of work that
         | people who actually develop that tool do, let alone the people
         | who work on the language!). I can't help but feel like that
         | farmer from the meme saying "it ain't much, but it's honest
         | work"; I enjoyed the little tradition I've built up and like
         | thinking that maybe every now and then someone might have
         | noticed and been pleased to get the updates without having to
         | file a notice to remind me to update things (although it's
         | happened a few times since that time years ago, I hope it
         | hasn't been that often!).
         | 
         | Just now, I was surprised to see that the package seems to be
         | getting put into the official Arch repos, so my eight years of
         | very minimal volunteer service seem to be at an end. I still
         | think I'm going to remember doing this and smile a little every
         | Christmas morning for years to come!
        
           | uticus wrote:
           | Thank you for the quiet work, appreciated
        
       | tan-z-tan wrote:
       | Every year-end, I update my Rails app. Lately, it's been stable,
       | and the updates just improve performance, so it's gotten easier.
        
         | tbolt wrote:
         | I haven't worked in ruby or rails in a few years but both seem
         | like they're in great spots and I'll be spinning up a new
         | project with Rails 8 soon. Hype
        
           | tan-z-tan wrote:
           | Sounds good. Rails is still my first choice for personal
           | development (though I've been using Next.js more often
           | recently).
        
         | Gigachad wrote:
         | I started at a company 3 years ago that was on Rails 5.1. After
         | 3 years on and off work I've managed to get it to Rails 6.1.
         | The process is such an incredible nightmare on a large app.
         | 
         | Currently stuck on trying to get Ruby 3 working.
        
           | prh8 wrote:
           | Same thing for me--4 years ago, Rails 4.2. Now on 6.0, work
           | for 6.1 is wrapped up. I did just finish going from Ruby 2.7
           | to 3.3. Any particular issues you're having, or just working
           | through the process?
        
             | Gigachad wrote:
             | Don't have the exact details on me but it was just the
             | change for the method params hash thing. The stack trace
             | seems to be pointing places that aren't the source of the
             | issue, just where it got triggered in some dynamic way.
             | 
             | Probably just need to spend more time understanding exactly
             | what changed and how to convert stuff.
        
           | ljm wrote:
           | At some point you just have to rip the bandaid off and put
           | any ongoing work on pause until the upgrade is done.
           | Otherwise it'll be another 3 years on and off while you try
           | to do the upgrade but the codebase keeps changing underneath
           | you.
           | 
           | And if that isn't happening and there's no other development
           | on the codebase, why bother upgrading it?
        
           | lifesaverluke wrote:
           | Curious what specifically you're running into?
        
       | cssanchez wrote:
       | I want to try Ruby since the news of Rails 8 came out, but it's
       | been so difficult that I just gave up. Installing Ruby on Mac and
       | Windows and actually getting the 3.3 version required for Rails 8
       | was a huge mission and test of patience because every installer
       | defaulted to older versions of both Ruby and Rails even one month
       | after the release. And yes, even Docker required tweaking to get
       | the versions and I had issues with devContainers anyway...
       | 
       | I finally got it installed and then followed some tutorials only
       | to see that Rails' html.erb files have completely broken syntax
       | highlighting in VSCode and other editors. I facepalmed and though
       | I tried to search for a fix online, I couldn't find one. I saw
       | posts mentioning it in forums and yet not a single solution
       | posted.
       | 
       | So I gave up. I tried in Mac, Windows and Linux. If someone here
       | knows how to fix the broken highlighter, that can be my Christmas
       | gift today, but for the most part I've moved on.
        
         | bendangelo wrote:
         | Use rvm to install ruby. Ruby dev sucks on Windows, mac only.
        
           | koshersalt wrote:
           | I think this is a major reason Ruby had trouble taking off
           | compared to Python. Most desktops were Windows, especially
           | for businesses.
        
             | liprais wrote:
             | typical hn comments,ignoring elephant in the room.
        
           | TiredOfLife wrote:
           | Ruby and rvm sucks also on linux (at least on SteamDeck).
        
           | jstummbillig wrote:
           | What sucks about it?
        
             | bendangelo wrote:
             | Most gems with native extensions won't work. Gems that
             | listen to filesystem changes like guard can be buggy. I
             | recommend using Mac or Linux for Ruby on Rails development.
        
               | chucke wrote:
               | The listen gem works on windows:
               | https://github.com/guard/listen?tab=readme-ov-
               | file#listen-ad... . Not sure whether guard builds on top
               | of it.
        
           | ufmace wrote:
           | It actually works quite well, if you use WSL.
           | 
           | Ruby itself works okay on bare-metal Windows, but virtually
           | guaranteed any decent size Rails project will use some native
           | gem that's a nightmare to get to build on Windows.
        
         | jeremy_k wrote:
         | Use asdf (https://asdf-vm.com/) to manage your Ruby versions.
         | 
         | You should be able to do
         | 
         | $ asdf plugin add ruby
         | 
         | $ asdf list all ruby (you'll see 3.4.1, the latest is
         | available)
         | 
         | $ asdf install ruby 3.4.1
         | 
         | And now you can use Ruby 3.4.1 with no issues. Follow that up
         | with
         | 
         | $ gem install bundler
         | 
         | $ gem install rails
         | 
         | $ rails new ...
        
           | psychoslave wrote:
           | Or mise, https://mise.jdx.dev/
        
           | d_sc wrote:
           | Like psychoslave suggested, try out mise
           | (https://github.com/jdx/mise). I used asdf for years, did the
           | switch to mise and have never looked back for package
           | management. It supports a huge number of languages and is
           | performant.
        
         | TiredOfLife wrote:
         | Only way to reliably use ruby seems to be docker.
        
         | dismalaf wrote:
         | I've found the easiest way to have a nice, consistent, working
         | Ruby installation is to install from source. Ubuntu, Debian or
         | Fedora are the easiest. There are a bunch of one-liners to
         | install all the dependencies on various distros floating
         | around. The Ruby website has instructions but the gist of it
         | is, run ./configure, then make, then make install. Actually
         | pretty easy. Gem is great for managing libraries, certainly
         | better than any Python solution for that ecosystem.
        
         | earthnail wrote:
         | On Mac, rbenv or asdf are both great. Also other commenters
         | here have good suggestions. I never had problems with VSCode;
         | curious what you ran into here.
        
       | hackerbrother wrote:
       | (Removed)
        
         | baggy_trough wrote:
         | Neither of those is the case.
        
       | revskill wrote:
       | Hope ruby 4 had static type system like typescript.
        
         | matthuggins wrote:
         | I would love that!
        
           | revskill wrote:
           | DHH is the issue, he means Rails is for one-person framework
           | while he think static typing is only for enterprisey
           | software.
        
             | dismalaf wrote:
             | DHH has no say in Ruby development.
             | 
             | That being said, Matz also isn't a fan of static typing.
             | Static type annotations exist in the form of RBS, but no
             | one that matters in the Ruby eco-system is pushing static
             | type annotations in .rb files themselves.
             | 
             | Also, after seeing TypeScript, I'm very happy about that.
        
               | nona wrote:
               | https://github.com/soutaro/rbs-inline
               | 
               | I myself am unsure where I stand on RBS. I wouldn't mind
               | more use of it in my gem dependencies, but would probably
               | not like it if it was enforced everywhere.
               | 
               | For now I'll stick with improving my test/spec-writing
               | skills, and maybe some runtime type checking like
               | https://literal.fun/
        
         | Maledictus wrote:
         | I hope not, that would turn Ruby into just another of the
         | myriad of statically typed languages.
         | 
         | Try Crystal if you want less dynamic typing.
        
       | replwoacause wrote:
       | If I want to make a SSR site using Ruby, are there any good
       | frontend UI libraries that make doing this easier? It'd be nice
       | if there was some Ruby abstraction for writing HTML, CSS, and JS
       | that makes building interactive UIs easier (possibly built on top
       | of HTMX, AlpineJS, etc).
        
         | Lio wrote:
         | Do you mean like Hotwire?
         | 
         | https://hotwire.io/
        
       ___________________________________________________________________
       (page generated 2024-12-26 23:01 UTC)