Elixir abstracts that away and leaves a ruby-like language that hides much away - which good and fine.
Erlang is by no means a simple language to get one’s head around.
I wish Elixir had more mindshare beside just LiveView and "real time" type functionality. Even building a GraphQL/JSON endpoint without real-time requirements, the functional nature (no side effects), pattern matching and ruby inspired syntax makes writing plain old JSON controllers a joy.
While Elixir might not have a package for every use case under the sun, the low level primitives are there.
It's like Rails except that there's much more resources for Rails to find if you made a mistake in the DSL
I think it helped that at the time I was trying to build some pretty advanced filtering functionality using Ecto and was having a pretty tough time. While searching for solutions I saw a few mentions of Ash and that it could solve the problem out of the box.
After a few days of experiments, I found that it was able to do the filtering I wanted out of the box and was even more functional than what I was trying to build.
For reference, I was trying to add some tagging functionality to a resource and I wanted to be able to filter by that tag, including multiple tags. Can I do that in Ecto? Of course, but Ash provided that out of the box after modeling the resource.
As an example, I wanted to add support for adding tags to a resource, and support filtering for the resource by the tag, and I wanted to be able to do this filtering both through Elixir functions as well as GraphQL.
Can I do this with Ecto? Absolutely, but I'd have to build it all myself.
With Ash, I created a `Tag` and `Tagging` resource, adding a `many_to_many` block on my resource, marked it as public. Then I added the `AshGraphql.Resource` extension to my `Tag` resource, marked it as filterable and I was done.
Now I can filter and sort by tags, filter by where tags _don't_ exist and more. I didn't have to do anything other than model my domain, and Ash took care of the rest for me. Not only that, but it probably did a lot of things for me that I probably wouldn't have thought of, such as supporting multi-tenancy, policies and more.
It really is a lovely tool, I can't say enough good things about it.
Does it have a learning curve? Absolutely! Is it worth overcoming it? Again, absolutely!
Source: Has worked on million-line Ruby on Rails codebase
I picked up Joe's Erlang book years after out of pure joy/curiosity.
Especially with LLMs, totally unnecessary.
Learning the concepts that embody Erlang such as tail recursion and function matching, make Erlang worth learning. Erlang is also a special mix of Prolog and Lisp.
For me Erlang was worth learning because it's so interestingly different to many other languages because of its Prolog roots.
I don't think it's really impeded my ability to learn or use Elixir. But I could also see how learning it and the underpinnings for Elixir could aid understanding too.
You don't need to learn OTP at first either — it'll just slow you down and confuse you. Learn Elixir syntax and semantics, learn how to build a Phoenix app or whatever, then dive into OTP once you're comfortable with the basics.
Erlang knowledge is not needed for building products with Elixir at all unless you want to go very in-depth.
if using elixir supposedly gives a competitive advantage, why aren't companies using to launch new products - both existing and startups.
a lot of those things quoted in the article are present on the jvm platform or through containers.
and btw some of those companies listed have migrated away from elixir e.g brex and discord.
A while back there was an effort to give more publicity on precise cases here https://elixir-lang.org/cases.html ; I think the effort is now moving to advertising the platform outside Elixir circles (e.g. more generalist conferences).
FWIW, I'm working on https://transport.data.gouv.fr, Elixir-based since 2016, the National Access Point to transportation data, which includes a business specific reverse proxy with a 3x YoY growth, with no plans to migrate :-)
Elixir also does not stand alone - the storied history of Erlang/BEAM in mission-critical distributed systems needs no introduction. Elixir lives within, and benefits from, that same ecosystem of libraries and tools.
So yeah I'm not sure what you believe there is to "introspect" about, nor to what end.
And no, Discord has not moved away from Elixir. While they have adopted Rust for certain parts of their infrastructure, Elixir remains a core part of their backend, particularly for real-time communication and chat infrastructure.
to learn what? that the language was not good enough? that it wasn't marketed well enough? that there was not enough community support? not enough word of mouth?
lisp users say they have a competitive advantage, as do smalltalk users. even pike at a time had a competitive advantage in that it was/is more performant than other similar languages.
some of us in the pike community kept asking ourselves why pike is not more popular. the syntax is not obscure. roxen was a killer webdev server, 10 years ahead of its time. but no takers. why? (probably a mix of lack of marketing and community support/encouragement from the financial backers, but other languages become popular without backing, so what gives?)
my point is that most times there is nothing you can do. unless you have the marketing power of sun (java) or google (go, etc), popularity of a language is mostly a case of luck and serendipity (ruby, python) or filling a unique need that no other language could (javascript, rust)
Tools like Elixir which are focused on solving problems, aren’t flashy or easy for web dev influencers (yes, they’re a thing) to tout, and have a bit of higher barrier to entry are probably at a disadvantage in this way, even if they’re actually quite good.
This is why the industry is stuck on a revolving door of JS frameworks and the n-hundreth React self-reinvention. It’s not about how good any of this actually is, it’s about how well it scratches the itch for that new car smell while also being easy to pick up and make grand declarations on social media about.
YMMV, but I think it writes fine unit tests, but really sub par functional or end to end tests that need to check business logic. I think that's just a hard case for LLMS and not an elixir issue though.
Elixir promotes a "do it all in one place" model—concurrency, distribution, fault tolerance—which can be powerful, but when you try to shoehorn that into a world built around ephemeral containers and orchestration, it starts to crack. The abstractions don’t always translate cleanly.
This opinion comes from experience: we’ve been migrating a fairly complex Elixir codebase to Go. It’s a language our team knows well and scales reliably in modern infra. At the end of the day, don’t get too attached to any language. Choose what aligns with your team’s strengths and your production reality.
If you don't know Elixir and the BEAM well, of course you're going to have a bad time. That's true of any language.
> what happens when the server restarts / connection is lost / server dies?
> you lose all of the current client state but you can work around this by persisting all the client state somewhere.
> oh, so why am i using live view again?
Not exactly, it's built to hold state in memory by default but doesn't assume how you want to handle deploys or server restarts. There's a built in restore mechanism for forms and it's trivial to shuffle state off to either the client/redis/your db[1]. You'd have the same problem if you were storing all your state in memory for any web application regardless of your library choice. Or you conversely have the problem that refreshing the page trashes client state.
So there are two thinks here, you don't have to use live_view to use elixir or phoenix, and if you do you just need to actually think about how you're solving problems. The state can get trashed anywhere for any number of reasons. Tossing on the client and forgetting about it just moves the problem.
i realize there is still a dataloss problem when there is state on the client but there is a lot of simple stuff that causes problems if you are effectively reloading the page if the server disappears due to a redeploy or a crash.
for example i'm reading an email in my message client. i've scrolled half-way down the email. but now the server crashes i reconnect to live view and my scroll position when reading the email is reset.
when i look at live view i feel like its written by people that have never deployed something in production. of course this is not really true but i feel like it would be better if live-view people were more honest about the tradeoffs. its a very complicated situation and having some bad outcomes might be worth the increase in developer productivity but i feel like live-view people just ignore the bad outcomes.
also, take a cloud deployment. websockets seem to be an inherent problem in cloud deployments especially AWS. as far as i know AWS does not expose some event to a instance that is part of a load balancer that it is about to die. ideally if you have a websocket instance with a client and you realize you are scheduled to be reaped you would message the client that it needs to reconnect. then the client would reconnect to a server that would not be reaped and everything would be dandy. but AWS doesn't seem to have this functionality (or its not easy to implement!) but more importantly live view does not expose any kind of hooks so you can have 'safe' server redeployment out of the box.
https://hexdocs.pm/phoenix_live_view/form-bindings.html#reco...
If I were starting a new company today though I'd probably go with Elixir, and then I simply wouldn't bother with containers, Kubernetes, and schedulers. Just run some servers and run the application on them, let them cluster, and generally lean into the advantages.
Erlang is low level, lightweight processes and message passing - perfect for micro-services and containerisation.
What Erlang lacks are high level web-oriented packages, i.e. markdown conversion, CSS and JavaScript packaging, REST (not quite true: cowboy is fantastic) - for which though Erlang was never intended.
However the cool thing is that you can combine both in the same project, allowing you to have high level Elixir and low-level process management in one project. This is possible because both use the same virtual machine - BEAM.
For example, the Erlang VM clustering can make use of K8s for Service Discovery. You can do ephemeral containers and use readiness probes to create a " hand over" period where new instances can sync their data from old, about-to-be-replaced instances.
Still, every release now contains new type system features. Next up is full type inference. [2] After that will be typed structs.
[1] José Valim giving his balanced view on type systems: https://www.youtube.com/watch?v=giYbq4HmfGA
So like a thin mirror? Which only serves to show the viewer back to themselves? And which also consists of just two extremely simple parts, that is, two panes/sheets of uniform materials, and nothing more?
How do you even come up with this metaphor for a web-based application? It's horrible!
It combines the "opinionated" aspects of ruby and rails and the power of erlang. The BEAM is like no other runtime and is incredibly fun to work with and powerful once you get how to use genservers and supervision trees.
We use Elixir for Mocha, and my one issue with it (I disagree with OP on this) is that live-view is not better than React for writing consumer grade frontends. I wish Phoenix took a much stronger integration with React approach, that would finalize it as the top choice for a web stack.
If I didn't need native functionality, I'd probably just use the recently released `phoenix_vite`: https://github.com/LostKobrakai/phoenix_vite
So it’s not a feature specific to Elixir since the BEAM is the common virtual machine.
This is what Erlang has and it’s very convenient since once a design is fixed, I end up writing a spec to remind me what types the function expects.
Note: I've not yet done any serious web-development, mostly command line tools, which I realise is not DHH's main focus.
They are actively shipping a type system for Elixir though, which as far as I understand is pretty similar to TS so, great!
But pattern matching in Erlang does do a lot of the heavy lifting in terms of keeping the variable space limited per unit of code which tends to reduce nesting and amount of code to ingest to understand the behavior you care about at any moment.
They have a success typing system (which isn't very good) and are working on a fuller system (which isn't very mature).
If typing is the only thing keeping you out, have a look at Gleam.
Having worked with Elixir professionally for the last six years now, it is a very mature platform, very performant and offers many things that are hard in other languages right out of the box.
If you're at all interested, I'd suggest doing the basic and OTP tutorials on the Elixir Website. Takes about two hours. Seeing what's included and how it works is probably the strongest sails pitch.
I see this phrase around a lot and I wish I could understand it better, having not worked with Erlang and only a teeny tiny bit with Elixir.
If I ship a feature that has a type error on some code path and it errors in production, I've now shipped a bug to my customer who was relying on that code path.
How is "let it crash" helpful to my customer who now needs to wait for the issue to be noticed, resolved, a fix deployed, etc.?
It's much more suitable as a replacement for adding try / catch everywhere and having to manually bubble exceptions.
Let it crash is more about autorestarting and less about type bugs. If you have a predictable bug in your codepath that always breaks something, it just means you never tested it and restarting will not fix it. But this kind of straightforward easy to reproduce bugs are also easy to test the hell out of.
But if you have a weird bug in a finite state machine that gets itself into a corner, but can be restarted -- "let it crash" helps you out.
Consider hot reload -- a field exists in a new version of a record, but doesn't exist in a old one. You can write a migration in gen server to take care of it, but if you didn't and it errored out, it's not the end of the world, it will restart and the problem will go away.
So sure, the code with the error won't work (it wouldn't work in any language - you can make an error in all of them), but you will get a nice, full stack trace and the other processes in your VM won't be impacted at all. You won't bring down the service with a crash. Sometimes this is undesirable - you could deploy a service where the only endpoint that functions is the health check - but generally people don't do that.
There are some very sharp Computer Scientists who believe static typing is unnecessary. Joe Armstrong (co-designer of Erlang) once said: "a type system wouldn't save your system if it were to get hit by lightning, but fault tolerance would"
You get zero help and punished hard for failing.
Log lines are whatever, but a system that goes into a crash loop or fails on most requests isn't great.
I don't want to look at TIOBE, so let's look at the stack overflow survey from 2024. https://survey.stackoverflow.co/2024/technology#admired-and-...
Strong + Static: TypeScript, Java, C#, C++, Go, Rust, Kotlin, Dart, Swift, Visual Basic, Scala
Weak + Static: C
Strong + Dynamic: Python, Lua, Ruby, R, GDScript(*)
Weak + Dynamic: JavaScript, PHP, Matlab, Perl
At this point I'm reaching into the low percentages. I think it's pretty clear that Strongly + Statically typed languages are massively over-represented on the list.
Both Strongly and Weakly Dynamically typed languages are similarly represented.
Note: I'm open to editing the comment to move languages from and to various categories. I haven't used many of them, so correct me if I'm wrong.
not anymore. they were very popular in the industry at one point. very few other languages have so many independent implementations as smalltalk and lisp. a testament to their wide spread use in the past.
Strong + Static: TypeScript; Weak + Dynamic: JavaScript
that doesn't make sense. typescript is javascript with types, it can't be both strong and weak at the same time.
but i believe we have a different definition of weak. just because javascript, php and perl have some implicit type conversions doesn't make them weakly typed. i believe it takes more than that. (in particular that you can't tell the type by looking at a value, and that you can use a value as one or another type without any conversion at all)
C is weakly typed, it was always a major criticism, C++ too i think (less sure about that).
once you correct for that you will notice that all languages in the strong and static category are less than 30 years old and many are much younger. (java being the oldest. but there are older ones like pike which is also strong and static and goes back to 1991)
the strong and dynamic category goes back at least a decade more. (if you include smalltalk and lisp)
what this does show is that static typing has experienced a renaissance in the last two decades, and also the worst is really using any form of weak typing.
i still don't get what makes strong and dynamic a bad combination, other than it's bad because it is not static.
I know that there are discussion about what strong vs weak even means, but I think most people would place the weak distinction way above yours on a possible weak-strong spectrum.
C can certainly be argued to be weak. My understanding is that it's mostly due to pointers (and void* especially). C++ is much better in this regard. I mostly just did not want to add a Weak + Static category just for one language.
Well, now that you've defined Strong to also include all of the languages I consider Weak, then yeah, no issues at all.
but the interesting question is really the one posed at the beginning. what makes strong but dynamic a bad combination?
i think we agree that weak is bad. implicit type conversions like 1+"2" range from the annoying to problematic and dangerous. if we eliminate weak that only leaves strong and static vs strong and dynamic.
i agree that strong and static is better in most cases, type declarations help, and pike the language i use the most myself which is somewhere between python and go, has powerful types that are a joy to work with, but for comparison in typescript types come across as more annoying (in part because they are somewhat optional, and because they get lost at runtime, so they don't help as much as in truly typed languages) but strong and dynamic has shown to be a solid combination, especially with python and ruby. so i don't feel the combination is as bad as you seem to suggest.
Sure, Smalltalk isn't, but Lisp is a different story. In this context I assume we all mean to say "Lisp" and not "Common Lisp" specifically.
Lisp (as the entire family of PLs) is quite massively popular.
Standard rankings have major blind spots for Lisp measurement, they miss things like, for example, Emacs Lisp is everywhere. There's tons of Elisp on GitHub alone, and let me remind you, it's not a "general-purpose" language, its sole function is to be used to configure a text editor and there's mind-boggling amount of it out there. AutoLISP is heavily used in CAD/engineering but rarely discussed online. Many Lisp codebases are proprietary/internal. Also, dialect fragmentation artificially deflates numbers when measured separately - many rankings consider them different languages.
If you count all Lisp dialects together and include: Emacs Lisp codebases, AutoLISP scripts in engineering, Research/academic usage, Embedded Lisps in applications, Clojure on JVM and other platforms - babashka scripts, Flutter apps, Clojurescript web apps, etc;
...Lisp would likely rank much higher than typical surveys suggest - possibly in the top ten by actual lines of code in active use.
I never did track down the last spot where we screwed that up. This was a system we shifted from statsd, so the offending callers were either working by accident or only killing some data points for one stat and nobody noticed.
So then OpenTelemetry.js had to start sanitizing its inputs and not assuming the compiler should catch it. I still think it odd that something called “.js” was actually “.ts” under the hood.
Very opposite the Go model, btw.
Erlang/Elixir's approach is to simply say, "It's gonna fail no matter how many precautions we take, so let's optimize for recovery."
Turns out, this works fantastically in both cellphone signaling, which is where OTP originated, as well as with webserving, where it is perfectly suited.
It just does not catch logics errors.
in other words, any error that doesn't occur right at start can be recovered from at least for all those operations that do not depend on that error being fixed.
Both because that memory leaks are normal is types languages - and does usually not matter in most serious applications - and because this class of errors is usually not what types catch.
Types have value when you 1) refactor and 2) have multiple people working on a code base.
The error you see when you don't have types is something like a BadArityError.
It WILL log the error, with a stacktrace, so you have that going for you
Note that even with typing, you cannot avoid all runtime errors
Also note that this tech was first battle-tested on cellphone networks, which are stellar on the reliability front
As such fault tolerance does not guarantee that you MRI scanner does not kill your patients.
You likely want both.
I see this story on an on: some hacker makes a language, they hate types because they want to express themselves. The languages gets traction. Now enterprise application and applications with several devs use it and typing gets essential - types will then gradually be added.
What? Elm was literally the result of a single grad students side project - elm incorporates both a sound type system and FRP.
This has nothing to do with time. It was a decision not to support it.
Elixir's seamless pattern matching paradigm, IMO, largely negates the need for strict typing. If you write your function signatures to only accept data of the type / shape you need (which you are incentivized to do because it lets you unpack your data for easy processing), then you can write code just for the pretty path, where things are as expected, and do some generic coverage of the invalid state, where things aren't, rather than the norm in software development of "I covered all the individual failure states I could think of". This generic failure mode handling, too, greatly benefits from dynamic typing, since in my failure state, I by definition don't know exactly what the structure of my inputs are.
However,elixir depreately needs proper types. IMHO the needs for types are in no means negated by pattern matching, and I also see hints at why you would say so.
> If you write your function signatures...
The point of types is worry less refactoring.
If you work at a place where you can define the arhicture for the entire lifecycle of the application without ever needing to Refactor, then sign me up! I want to work there.
I have the same attitude toward overly permissive type systems that I do toward the lack of memory safety in C: People sometimes say, "if you do it right then it isn't a problem," but since it objectively IS a problem in practice, I would rather use the tool that eliminates that problem entirely than deal with the clean-up when someone inevitably "does it wrong."
Long story short, a particular machine that joined the cluster that morning had some kind of CPU or memory flaw that flipped a bit sometimes. Our Elixir server was fine because we were matching on valid values. Imagine a typed language compiler that makes assumptions about things that "can't" happen because the code says it can't... yet it does.
It seems like the Elixir/Erlang community is aware of this, as is Ruby, but it's a rather large hole they have to dig themselves out of and I didn't feel particularly safe using the tools today.
I've heard a lot of good things about the Erlang runtime and I did really like Elixir's pipe operator, so it was unfortunate.
there are other things that contribute to this like pretty universal conventions on function names matching expected outputs and argument ordering.
it does suck hard when library authors fail to observe those conventions, or when llms try to pipe values into erlang functions, and yes, it WOULD be nice for the compiler to catch these but you'll usually catch those pretty quickly. you're writing tests (not for the specific reason of catching type errors), right? right?
There is also pattern matching and guard clauses so you can write something like:
def add(a, b) when is_integer(a) and is_integer(b), do: a + b
def add(_, _), do: :error
It’s up to personal preference and the exact context if you want a fall through case like this. Could also have it raise an error if that is preferred. Not including the fallback case will cause an error if the conditions aren’t met for values passed to the function.
lol
https://hexdocs.pm/elixir/main/gradual-set-theoretic-types.h...
There's also tooling like dialyzer, and a good LSP catches a lot too. The language itself has some characteristics that catch errors too, like pattern matching and guard clauses.
With all that said, I'm still very keen for static typing. In the data world we mostly start with Python without mypy, and it's pretty hard to go back.
Erlang OTP relies on being able to swap to new functions to do upgrades without downtime.
All of these would nominally be considered a type signature failure.
Yes you are. First of all there isn't such a thing as "strict typing", types are either static/dynamic and/or strong/weak. I suppose you meant Elixir has no static types. It is however a strongly typed language.
And just like it usually happens, static typing enthusiasts often miss several key insights when confronting dynamically typed languages like Clojure or Elixir (which was inspired by ideas implemented in Clojure).
It's not simply "white" and "black", just like everything else in the natural world.
You have to address:
- Runtime flexibility vs. compile-time safety trade-offs — like most things, things have a price to it, nothing is free.
- Different error handling philosophies. Sometimes, designing systems that gracefully handle and recover from runtime failures makes far more resilient software.
- Expressiveness benefits. Dynamic typing often enables more concise, polymorphic code.
- Testing culture differences. Dynamic languages often foster stronger testing practices as comprehensive test suites often provide confidence comparable to and even exceeding static type checking.
- Metaprogramming power. Macros and runtime introspection enable powerful abstractions that can be difficult in statically typed languages.
- Gradual typing possibilities. There are things you can do in Clojure spec that are far more difficult to achieve even in systems like Liquid Haskell or other advanced static type systems.
The bottom line: There are only two absolutely guaranteed ways to build bug-free, resilient, maintainable software. Two. And they are not static vs. dynamic typing. Two ways. Thing is - we humans have yet to discover either of those two.
They clearly said they "can't go back to" it, meaning they've experienced both, are aware of the trade-offs, and have decided they prefer static types.
> Gradual typing possibilities. There are things you can do in Clojure spec that are far more difficult to achieve even in systems like Liquid Haskell or other advanced static type systems.
That's great for clojure and python and PHP, but we're not talking about them.
Dynamic typing also varies - there's type introspection, runtime type modification aka monkey patching, different type checking strategies - duck typing & protocol checking, lazy & eager, contracts, guards and pattern matching; object models for single & multiple dispatch, method resolution order, delegation & inheritance, mixins, traits, inheritance chains, metaprogramming: reflection, code generation, proxies, metacircular evaluation, homoiconicity; there are memory and performance strategies: JIT, inline caching, hidden classes/maps; there are error handling ways, interoperability - FFI type marshaling, type hinting, etc. etc.
Like I said already - things aren't that simple, there isn't "yes" or "no" answer to this. "Preferring" only static typing or choosing solely dynamic typing is like insisting on using only a hammer or only a screwdriver to build a house. Different tasks call for different tools, and skilled developers know when to reach for each one. Static typing gives you the safety net and blueprints for large-scale construction, while dynamic typing offers the flexibility to quickly prototype and adapt on the fly. The best builders keep both in their toolbox and choose based on what they're building, not ideology.
In that sense, the OP is wrong - you can't judge pretty much any programming language solely based on one specific aspect of that PL, one has to try the "holistic" experience and decide if that PL is good for them, for their team and for the project(s) they're building.
That's true but some languages don't let you ship code to prod that multiplies files by 9, or that subtracts squids from apricots
There are really good arguments both ways.
Just use what you need or go with whatever your current project dictates. Over time you will probably feel drawn to both, for different reasons.
Far from it.
atom, binary, boolean, function, list, map, pid, reference, integer, float, and tuple
There are a few others but they are generally special cases of the ones above. Having so few data types tends to make it much more obvious what you’re working with and what operations are available. Additionally, because behavior is completely separate from data it’s infinitely easier to know what you can and can’t do with a given value.
Ruby being dynamic drove me insane at times, but Elixir/Erlang being dynamic has been a boon to productivity and quality of life. I recently had to write some TypeScript and was losing my mind fighting the compiler, even though I knew at runtime everything would be fine. Eventually I slathered enough “any” on to make the burning stop… But! That’s something I haven’t had to do in years, and it was 100% due to type system chicanery and not preventing a bug or making the underlying code more sound.
There are still some occasions where having some static typing would be nice— but they’re pretty rare and often only for things that are extremely critical or expensive to fix. And IMHO even in those cases, Elixir’s clarity and lack of (implicit) state generally make up for it.
Talking about stuff like this:
nodes =
node_data
|> Input.split_by_line(trim: true)
|> Enum.map(fn <<
t::binary-size(3),
" = (",
l::binary-size(3),
", ",
r::binary-size(3),
")"
>> ->
{t, {l, r}}
end)
|> Enum.into(%{})
I decided to learn Clojure for my next language.
i am interested in clojure, but i am put off by it using the java run time. ;-)
Clojure runs not only on Java - you have Clojurescript, you have babashka and nbb, you have Clojure-Dart — if interested in building Flutter apps, you can even use Clojure with Python libs. If you need to target Lua, there's Fennel, which is similar as it's inspired by Clojure.
For me - Clojure is a hands-down best medium for data manipulation - there's just nothing better out there to explore some data - investigate APIs; sort, group, dice and slice any kind of data - CSVs, JSON, etc. Nothing else simply can match the joy how one could incrementally build up complex data transformations, it makes it incredibly productive for the "let me just quickly check this shit" scenarios that can easily turn into full analyses. REPL-driven nature of it makes it so much fun - you feel like you're playing a videogame.
I honestly wish every programmer knew at least some Clojure. I lost count of how many times I gave up on figuring out complex jq syntax and reached for Clojure instead. Or the times I'd quickly build a simple Playwright script for reproducible web-app bug trapping or quick data scraping that saved me hours of frustration and manual clicking.
Fennel -> Lua
Jank -> C++
No, you're not alone. After learning Lisp, structural editing and REPL-driven-development, I just don't feel like needing to learn new languages no matter how powerful they seem to be. Lisps like Clojure are highly pragmatic and offer something fundamentally different from the endless parade of syntax-heavy languages that dominate the mainstream.
Once you've experienced the fluidity of paredit or parinfer, where you're editing the structure of your code rather than wrestling with textual representations, going back to manually balancing brackets, fixing indetnation and carefully placing semicolons feels like reverting to a typewriter after using a word processor. The code becomes malleable in a way that's hard to appreciate until you've lived with it.
And the REPL changes everything about how you think and work. Instead of the write-compile-run-debug cycle, you're having a conversation with your running program. You can poke at functions, test hypotheses, build up solutions incrementally, and see immediate feedback. It's exploratory programming in the truest sense - you're not just writing code, you're discovering it.
The homoiconicity - code as data - means you're working in a language that can easily reason about and transform itself. Macros aren't just text substitution; they're proper AST transformations. This gives you a kind of expressive power that most languages can't match without tremendous complexity.
So when the latest trendy language appears with its new syntax and novel features, it often feels like rearranging deck furniture. Sure, it might have nice type inference or clever concurrency primitives, but you're still stuck in the old paradigm of fighting syntax and losing the conversational flow of development.
You've tasted something closer to the pure essence of computation, and it's hard to go back.
To my surprise this there isn't really a good mobile story to build mobile apps for both Android and iOS with it, although it looks like it could be a great option for quick turnaround mobile apps with a web- or native frontend...
I know that there is something being worked on, eg. LiveView native: https://native.live/ , but that seems to target two entirely different frontend frameworks, one for each platform...
I started using capacitor as a wrapper for a HTML frontend, but I think I might potentially run into trouble when I'd try to move into production builds...
I think there's some space for research and maybe some nice starter packs / tutorials there... Because I think it is a big and pretty relevant market for browser-based apps, which Elixir seems to be very well suited to!
I'm grateful for any additional pointers, peace out! :)
Why nobody's hiring for Elixir :(
andy_ppp•10h ago
tl•9h ago
Clojure brings about half the novelty of Elixir, runs on the JVM and still struggles to replace Java.
stanmancan•3h ago
For what it’s worth, I’ve been using Elixir professionally for a few years now and haven’t touched Redis once.
Not sure why telling people they don’t need another service is bad for adoption?
jjtheblunt•57m ago
is there a popular pattern, perhaps as used by whatsapp, i guess?