60 comments

[ 79.3 ms ] story [ 1917 ms ] thread
(comment deleted)
With a Domain Specific Language (DSL), you parse code and build an abstract syntax tree. But you can also build a Python library where you construct the same tree. With the benefit that LLMs are already better trained on Python code. If you need a deterministic programming language, you could use starlark.
The quotation marks having been stripped from the title changes the meaning quite a bit…
I will not. I refuse
Yes! This is also why I think it's stupid that languages are now trying to kill their most popular libraries as a matter of principle.

E.g. node says "oh no, you need a library to write tests!" and now that means that you have to have a testing framework built into your runtime. And of course it's just another library, really, that competes with the original one, but this one is blessed with standards so it has a monopolistic advantage that will deter further innovation.

I know that HN is famously a discussion forum where users comment based on the titles of submitted articles, rather than their content.

With that said, the divergence in comments on this very insightful and well written article will soon provide an unusually clear means of determining who is commenting on the title and who is commenting on the article.

The OP's point is well-taken: a new language usually forces you to change 100% of your environment and tooling, whereas a new library respects your habits and preferences.

I follow new language developments with keen interest, but few of them will ever reach the level of maturity to be considered serious candidates for adoption. It's also risky to adopt a language that you cannot easily hire developers for, for example.

Libraries are great, but there is only so much they can address, and that depends on the language, too, as the article correctly points out. And there are two kinds of libries: tool libraries and frameworks. Someone once said it nicely: "Frameworks are like Hollywood - 'You don't call us, we call you!'". Frameworks often require you to submit to their control flow rather the other way round; that's why I prefer tool libraries.

I would love to have a scripting language has typed features and you can replace bash with.

What comes close is:

    #! /usr/bin/env elixir

    Mix.install([:jason])

    defmodule JsonPrettyPrinter do
      def get_stdin_data do
        :stdio
        |> IO.read(:all)
        |> Jason.decode()
        |> case do
          {:ok, json_data} -> json_data
          _ -> raise "Invalid JSON payload was provided"
       end
     end
    end

    JsonPrettyPrinter.get_stdin_data()
    |> JsonPrettyPrinter.pretty_print_json()
    |> IO.puts()
> But thanks to Ruby on Rails, he doesn't have to! So he said that he has no particular opinion about the Ruby programming language, but he absolutely loves Rails.

Ruby got a hype phase with regards to rails. It then dropped. A lot.

TIOBE, while it is in general crap, is somewhat accurate when you plot things over time:

https://www.tiobe.com/tiobe-index/ruby/

So, ruby peaked with rails between 2006 to 2009 or so, give or take. Then the decline phase set in, and now it is unfortunately also crawling behind perl into extinction. This is very unfortunate - I still use ruby almost daily as the ultimate glue language. But this can not be denied now that ruby is following the extinction path perl already had going some years before.

I was using ruby before rails was created and ruby covers all my web-needs. I had a web-framework in PHP, used it for about three years, ported it into ruby and expanded it massively in the last 20 years or so (well, almost 20 years). I retired from rubygems.org when RubyCentral got crazy in 2024 (and even crazier in 2025 with the mass purge of developers). So, one difference here is that the friend he talks about is using a specific framework. He probably no longer uses ruby nor rails. I use ruby because the language is very well designed and covers (most of my) use cases; the rest I may sprinkle down with java. So whether rails exists or not, makes zero difference to me. Actually without rails it would be better, because people using ruby would be using it because of ... ruby. Even if there are then fewer users. I still think this is better than those who will jump ship anyway because they only use ruby due to rails. These guys are not like in the same boat. They have use cases for getting work done via rails, designing websites, infrastructure related to websites, user-interaction and so forth. But they don't really use ruby as such. Their use case is quite limited. I think this is one of the biggest problems here. It in part explains why ruby dropped down a lot (there are many reasons for this, python being so successful is in my opinion the biggest reason, but the other smaller reasons also add up - that also includes the laughable joke that is documentation in the whole ruby ecosystem. That's inexcusable - note, I am not saying documentation must be perfect, but please look at opal, ruby-wasm or rack - the documentation there is virtually NOT EXISTING.)

> The vast majority of programmers are non-experts, like himself

No, I think he is an expert - just in a specific niche and field. Not all experts know everything equally well.

> Subtle language features like first-class functions, and object systems, are lost on them because they don't really use them anyway.

I don't think this is true. Some language features are very useful. Ruby's blocks for instance. They are probably one of the top three win-win features ruby offers.

> Computer scientists should really be spending their time developing new libraries rather than inventing new programming languages.

I also disagree here. I would, however had, say, that new languages should be well-designed. Many new languages suck. Old languages also suck. Designing a great language is very hard. If it is just a toy or research language then this is fine, but once a language is meant to be "real", it really needs to have compelling use cases and be great in many areas including documentation.

> These features are simply not available in all other languages. Java's meta-programming features, for example, are just not powerful enough to implement a system like ActiveRecords. Rails is only possible because of Ruby.

That's also incorrect. You can create any DSL as you like in Java too. Ruby just makes this a lot easier out of the box. Plus, you can also have great websites without rails.

> Ruby on Rails was designed to make it possible to build we...

Well, maybe. The problem is that mature languages and ecosystems are mature and new features have to be shoehorned in. Raku (https://raku.org) on the other hand is intentionally designed as a braid of sub languages (slangs) for quoting, regex, PEG, etc and you can easily make your own slang with eg. https://raku.land/zef:lizmat/Slangify so you get your DSL as a drop down language in a general PL setting.
I just came across a situation where I had a DSL but it was clear that a language would have been better. What I don't like about this is the dogmatic tone which is pretty common in IT. Don't to it that way, do it my way! Sometimes a DSL is a solid choice, sometimes a language is a better one, sometimes you might want to support both but I guess "Choose the right abstraction for your domain" doesn't make for a clickbait title.
I don't know ruby or rails so probably wrong on this but why does the author say no framework for Java web. How different is Spring from that?

They talk about the programmer which doesn't know neither cares about the language stuff. So what is Spring lacking from that perspective?

(comment deleted)
Rails wouldn't exist without Ruby, Ruby wouldn't exist without C, Rails can't be rewritten in C, Rails isn't a library.

But aren't Rails, Laravel and Django a bit similar? At least for the people not directly involved in coding.

I was big fan of Scala a decade ago. The idea of a “scalable language” where DSLs could be built within the type system seemed super powerful. I lost my enthusiasm when the community decided they wanted to use it as Haskell on the JVM.

I’m hoping more recent developments, like WASM or Graal, provide a route for more flexibility when selecting languages. It’s nice to see Rust slowly become a serious choice for web development. Most of the time JS is fine, but it’s good to have the option to pull out a stricter low-level language when needed.

I completely disagree with the post.

All programming languages are equivalent meaning their level of expressiveness is the same, it's not an opinion it's a fact. Each language comes with its runtime and its peculiarities but potentially you can always make any feature that another language runtime has with any language, even though probably not with the same performance and efficiency has been that feature native to the runtime itself.

So there are no "more powerful languages" just runtimes that allow you to hide away some stuff considered stable enough that they become some kind of primitive for the programmer, now we may have different opinions on what elegant code is, but personally I'd like to avoid code that directly (i.e. no kind of abstraction) relies on runtime features and instead express clearly my intention in code, but I recognize the productivity gains.

(comment deleted)
The best example of all is Prolog. It is always held up as the paradigmatic representative of logic programming, a rare language paradigm. But it doesn't need to be a language. It is really a collection of algorithms which should be a library in every language, together with a nice convention for expressing Prolog things in that language's syntax.

(My comment is slightly off-topic to the article but on-topic to the title.)

Prolog is a contrived example. It's small and simple enough to be implemented as a DSL embedded in another language, reusing most of the parser and leaningn its execution logic.

Now try to produce a library that adds compile-time features: static types, lifetimes, the notion of const and constexpr, etc. You can, of course, write external tools like mypy, or use some limited mechanism like Java annotations. But you have a really hard time implementing that in an ergonomic way (unless your language is its own metalanguage, like Lisp or Forth, and even then).

Creating a library that alters the way the runtime works, e.g. adding async, is not entirely impossible, but usually involves some surgery (see Python Twisted, or various C async libs) that results in a number of surprising footguns to avoid.

Frankly, even adding something by altering a language, but not reworking it enough to make the new feature cohesive, results in footguns that the source language did not have. See C#'s LINQ and exceptions.

Think of Prolog the language as just a serialization of a Prolog AST. The AST could be constructed in any programming language as a library. But what if we want to share and store these ASTs? We can serialize them to Prolog the language! The language has value even if it’s a library.
Prolog admittedly mystifies me even more than the Haskell family. How do you do anything effectful, like read from a file, or output arbitrary data to standard out, or set up a loop to process keyboard events every 1/n seconds? How do you make system calls?
Speaking of prolog, any recommendations for resources learning it at a stage somewhere between "draw three circles" and "draw the rest of the owl"

I don't have real work I need prolog for, but I find it an interesting subject, My personal learning goal, the point where I can say I know prolog reasonably well is when I can get it to solve this mit puzzle I found, a sort of variant of soduku. I found a clever prolog solver for soduku that I thought could teach me more in this domain, but it was almost to clever, super optimized for soduku(it exploited geometric features to build it's relationships) and I was still left with no idea on how to build the more generic relationships I need for my puzzle(specific example if soduku cells were not in a grid how could they be specified?), in fact I can find very little information on how to specify moderately complex, ad hoc relationships. One that particularly flummoxed me was that some rules(but you don't know which) are wrong.

https://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku

Sudoku*. Suu means numbers in Japanese and Doku means solving here. So literally "number solving".
Disclaimer: I've no idea what I'm talking about. :)

But I have heard repeatedly that the good thing of prolog is the compiler, that takes information and queries that would be awful inefficient, and convert them in something that actually works. So I'm not sure... of course, you can convert virtually any language in a kind of library with some API that basically accepts source code... but I'm pretty sure is not what you meant.

How many Prolog programmers does it take to change a lightbulb?

false.

https://www.j-paine.org/dobbs/prolog_lightbulb.html

I always wanted to write a compiler whose front-end consumes Prolog and back-end emits PostScript, and call it "PrologueToPostscript".

prologue: a separate introductory section of a literary, dramatic, or musical work.

postscript: an additional remark at the end of a letter, after the signature and introduced by ‘PS’.

> Stanza provides an optional type system, garbage collection, and a multimethod based object system. But if you don't like Stanza's object system, there is no way to write your own. This is one of the main directions of programming language research. Can we design a language so expressive that library writers can easily write the most appropriate object system, or most appropriate type system, to fit their application? Perhaps one day we'll have such a language.

We already have it. It's an obscure little language called C++. Tise interested in those kinds of extensions to a language should look into Herb Sutter's experiments with cppfront: https://hsutter.github.io/cppfront/welcome/overview/

> Are Java developers just not as competent as Ruby programmers?

years ago a senior developer close to me said "when screening interviews, if i see rails i throw the resume in the trash"

so ironic how trivial/stupid these language-based judgements are

> Can we design a language so expressive that library writers can easily write the most appropriate object system, or most appropriate type system, to fit their application?

Why yes, it can and has been done: https://www.dreamsongs.com/Files/ECOOP.pdf

For me the title is a bit of a contradiction: I always think about the library as “the final language”. So author’s example of RoR/Ruby is “RoR is a great web service language that uses Ruby as the base, they evolved together and arguably as RoR is the main source of clients for ruby, ruby was as well designed for RoR as RoR for ruby”

I think about programming/design as languages/translation in a lot of ways: its languages all the way down.

(comment deleted)
(comment deleted)
Any language/library needs to communicate in two directions: to the machine and to the people. At the micro-level, machines work with bits, or voltages, or whatever. That's a technological problem, not easy, but tractable in a mechanical sense.

People, on the other hand, work with ideas, metaphors, expressions of intent, etc. If a language/library makes the communication of those things easier/better/faster; if it can be "written down" clearly, and "read" clearly by a person, then does it really matter into which taxonomic category it fits? We pick horses for courses. That seems about right.

If Rails works for you, is complementary with what you want to achieve, is an accelerator, and is generally well-understood by the people with whom you work, then use it. Alternatively, if the answer to all the previous is Stanza then go with that. There's less "right" and "wrong" in those decisions than there is "advance", or "struggle". It sounds trite. But, use what works. If something doesn't work make something that does, iff that's the most efficient approach.

Logic systems are a good place where the library first approach tends to work well: you keep a small, boring core (the inference engine), and let people extend it with predicates, rules/operators, and domain packages.

I’ve been experimenting with a small defeasible-logic core (argumentation semantics + priorities + conflict detection) that stays stable, while most of the real meaning lives in extension points. https://github.com/canto-lang/canto-lang

"The more powerful the language, the easier the libraries are to use." for anyone thinking of reading the title without the body

It's true, you couldn't really do Express in Java, at least not back then.