logoalt Hacker News

“Stop Designing Languages. Write Libraries Instead” (2016)

267 pointsby teleforcelast Wednesday at 12:29 PM268 commentsview on HN

Comments

jmmcdlast Wednesday at 2:05 PM

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.)

show 16 replies
rorslast Wednesday at 1:50 PM

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.

show 9 replies
dev_l1x_belast Wednesday at 1:06 PM

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()
show 4 replies
srikulast Wednesday at 3:32 PM

This looks to me like partly a false dichotomy. We can design languages and write libraries. Some would even argue that some kinds of "libraries" could be viewed as languages themselves, as much as some languages might as well have been written as libraries in another language.

Also often, the language doesn't live isolated from its implementation (compiler or interpreter). While theory looks at languages via its semantics, in practice as the OP notes it is about the quality of the implementation and what can be reasonably done with the language.

A recent [1] case is Julia. I think it has hit a kind of sweet spot for language design where new performant code tends to get written in Julia rather than in some other language and bound to it. At its core, it is a simple "call functions, passing data in and getting results out" kind of language, but what the functions ("methods") mean and how the compiler does just-ahead-of-time compilation with deep type specialized code means you can write high level code that optimizes very well. Those mechanics operate under the hood though, which makes for a pleasant programming experience ... and there are loads of cutting edge packages being written in Julia. It is less interesting to look at Julia as "just the language".

[1] recent in programming languages is perhaps anything <= 15 years? .. because it takes time to discover a language's potential.

show 1 reply
librastevelast Wednesday at 1:27 PM

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.

css_apologistlast Wednesday at 2:12 PM

> 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

show 7 replies
kayo_20211030last Wednesday at 2:55 PM

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.

unkulunkululast Wednesday at 2:29 PM

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.

show 2 replies
morshu9001last Wednesday at 3:12 PM

"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.

show 3 replies
rambambramlast Wednesday at 3:22 PM

There is a good web framework for C. It's called PHP. ;)

show 1 reply
OkayPhysicistlast Wednesday at 7:42 PM

I have to disagree about the author's described purpose of programming languages. PLs exist to provide elegant expression to a curated subset of ways of expressing solutions to problems.

At the extremes, we call these paradigms. Functional languages, Object Oriented languages, Array languages, etc. But every language exists to make some subset of "shapes" of solutions easier to read and write. Elixir encourages you to describe your programs as a distributed system of programs each running a series of transformations to data, thanks to its pipeline system, and to push your branching to function-call level with its pattern-matching multiple dispatch.

Java encourages you to write your application as a collection of things, that know stuff and do stuff, including telling other things to do stuff based on things they know.

C and Go encourage you to write your programs as an ordered series of atomic tasks for the computer to complete.

SQL has you describe what you want your output to look like.

Etc, etc. There are inherent trade offs between languages, because what you make inelegant to express or even inexpressible carries value, too.

taylorallredlast Wednesday at 4:00 PM

I agree with the sentiment of this article but the question that fascinates me is "when do you need a language feature instead of a library in order to accomplish X, Y, or Z?"

show 1 reply
bmc7505last Wednesday at 5:57 PM

There are a few approaches if you want to write a new language. One, as the author argues, is to write a library in an existing language, which may require sacrificing ergonomics to fit inside the syntax of the host language, but is safe, modular and reusable.

Many DSLs can be bolted onto an existing language with support for compiler extensions. This approach offers more flexibility, but often leads to fragmentation and poor interoperability in the language ecosystem.

There is third approach, established by a group in Minnesota [1], which is to design languages and tools which are modular and extensible from the get-go, so that extensions are more interoperable. They do research on how to make this work using attribute grammars.

If the host language has a sufficiently expressive type system, you can often get away with writing a fluent API [2] or type safe embedded DSL. But designing languages and type systems with good support for meta-programming is also an active area of research. [3, 4]

If none of these options work, the last resort is to start from tabula rasa and write your own parser, compiler, and developer tools. This offers the most flexibility, but requires an enormous amount of engineering, and generally is not recommended in 2026.

[1]: https://melt.cs.umn.edu

[2]: https://arxiv.org/pdf/2211.01473

[3]: https://www.cs.tsukuba.ac.jp/~kam/papers/aplas2016.pdf

[4]: https://arxiv.org/pdf/2404.17065

show 2 replies
tjchearlast Wednesday at 6:05 PM

The author makes a good point about language capabilities enabling certain libraries to be written, just as DSL makes it easier to reason about problems and implement solutions with the right kind of abstractions and language ergonomics (usually at the expense of expressivity and flexibility).

There’s a time in my life where I designed languages and wrote compilers. One type of language I’ve always thought about that could be made more approachable to non technical users is an outline-liked language with English like syntaxes and being a DSL, the shape of the outline would be very much fixed and on a guardrail, and can’t express arbitrary instructions like normal programming languages, but an escape hatch (to more expressive language) for advanced users can be provided. An area where this DSL can be used would be common portal admin app generation and workflow automation.

That said, with the advent of AI assistants, I’m not sure if there is still room for my DSL idea.

show 1 reply
scoofylast Wednesday at 7:44 PM

As a student of philosophy of language, I obviously agree with the author (against the quoted thesis).

The structure of a language matters to the ease and feel of its use, despite even being logically identical. One parallel would be the syntactic benefits of something like Hintikka’s independence-friendly logic vs first order logic, even if they are equivalent.

The sentiment shared is that we should sacrifice benefits to the next generation to make our own lives easier. This is a common sentiment, but a sad one. The goal should be a natural language based programming language, that everyone can use, along side a technical programming language that makes unambiguous the interface between the language and the machine.

Everyone seems to endorse their happy medium, and those languages are also perfectly fine.

patrickmaylast Wednesday at 2:23 PM

> 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

jll29last Wednesday at 1:06 PM

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.

whazorlast Wednesday at 12:55 PM

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.

show 1 reply
igt0last Wednesday at 2:56 PM

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

ninalanyonlast Wednesday at 11:04 PM

I'd say that the best thing ever would be an easy way to call a library written in xxx from a program written in yyyy.

There are lots of libraries already. Instead of rewriting them in every language why make them available to every language.

Yes, I know it would be difficult and in some cases impossible.

defactorlast Wednesday at 3:24 PM

Java has Grails web framework. We have designed apps with 75% less resources and time compared to Spring at a big enterprise. But most devs wanted springboot.

show 1 reply
NoGravitaslast Wednesday at 5:42 PM

Of course, in Lisp, you can implement language features as libraries, which kind of undercuts the point of this article.

kazinatorlast Wednesday at 5:36 PM

> In summary, the purpose of a general-purpose programming language is to enable the creation of powerful and easy-to-use libraries.

Close! The purpose of a general-purpose programming language is to enable the creation of powerful and easy-to-use languages, but often just libraries.

butterisgoodlast Wednesday at 9:21 PM

I think this thinking makes sense if you've not used enough programming languages pragmatically.

But, if you squint, great API design is a bit like embedded domain specific language design as well.

I think there's room for both.

fithisuxyesterday at 6:59 AM

Julia got it right with its macro system. You can write embedded DSLs easily.

show 1 reply
vhantzlast Wednesday at 2:12 PM

> 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/

show 2 replies
dominicroselast Wednesday at 1:46 PM

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.

Arch-TKlast Wednesday at 3:59 PM

The problem is really that sometimes making something feel ergonomic in a language can be a pain.

Although that in itself might be a hint to change language and write your library there, instead of inventing a new one.

agumonkeylast Wednesday at 3:14 PM

it's strange cause for some devs (lispers, smalltalkers, forth..ists), the language is the core, and any concept is to become a generic linguistic trait (and everything will be build by composing expressions with these traits).

yet at the same time, clojurists love the idea of doing lots of dsl libraries..

noreplydevlast Wednesday at 6:27 PM

i think that languages is are for worlds and libraries are for adding ships, planes and cars to that worlds, enabling those worlds itself.

the key is that not all worlds enable the same kinds of libraries.

vivzkestrellast Wednesday at 5:39 PM

- i need a language that looks like typed python

- and runs 50 times faster than c, c++, rust and zig

- comes with a standard library covering 50000 use cases

- has direct integrations with drivers to every major database, crm, analytics provider, key value store, queue systems

newsofthedaylast Wednesday at 3:54 PM

The article seems to vibe railing against Java.

show 1 reply
6510last Wednesday at 4:28 PM

Libraries and languages are not actually about syntax or function. They are communities first. They each have a community of users and one of developers. Depending on their application they each attract very different people - which is wonderful.

The work matters too of course. Frequently used functions should be categorically bagged into libs and if the lib is used often enough some of it's functionality should be baked into the language. If languages require something often enough the language layer above should provide it and if things are frequently needed close to the metal it should be baked in hardware. Possibly as a co-processor and then as part of the cpu. We should even have a similar process moving things in the other direction. I cant wait for the day when floating-point arithmetic becomes a library complete with a community of people who still think it's wonderful. Like a football channel to cleanly contain that kind of undesirable materials. Some libraries/modules/frameworks should also be replaced by competent developers. We don't want a leftpad community.

eklavyalast Wednesday at 1:36 PM

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?

hulitulast Wednesday at 6:14 PM

> “Stop Designing Languages. Write Libraries Instead” (2016)

It looks that somebody listened. We now have 3 GTK libraries in a system, a lot of graphics libraries (cairo, etc) 3d libraries (Mesa, vulkan). It is a mess.

CyberDildonicslast Wednesday at 5:41 PM

Lots of languages could just be implemented with classes in C++. Every "probabilistic language" could just be types that interact with each other properly.

dieggsylast Wednesday at 3:36 PM

I think I mostly agree with the thesis here, but I actually liked the point in the title at face value, too. We need both, I think. I guess I'll be another annoying Lisp guy, but:

> At this point, the right question to ask would be, well can you write a static-typing library for Scheme that then automatically checks your code for type errors? And the current answer, for now and for the foreseeable future, is no. No mainstream language today allows you to write a library to extend its type system.

The author seems to provide a counter example themselves(?):

> Racket and Shen provide mechanisms for extending their type systems...

I wonder if this is as clear-cut as the author is making it out to be. Coalton, which is effectively a library (and language) for Common Lisp, seems like it basically does this. Maybe that's not exactly what the author is referring to, because it is essentially a new language on top of Lisp using its meta-programming facilities, as opposed to merely extending the type system. Still, it can be used as a library right alongside Lisp code, so I think it's in the same spirit of of the first question of writing a "static-typing library that automatically checks your code" in a dynamic language.

Standard scheme may or may not be able to do this, but most Scheme implementations have unhygienic macros like CL's too, so I'd assume something similar would be possible. The fact that that these tend to be extensions from implementation designers might align with the article's point though. Also somewhat to the author's point, Coalton does rely strongly on CL's underlying type system, for which there's no real equivalent in Scheme. It also relies on implementation-specific optimizations alongside that.

For what it's worth you can (and indeed people have) written object systems in Scheme, despite the language not having one, though they tend not to be performant, which is likely another point towards using/writing a different language. CL also tends to allow fairly deep extension of its object system through the Meta-object Protocol.

I guess my point is that in my (probably biased) opinion, Lisps, or other languages with very strong meta-programming facilities, are pretty close to the language longed for in "Perhaps one day we'll have such a language." They aren't a silver bullet, of course. CL has no easy way to write performant coroutines/continuations, for example, even given all its extensibility. Scheme has no real type system, etc. etc.

I don't think any of this invalidates the articles points, I'm just not sure I agree with the absolutes.

shevy-javalast Wednesday at 1:17 PM

> 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 websites without understanding type theory, or memory management, or object-oriented design patterns.

Ok so ... why would this not be possible in Java? Why would he have to write Java code for a library to be used in this regard?

> Ruby on Rails provides a concise way for expressing: do this when the button is clicked

But you have the same in many other languages and frameworks too. I mean this is how PHP was started initially.

> The "do this" part is implemented in Ruby as a first-class function. How would it be implemented in languages like Java which don't support them?

Write a solid DSL.

> The programming language directly shapes the design of its libraries.

If this were true, why would GTK have glib+vala? I mean, they could just rely on C directly, right?

Besides, ruby is just a wrapper over C really.

> The more powerful the language, the easier the libraries are to use.

That part is true. A better designed language makes for better libraries or a chance to have better libraries. I noticed this when I compared my PHP code to my ruby code. I am not a good programmer, but my ruby code is much better on every level than the equivalent PHP code. Fewer lines too. While this also has to do with experience, at the end of the day PHP is simply a much worse language than Ruby is. At some point I decided I don't want to invest into languages that suck when I could be using better languages instead. That is also why I stopped writing shell scripts - it is just a waste of time having them.

Rails is also, by the way, fairly well documented. So I am not saying all in ruby has horrible documentation of course.

xigoilast Wednesday at 1:02 PM

The quotation marks having been stripped from the title changes the meaning quite a bit…

show 1 reply
CPLXlast Wednesday at 1:05 PM

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.

show 2 replies
tonyglast Wednesday at 1:04 PM

I will not. I refuse

show 1 reply
conartist6last Wednesday at 1:04 PM

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.

duesabatilast Wednesday at 1:55 PM

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.

show 3 replies
zcw100last Wednesday at 1:32 PM

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.

bluGilllast Wednesday at 3:50 PM

Languages are "Easy" to design. There is nothing wrong designing a new language and it can be fun.

There is however something wrong with releasing your new language! In most cases you should show it off to close friends, or your professor, and then burn it and all the source. Sure you might be better than the current language, but you won't be enough better as to be worth it. (even if the language is notoriously bad C++ where it is easy to be better - you won't be enough better as to be worth it).

If you want a better language there are two good options: switch to a different one that already exists; or make your language better. There are lots of great choices for languages out there if you want to switch. If the language you are thinking of doesn't have an active community of people working on making it better, it probably isn't a good choice.

Whichever language you choose though, libraries are the hard part. There are a lot of bad libraries, we need someone to write a better one - but only if one doesn't exist! For the great libraries out there, most need someone to contribute.

A large part of libraries is the consistent interface. Often there is a great libFoo and libBar, but their APIs are not consistent and so we need a libBarWithFooStyleInterface, and/or libFooWithBarStyleInterface. Better yet, we need everyone to come together and agree on how the interface should be and then make both use that new standard - cleaning Augean stables with a toothbrush seems like an easier task. Of course in the real world there a hundreds of libraries each with a great interface that is not consistent with the others.

show 1 reply