9 ms·
I'm pretty sure that's where Elixir got its start, too. Jose Valim is a member of the RoR core team and he wanted better concurrency for Ruby.
by mikedelago 4y ago
I'm pretty sure that's where Elixir got its start, too. Jose Valim is a member of the RoR core team and he wanted better concurrency for Ruby.
- cpursley 4y agoYeah. Unless you're already running a big Rails app that's not a good candidate for a rewrite, what's the point? Nothing against Ruby, but just use Elixir/Erlang already.
- valenterry 4y agoThe BEAM is awesome, but both Elixir and Erlang are not really great for concurrency. They lack support for pure functional programming, which is really one of the most useful things in this area.
- brightball 4y agoHow are Elixir / Erlang anything but great for concurrency?
- valenterry 4y agoUsing Elixir / Erlang on the BEAM is great for concurrency - but the programming languages themselves are not. It's an important distinction, because I believe that there is still a lot of potential for those languages.
- ramchip 4y agoWhat is it about pure functional that makes concurrency much easier? Is there a code sample that would illustrate it? I've done both Haskell and Erlang/Elixir and yet I don't really see what you're referring to concretely. There was hope that automatic parallelization would be a big win for pure functional, but I don't think it's really worked out in practice, because of the overhead and difficulty of predicting if parallelizing something would make it faster or slower.
- valenterry 4y agoIt's not about performance as much as correctness and easiness to understand code. Functional programming removes the need to simulate (local) state in your head when trying to understand what code does. And in the places where it is inevitable, it makes it explicit and leads to a design where it's easy to track why and how things got changed. For example, .map and .filter are now in almost every language, because they are much easier than for-loops. You see them and you know "aha, this collection will be transformed, the number of elements stays the same" or "this collection will be filtered and the elements will look the same, but some might be gone and no new ones will have been added". Pure functional programming is similar, just that the scope is suddenly "the whole runtime/machine" instead of "a small piece of code that somehow does a loop".
- ramchip 4y agoIf I understand correctly, you're saying Erlang/Elixir code would be easier to understand and work with if functions that did I/O or message passing etc. were labeled as such, via type info. I don't entirely disagree, but I also don't think it would be a game changer for a couple reasons... - It's already well established practice to separate pure and impure modules in Erlang/Elixir projects, even without a type system to enforce it. Take Ecto for instance, it has a clean split of side-effects (Ecto.Repo) and pure logic (Ecto.Changeset). Very different from things like ActiveRecord or Django ORM. [1] - BEAM programs (and libraries) use a lot of concurrency and message passing, and I think you would have to use an escape hatch ala unsafePerformIO more often than a typical Haskell program, otherwise the IO would "infect" most of the code. Things like instrumentation, fetching app environment, calling the code server, using process dict... Joe Armstrong kind of mentions the latter problem in his thesis [2]: Notice that I have chosen a particularly simple definition of “dirty.” At first sight it might appear that it would be better to recursively define a module as being dirty if any function in the module calls a “dangerous” BIF or a dirty function in another module. Unfortunately with such a definition virtually every module in the system would be classified as dirty. The reason for this is that if you compute the transitive closure of all functions calls exported from a particular module, the transitive closure will include virtually every module in the system. The reason why the transitive closure is so large is due to “leakage” which occurs from many of the modules in the Erlang libraries. We take the simplifying view that all modules are well-written and tested, and that if they do contain side-effects, that the module has been written in such a way so that the side effects do not leak out from the module to adversely affect code which calls the module. He is of course talking about "dirty" _modules_. Working at the function level, the leakage wouldn't be quite as bad... but I think it may still be enough to limit how useful IO annotations would be. Code that "has been written in such a way so that the side effects do not leak out" is quite common on BEAM. Who knows though. Maybe we'll see interesting things in Gleam in the future :) [1] "To spawn, or not to spawn?" is a good article on the practice of separating I/O (GenServer) code and pure code: https://www.theerlangelist.com/article/spawn_or_not https://www.theerlangelist.com/article/spawn_or_not [2] https://erlang.org/download/armstrong_thesis_2003.pdf https://erlang.org/download/armstrong_thesis_2003.pdf
- User23 4y agoSpeaking of important distinctions, concurrency isn't a property of a language, but rather a property of a runtime. It's the old procedure vs process distinction. Now a language can have nondeterministic constructs that beg for a concurrent runtime, but that doesn't actually require it. After all, a nondeterministic construct can be implemented deterministically. If the language doesn't specify the order the nondeterministic cases are handled in, then the runtime is free to handle them in some deterministic way. Incidentally that's the root of the misconception that pure functional languages are easier to reason about. It's operational reasoning that's problematic, because simulating a nontrivial state machine in one's mind is a great cognitive challenge for those of us who are less bright than John von Neumann. However, the Dutch basically solved this problem and provided a logical framework for reasoning about imperative programs in a way based off the program text, with no need for attempting to mentally simulate the probably infinite set of possible processes it describes.
- nequo 4y ago> However, the Dutch basically solved this problem and provided a logical framework for reasoning about imperative programs in a way based off the program text, with no need for attempting to mentally simulate the probably infinite set of possible processes it describes. Do you mind clarifying what the framework is that you mean? A pointer would be helpful for me.
- brightball 4y agoMy guess is that he means OTP.
- User23 4y agoSee Dijkstra and Scholten.
- valenterry 4y ago> Speaking of important distinctions, concurrency isn't a property of a language, but rather a property of a runtime. But the way of how you can and will describe how the runtime should execute code in a concurrent way is highly dependant on the language. Compare Assembly and Go or Rust or Erlang. Completely differnt worlds, don't you think so? > Incidentally that's the root of the misconception that pure functional languages are easier to reason about. It's not a misconception. People are different, but at least I can say after many years of experience in both worlds that pure functional programming is much much more productive than any kind of other approach that I have tried when it comes to dealing with concurrency, parallelism and effects.
- latch 4y agoI've been doing Elixir professionally for 6 years. There's a whole class of problems that are best solved with concurrent read/write access to data. So the answer to your question is exactly that: when you want N-cores to work on the same piece of data.
- brightball 4y agoI still don't understand how OTP doesn't already address that case?
- slindz 4y agoStrong disagree. Elixir has been my primary language since 2016 because it makes concurrency so easy. I'm also a little confused how it's not functional enough for you.
- valenterry 4y agoPlease mind the distinction between functional programming and pure functional programming - despite the name it's very different.
- dmitriid 4y agoIt's also the difference between being pragmatic and being in a cult.
- valenterry 4y agoThat sounds like you had some bad experiences - what happened?
- dmitriid 4y agoI've had a bad experience with zealots. Your original statement lacks any nuance except "E are bad because no pure functional programming". Any attempts to clarify resolve to basic "it's for the good of the whole program". Whereas easy-to-use concurrency primitives, effortless parallelisation and concurrency, and even the most basic stuff like ability to put a logging statement anywhere in the code without re-engineering half of your program trump whatever imagined advantages of pure functional programming you may come up with. Any day of the week, and twice on Fridays. In theory, theory beats practice. But in practice...
- valenterry 4y agoI did not intend to write an essay of why PFP would be great to have in Elixir/Erlang. I'm just posting my opinion here and I'm happy to explain it as you can see from my answers. > ability to put a logging statement anywhere in the code without re-engineering half of your program Let me ask you a question: does it change the semantics of your (whole) program if that logline, that you are talking about, is not executed for some reason - or if it is executed more than once? If your answer is "it doesn't really matter, might at most be a bit annoying but it's just a log, no stakeholder of the program can ever notice" then there is no problem with putting this logline into the program. No need to re-engineer anything. If, however, this logline is critical and will be e.g. parsed and used by another system and actions might be taken due to it, then I would argue it is good if you are forced to consider the potential impacts to your program. If that means that you need to re-engineer half your program then there is a good reason for that, since the potential impact is huge. Such a thing has never happened to me in many years while working on different kind of applications. Sometimes a couple of 100 lines need to be rewritten - that is the max that I ever had to do. And indeed sometimes this rewrite in fact caused me to find and resolve problems that would have otherwise been introduce by accident.
- throwawaymaths 4y agoMore important than pure functional programming is: smart timeouts, builtin load shedding/backpressure, supervisory restart trees.
- valenterry 4y agoThat's like saying "more important than food is having a full stomach". Pure functional programming is a tool (or paradigm) that makes the things you mentioned extremely easy and safe to implement and extend. It focusses on the local runtime though, not on distributed systems (where the BEAM comes in) - which is why they don't contradict themselves.
- throwawaymaths 4y agoBEAM is not a pure functional language system. There's lots of hidden state: message passing, IO, process dictionary, ets tables, counters, sockets, NIFs, etc.
- ilyt 4y agoForcing functional programming upon developers instead just giving them tools to do it well is a disadvantage, not a feature.
- valenterry 4y agoI think you misunderstood me. I said "They lack support for pure functional programming" which does not imply that they should force the developer into using it.
- ilyt 4y agoWhat it is missing in Elixir/Erlang ? I only have ops experience with those
- valenterry 4y agoBasics for pure functional programming support would be some kind of IO-effect-type, tail-call-optimization (Elixir supports that), syntactic sugar for IO-combinators (to build up the "concurrent execution-plan" without actually executing it). Optimally also stdlib functions and an ecosystem that help. Those can be rebuilt, but most people consider them tightly related to the language, so without it, it couldn't probably be called great support.
- lucidone 4y agoRails remains a best in class framework for web application development and ruby (in my opinion) a fantastic programming language (amazing object model + standard library).
- sho 4y agoSigh. As an old Rails hand myself - hell, I credit Rails for much of my tech career - I think I now have to disagree. Rails is great, indeed the best, for its use case, which is CRUD apps. That might still be enough. But what is expected of applications has changed over the years and Rails isn't really capable of meeting some of these new expectations, not alone anyway, and developers trying to implement them find themselves reaching for ever more kludges and workarounds and 3rd party software trying to fit, essentially, a square peg into a round hole. Applications these days - well, a large number of them - need to be realtime. Server push. Websockets. Push notifications. Scheduled jobs. Long running background jobs. Calls into other services. Presence awareness. The list just goes on and on. And sure, you can somehow deal with all of this in Rails - hell, you can do anything in any language given enough time and effort - but you are absolutely going against the grain, and you're not using Rails anymore, you're using Rails + sidekiq + node + some other thing + xyz. I thought Rails was supposed to be the simple option? Rails still might be the best choice, if you're sure your domain will never need to do anything long-lasting or concurrent. Internal admin apps or simple e-commerce would be good examples. But if it's going to be more than that then Rails might save you some time at the beginning only to bite you badly later on. Phoenix 1.7 is out now and I basically recommend all rails developers to start learning it. It is going to be a bit of a learning curve, and it's not quite as lovable as ruby and its near-perfect syntax, but it is vastly more capable and is, IMO, the way forward. Frankly, I don't understand why it isn't much, much more popular.
- inferiorhuman 4y agoFrankly, I don't understand why it isn't much, much more popular. It's been a few years since I walked away from Elixir and Phoenix for recreational projects so I've forgotten the finer points. The two things that bothered me the most were that a.) Erlang treats BSD as a second class citizen and b.) I got the sense that there was a lot of cargo culting going on. Getting an informed answer felt like it was just that much more difficult than with say Ruby. Professionally, as an ops monkey, I wouldn't want to be on the hook for supporting an Erlang or Elixir app. There's definitely a chicken-egg problem and I'd worry about finding coworkers who would be comfortable with Elixir, but there are also simply far too many moving parts. Like. Yeah okay channels are cool, in-place upgrades are cool, and a well disciplined team could make good use of them but to me that all sounds like a lot of very tempting footguns. All of a sudden I'm not just supporting an app, I'm supporting an entire runtime on top of Linux. I'd much rather deal with a single binary like e.g. go or rust provide, and I'd much rather not deal with Erlang processes and whatnot. That said the language itself is great. At the time I started dicking around with Phoenix I was working with a guy who was making a big push to use clojure for internal tooling. I liked the Elixir syntax which felt like a great mashup of Ruby and Clojure.
- adamors 4y agoWell, 3rd party ecosystem is minuscule in Elixir compared to Ruby. When you want to iterate fast but get bogged down by missing/unsupported libraries or having to learn Erlang to use its libraries with Elixir etc. Lot of services are also not publishing official SDKs for Elixir but do for Ruby etc. The list goes on. There's more to a non-trivial project than what the language itself provides.
- mrdoops 4y agoRunning into concurrency woes of that whole generation of languages (Ruby/Python/PHP/Java/JS) is how most Elixir developers happen I think ;)
- letmeinhere 4y agoIsnt the php concurrency story distinctly good, with every request spawning its own process?
- colonwqbang 4y agoAnyone can do "concurrency" by starting from scratch with a fresh process each time. That isn't "having a concurrency story" it's rather the opposite I think. It's very wasteful of system resources, energy, etc.
- stevewatson301 4y agoPHPs model would be okay if they used green threads/goroutines. That way, you can have a far larger number of workers, as most of them are blocked on database connections or HTTP requests to other services.
- heurisko 4y agoPHP's model is different, not a mistake. It has proved successful so far. The shared-nothing, short-lived process avoids classes of issues such as with slow memory leaks, accidentally blocking event loops, and shared memory threading issues. Most PHP sites will utilise php-fpm, so it isn't really true that each request will spawn another PHP process. The language historically hasn't been that great, but its shared-nothing architecture has always been the good part.
- weatherlite 4y agoOn the other hand its simple and works for many many people and apps. I wouldn't just discount it. The fact that "Anyone can do" it is a pro.