[HN Gopher] Elixir protocols vs. Clojure multimethods
       ___________________________________________________________________
        
       Elixir protocols vs. Clojure multimethods
        
       Author : sandbags
       Score  : 142 points
       Date   : 2021-07-17 11:47 UTC (11 hours ago)
        
 (HTM) web link (mattmower.com)
 (TXT) w3m dump (mattmower.com)
        
       | Aboh33 wrote:
       | I recently found there was a clojure implementation for .NET and
       | also one for the BEAM Virtual Machine. Has anyone used the
       | latter? Regards
       | 
       | [1] https://github.com/clojure/clojure-clr [2]
       | https://github.com/clojerl/clojerl
        
         | AkshitGarg wrote:
         | There is also lfe [1] which is a lisp for the BEAM VM
         | 
         | [1] https://lfe.io/
        
           | segeda wrote:
           | And also https://github.com/clojerl/clojerl
        
         | zcam wrote:
         | There is also ClojureDart in the making. That one seems quite
         | promising.
        
         | didibus wrote:
         | Why do you say "was"? They are both still actively developed
         | even if not very popular.
        
       | tobyhinloopen wrote:
       | Using dashes in function names? Blasphemy
        
         | sandbags wrote:
         | Funky, I hadn't even noticed I had switched back when I started
         | thinking about Clojure and that it's not legal Elixir. I had to
         | go check my Elixir code to find the _'s!
        
         | nlitened wrote:
         | That's called "kebab case". When your language supports it, you
         | know the language is good :)
        
       | dnautics wrote:
       | You can, you can match against the module in the struct of the
       | second parameter, concatenate the two modules, and manually
       | dispatch against the concatenated module. I don't really
       | recommend this (it is not performant and feels like a code
       | smell), but it is possible
        
         | blunte wrote:
         | Does performance matter considering Elixir is already very slow
         | in per-thread performance?
        
           | brightball wrote:
           | How is it slow?
        
             | blunte wrote:
             | How? Do you mean how do I know it's slow? Because it takes
             | longer to run.
             | 
             | Write a typical computation such as Fibonacci in Java and
             | Erlang/Elixir and compare. Fortunately someone has already
             | done this.
             | 
             | Elixir is 3x slower than C and 2x slower than Java for this
             | single thread example.
             | 
             | https://github.com/drujensen/fib
             | 
             | Apparently this upsets people for me to point this out.
             | However, I did not say that Elixir was slow in general or a
             | bad choice. It's an excellent choice for problems which
             | suit parallelization or which require reliable, consistent
             | performance.
             | 
             | Since the parent poster had commented that adding this
             | multi-module dispatch would not be performant, I merely
             | pointed out that the single thread peformance was already
             | slow (as in, why worry too much about the performance cost
             | of the multi dispatch suggestion).
        
               | CraigJPerry wrote:
               | I'm starting to get a bit fed up with the down-voting
               | behaviour here recently.
               | 
               | It used to be that on HN you down-voted for people who
               | were obstructing conversation, being disingenuous or in
               | some cases being excessively disrespectful.
               | 
               | Now having read 3 of your comments and seeing all 3 are
               | heavily down-voted and yet the content of your messages
               | is constructive and interesting.
               | 
               | If you disagree with something, fine, just don't vote on
               | it. Save the down-votes for bad actors, not someone with
               | a different view.
               | 
               | The last thing HN needs is to become the kind of place
               | where you're actively encouraged to karma farm or
               | whatever that term is for that behaviour on reddit.
        
               | ddek wrote:
               | Eh, I'd rather the thread discussed the language features
               | in TFA. Once again, a potentially interesting comment
               | section is sidetracked by _yet another referendum_ on {{
               | niche_programming_language }} 's application to web
               | development. Can't we just keep this to release posts?
        
               | dnautics wrote:
               | I think they were downvoted because the first response
               | was almost contentless and the other posts complain too
               | much about the downvotes. Yes, there is some "good info"
               | there but basically they are still presented in a
               | relatively context-poor fashion and defensive, and
               | willfully ignoring other points being made, and most
               | active practitioners of elixir are aware of the context,
               | so the comments are of questionable utility except for
               | people who don't use the system, who may interpret it out
               | of context and come to conclusions that are wrong. In
               | short, they _still_ have a shitposty feel.
        
               | brightball wrote:
               | It's slower for an operation like that because of the
               | scheduler ensuring a single process isn't hogging all of
               | the CPU.
               | 
               | When was the last time you needed to write a Fibonacci
               | for anything you've built in your career?
               | 
               | It's a benchmark that doesn't show anything useful for
               | real world applicability.
        
           | dnautics wrote:
           | depends on what you are doing. And it's not necessarily "very
           | slow", moving forward as the JIT gets better and better. I
           | highly doubt that this technique is going to be very
           | jittable.
        
           | Zababa wrote:
           | On the web site of things, it is faster than Rails, Django,
           | Laravel, Express and even Spring, and this is with Plug and
           | Ecto. https://www.techempower.com/benchmarks/. That seems to
           | be very good performance to me.
        
             | blunte wrote:
             | People go nuts here on HN if they think you said something
             | bad about their baby.
             | 
             | I said per-thread, but I meant single-thread... as in CPU
             | bound single process activity. That is undisputedly slow
             | compared to languages like Java, C/C++, Go, etc. That is
             | also very much not what Erlang is designed for. It adds a
             | lot of overhead with the supervisor and other features
             | which do not give a benefit for single thread CPU heavy
             | activities.
             | 
             | And since the parent poster mentioned the multi-dispatch
             | approach would not be performant, I attempted to suggest
             | that the performance cost of that would be less relevant
             | considering Elixir is already not very performant in single
             | thread cases. In other words, it was a moot point.
             | 
             | I never said that Elixir/Erlang was slow for multi-
             | thread/process distributed activities. Obviously that is
             | where it really excels. But if you want to crunch numbers
             | sequentially in a way that cannot be spread across multiple
             | processes/threads, then you will find Elixir to be slow.
             | 
             | The benchmarks you are referring to are very much multi-
             | thread comparisons. They are specifically NOT what I was
             | was slow.
        
               | Zababa wrote:
               | You're right about the performance of single-threaded vs
               | multi-threaded Elixir. However, I used web apps as a
               | comparison because they are the most common use case for
               | Elixir. Considering here Elixir performs very well,
               | performance could be one of the reasons why people choose
               | it. In that case, being aware of performance pitfalls is
               | a good thing.
               | 
               | I don't agree that performance is a moot point if what
               | you use is slower than some alternatives, and I think
               | that's the main point where we disagree.
        
               | blunte wrote:
               | I am not a fan of slowing something down, but in the
               | multi-method dispatch example, unless it was being
               | exercised in a tight loop (which would seem very much
               | like a single thread CPU bound scenario which is already
               | a problem), then it wouldn't be exercised often enough to
               | make a big impact. That's just my gut feeling based on my
               | experiences.
               | 
               | But if this really is a big deal, then it would be fair
               | to consider the other language features which do not
               | contribute to the reliability, scalability, and other
               | core Erlang/BEAM features. For example, what is the cost
               | of pattern matching in general? Doesn't that add
               | considerable overhead, just for the benefit of making
               | code cleaner? If that's acceptable, then I don't see why
               | "just one more" feature - in this case a homegrown multi-
               | method dispatch across modules - should be considered
               | non-performant.
        
               | ch4s3 wrote:
               | Pattern matches should execute in linear time in the
               | worst case worst. Generally you want to place the most
               | likely and specific matches first.
        
               | Zababa wrote:
               | Good point about the tight loop. For the other part, my
               | gut feeling would be that there is a "base language" that
               | most developers are familiar with, and accept the
               | performance/other things tradeoffs of, but for more
               | obscure features, people are explicit about these points
               | because they are less known.
        
         | dnautics wrote:
         | defmodule A do           defstruct [...]         end
         | defmodule B do           defstruct [...]         end
         | defprotocol C do           def foo(a, b)         end
         | defimpl C, for: Any do           def foo(x1 = %m1{}, x2 =
         | %m2{})             Module.concat(m1, m2).foo(x1, x2)
         | end         end         defmodule A.A do           def foo...
         | end         defmodule A.B do           def foo...
        
           | sandbags wrote:
           | Ah, this is very neat.
        
             | dnautics wrote:
             | yep. pattern matching on the `__struct__` sugar, the poor
             | man's protocol!
        
       | tekacs wrote:
       | > Now Elixir has an equivalent to multi, the Protocol.
       | 
       | For what it's worth, Clojure also has a much closer fit to Elixir
       | Protocols called... a Protocol.
       | 
       | https://www.braveclojure.com/multimethods-records-protocols/...
       | 
       | They too can only dispatch on the type of the first argument, but
       | are more structured (you can add multiple pieces of behavior at a
       | time) and performant than multimethods where that's the behavior
       | you're looking for.
        
         | didibus wrote:
         | Elixir's Protocols actually were inspired by Clojure Protocols.
         | 
         | Here's Jose Valim talking about it:
         | 
         | > I've learned a lot also from Clojure because, at the time I
         | was thinking about Elixir, Clojure was already around. I like
         | to say it's one of the top three influences in Elixir
         | 
         | [...]
         | 
         | > The main, the top three influences are Erlang, Ruby, and
         | Clojure.
         | 
         | [...]
         | 
         | > I was like, no, but I'm going to call them protocols because
         | there are a lot of similarities between Clojure and Elixir in
         | terms of them being dynamic languages and in terms of the macro
         | system. I was like, okay, I'm going to call them protocols
         | because the closest thing we have today to what I want is
         | Clojure
         | 
         | And he goes on talking about more inspiration and similarities
         | from Clojure like Agents, etc.
         | 
         | Full exert is here: http://blog.cognitect.com/cognicast/120
        
         | tekacs wrote:
         | I'll also leave these here, in case the conversation inevitably
         | turns to pattern-matched function definition in Elixir. :)
         | 
         | https://github.com/clojure/core.match -- pattern matching as a
         | library
         | 
         | https://github.com/killme2008/defun -- using core.match to
         | implement Elixir/Erlang-like function definition
         | 
         | https://github.com/noprompt/meander -- advanced pattern
         | matching, for some fun and flavor :)
         | 
         | What's also fun is that core.match is implemented using a paper
         | from INRIA on how to efficiently convert patterns into decision
         | trees:
         | 
         | https://github.com/clojure/core.match/wiki/Understanding-the...
        
           | jwhitlark wrote:
           | I've always loved that paper. Very readable, and gives good
           | insights.
        
           | SatvikBeri wrote:
           | If videos are more your speed, David Nolen, the primary
           | author of that library (and article) has a talk about it as
           | well: https://www.youtube.com/watch?v=TVJa-V6U-XI
        
       | ollysb wrote:
       | https://github.com/OvermindDL1/protocol_ex gives you protocols
       | with full pattern matching.
        
         | sandbags wrote:
         | Brilliant, thank you.
         | 
         | I assumed that, with Elixir macro support, someone could
         | implement protocols with full pattern matching. Just way above
         | my current pay grade!
        
       | dmitriid wrote:
       | It's one of those "rarely used in practice but insanely
       | frustrating when you write a library or some generalized code".
       | 
       | However, I'd rather Clojure got proper pattern-matching than
       | Elixir multimethods. I find pattern matching a much more
       | powerful, flexible and useful tool.
        
         | OliverM wrote:
         | Why not just use core.match?
         | https://github.com/clojure/core.match
        
       | rainygold wrote:
       | Feels like Elixir has stolen much of Clojure's appeal and
       | 'thunder' as the niche pragmatic functional language.
        
         | arvidkahl wrote:
         | The ruby-like syntax and the VERY open and newbie-friendly
         | community have definitely contributed to this.
         | 
         | I've been to Elixir conferences, and they felt like people were
         | just encouraging each other to build solid software WITH each
         | other. I've not seen this level of camaraderie for other
         | programming language communities.
         | 
         | Elixir devs -- and I am super biased here -- are a special
         | bunch :)
        
           | uDontKnowMe wrote:
           | That's great to hear! I get the same feeling towards the
           | Clojure community as well, some of the friendliest, smartest
           | and most helpful people hanging out at the Clojure watering
           | holes (in comparison to other languages I've worked with). I
           | also am constantly in awe of the output of the Clojure world.
           | There are like 3 or 4 great podcasts going, so many cool
           | projects being worked on, especially for a community which
           | seems to be sadly so small.
        
             | filoeleven wrote:
             | Which podcasts do you recommend?
        
               | uDontKnowMe wrote:
               | I like:
               | 
               | Defn: https://podtail.com/en/podcast/defn/
               | 
               | The REPL: https://www.therepl.net/episodes/ (Seems to
               | have gone quiet)
               | 
               | ClojureScript Podcast: https://clojurescriptpodcast.com/
               | 
               | Functional Design in Clojure: https://clojuredesign.club/
               | (Also seems to have gone quiet since December)
               | 
               | LispCast by Eric Normand: https://lispcast.com/
               | 
               | Cognitect, the company behind Clojure also has their own
               | podcast but I haven't found it to be that interesting
               | most of the time, at least yet:
               | https://www.cognitect.com/cognicast/index.html
               | 
               | Not specifically Clojure-related but has discussed a few
               | times including wit Rich Hickey (as well as other
               | unrelated great conversations!): CaSe https://www.case-
               | podcast.org/
               | 
               | Completely not at all about Clojure but great software
               | podcasts:
               | 
               | Go Time: Even though I hardly ever write Go, I find their
               | conversations to be really great and having lessons
               | beyond Go. It helps that I am interested in the language
               | though: https://changelog.com/gotime
               | 
               | Web Development and Development in general - The Bike
               | Shed: https://www.bikeshed.fm/
               | 
               | Software Engineering Radio: https://www.se-radio.net/
               | 
               | CoRecursive: https://corecursive.com/
               | 
               | Inside Java: https://inside.java/
        
           | rainygold wrote:
           | Community can definitely play a role though I can't help but
           | think that Phoenix and the proselytizing done by Jose and co
           | are the main factors.
           | 
           | Sure, we have Luminus in the Clojureverse but its just not as
           | easy and straightforward as the Rails-like experience of
           | Phoenix. You don't have Hickey personally responding to
           | comments on HN/Reddit etc.
        
             | KingMob wrote:
             | Hickey is extremely remote from the Clojure community. Most
             | of Cognitect is. Really, only Alex Miller engages on a
             | regular basis. To a lesser extent, Fogus and Ghadi do, too.
             | 
             | The Clojurescript community is friendlier, IMO.
        
               | rainygold wrote:
               | Much to the detriment of the language imo, and he didn't
               | help the feeling when he released 'Open Source is not
               | about you'
        
               | uDontKnowMe wrote:
               | I would agree here that the combination of being "closed
               | to collaboration", the slow pace of development lately,
               | and really infrequent communication from the sole
               | owner/leader/BDFL does send a weird vibe and raises some
               | concern regarding what direction the language is going to
               | be going in in the future.
        
               | jshen wrote:
               | Isn't one of the beauties of lisp is that you don't need
               | much from the language creator. It should be far more
               | stable than non-lisp languages, and you can implement
               | most ideas with macros outside of the core language.
        
               | uDontKnowMe wrote:
               | You can get a pretty long way but there are still things
               | that need to be improved over time. For example Clojure
               | still 7 years after the java 8 release doesn't have great
               | integration with java 8 functional interfaces, which is a
               | pretty big detriment to java interop. I saw this patch
               | which seems to have been submitted by a community member
               | https://clojure.atlassian.net/browse/CLJ-2637 (not sure
               | if the author is a core contributor or what), but even
               | after month no comment from Rich or anyone else on the
               | team to indicate if this is a good idea, if they'd let it
               | in or what.
        
             | didibus wrote:
             | For the most part, Clojure is tuned for experienced
             | developers I think. It's kind of an oximoron, but it feels
             | like it was Rich Hickey's goal as well, to not appeal to
             | any of the "easy" and "convenient" and "familiar", but
             | focus entirely in "no bs", "simple" and "very flexible"
             | pieces that never break backwards compatibility, are always
             | open for extension, keep performance in mind, reaches for
             | battle tested hosts when it can, and all that.
        
           | didibus wrote:
           | There's a big downside to Clojure having the most amount of
           | experienced developers I think in bringing beginners in.
           | You'd think it be the opposite, but beginners are better
           | treated by other passionate smart beginners and people who
           | just got out of being a beginner. As experienced old devs
           | tend to not have the time or patience or not know how to
           | explain things or make it beginner friendly.
        
         | brianberns wrote:
         | To me, F# is the pragmatic functional language with the most
         | appeal, but being on .NET maybe it's not even niche.
        
         | sandbags wrote:
         | Honestly I wouldn't be using Elixir if it wasn't for my co-
         | founder's singing the praises of Phoenix & Liveview. I'd tried
         | it once about a year ago but couldn't see any advantage over
         | Clojure (esp. with re-frame). Sadly he was never going to move
         | to Clojure.
         | 
         | That said, now I've dug in and really used it for solving some
         | problems I am finding it an elegant and enjoyable experience.
         | 
         | I'd happily use either although I think Elixir has a particular
         | fit to web applications.
        
         | dgb23 wrote:
         | Elixir seems to be very approachable. But some of the strengths
         | of Clojure are unmatched, such as Java/JS interop, isomorphic
         | code for web development, and generally being a Lisp (which
         | includes macros).
        
           | Zababa wrote:
           | Elixir has macros. People are currently building Nx
           | https://github.com/elixir-nx/nx while not having to change
           | anything in the language. Java/JS interop being unmatched is
           | true, but Elixir has Erlang interop too.
        
           | rainygold wrote:
           | LiveView sorta tackles the isomorphic web development side,
           | and while I agree that Lisp is a better syntax you do have
           | hygienic macros in Elixir as well.
        
           | lawn wrote:
           | Elixir has macros too.
        
           | nesarkvechnep wrote:
           | Elixir has Erlang interop. Erlang is a 30 year old language.
        
             | adamkittelson wrote:
             | Yes and no. Yeah Erlang has been around for 30 years but
             | "30 year old language" makes it sound like it came out 30
             | years ago and then stopped. Erlang is still being very
             | actively developed and improved, it's by no means a crusty
             | old language.
        
               | prophesi wrote:
               | I'm not sure what the implications are of either comment.
               | Both Java and Javascript are reaching the 30 year old
               | mark as well.
        
         | vendiddy wrote:
         | Elixir afaik has taken a lot of inspiration from clojure and
         | lisp type languages.
         | 
         | It's not readily apparent from the ruby like syntax though.
        
       | kopos wrote:
       | Having worked with both to create the same system (building a
       | game server) I've found Clojure actually sits better with the
       | functional thinking style (1 data structure, 100 functions).
       | 
       | While Phoenix was the killer app for Elixir, and Elixir has far
       | superior readability (using the Ruby syntax); there were couple
       | of things that were off-putting and I struggled with them.
       | 
       | 1. everything is inside a module was an unnecessary distraction
       | 
       | 2. And then the separation between anonymous and named functions
       | simply were unnecessary
       | 
       | 3. And that I would have to declare the data / record inside a
       | module (??)
       | 
       | Elixir felt like a functional language un-necessarily trying to
       | look like a class based language.
       | 
       | I sometimes feel that had Elixir had only supported functions
       | outside of modules... oh that freedom.
       | 
       | But some of the thought that went into Flow, Channels (which has
       | become the de riguere now), mix (developer ergonomics ftw), those
       | micro-second latency responses, distillery are still too classy
       | and amazing.
        
         | jeremyjh wrote:
         | > Elixir felt like a functional language un-necessarily trying
         | to look like a class based language.
         | 
         | Not really. Named functions live in modules because that is how
         | it is done in Erlang; Elixir is compiled to Erlang's abstract
         | syntax. In practice does anyone define Clojure functions
         | outside of a namespace? Haskell functions are always defined in
         | modules too, do you think they got that from class based
         | languages?
        
           | divs1210 wrote:
           | The problem here is that its inconvinient to define a
           | function at the Elixir REPL because it demands that it be put
           | inside a module.
           | 
           | Clojure REPLS allow switching the namespace, and anything you
           | define goes intoo the current namespace. So it is more
           | ergonomic.
        
             | tomjakubowski wrote:
             | IEx will let you define a module at the REPL. Combine that
             | with a macro (exercise for reader) in your .iex.exs which
             | expands a function into a module definition and imports it
             | and you're in business.                   iex(1)> defmodule
             | Foo, do: def bar(x), do: x + 1         {:module, Foo,
             | <<70, 79, 82, 49, 0, 0, 4, 192, 66, 69, 65, 77, 65, 116,
             | 85, 56, 0, 0, 0, 135,            0, 0, 0, 15, 10, 69, 108,
             | 105, 120, 105, 114, 46, 70, 111, 111, 8, 95, 95,
             | 105, 110, 102, 111, 95, 95, 10, 97, 116, ...>>, {:bar, 1}}
             | iex(2)> Foo.bar(1)         2                  iex(3)>
             | import Foo         Foo         iex(4)> bar(1)         2
        
               | divs1210 wrote:
               | Yup, like I said, not as ergonomic as Clojure.
               | 
               | In clojure, it is:                   user> (defn bar [x]
               | (+ x 1))
               | 
               | If you want it inside a namespace named foo, then it is:
               | user> (in-ns 'foo)         foo> (defn bar [x] (+ x 1))
        
               | jeremyjh wrote:
               | I agree Clojure has a better REPL experience than Elixir.
               | But in Elixir REPL for a quick and dirty function you'd
               | probably just do                   >bar = fn x -> x + 1
               | end
               | 
               | The most unfortunate thing though is then you have to
               | have a different calling convention. Its the greatest
               | flaw in Elixir by far but they didn't have a reasonable
               | alternative given the constraints of Erlang.
               | 
               | Still for defining a named function in the REPL its the
               | same in Haskell and most other languages I believe that
               | you can't define a new named function or add a function
               | to a module in the REPL, though at least in Haskell the
               | calling convention for a variable bound to a lambda is
               | the same as for a named top-level function. LISPs have
               | always had a different notion of how the REPL integrates
               | into the development experience of a running program, and
               | I don't think its really been replicated elsewhere.
        
         | sergiomattei wrote:
         | I had most of these concerns when I was early learning the
         | language. I found it annoying to have everything in modules.
         | Now, however, I've come to appreciate the organization and
         | structure that this forces upon the programmer.
         | 
         | It makes me structure my code and group related concerns at
         | time of writing. I now code my functions as a working
         | collective rather than individual items.
         | 
         | And with .exs files, you can have multiple modules in one file
         | for quick scripting.[0]
         | 
         | [0]https://github.com/matteing/stack/blob/main/server/boilerpla
         | ...
        
           | brightball wrote:
           | This was one of my big impressions of Elixir. It forces you
           | into so many things that improve long term maintainability.
        
         | winrid wrote:
         | Sounds like you would love Nim.
         | 
         | You can just ignore modules/namespaces. While you have some
         | procedures private to the file, you can expose them and they're
         | just in the global namespace.
        
           | elcritch wrote:
           | Maybe my enjoyment with Nim is partly due to the (awesome!)
           | boringness of Elixir at times. I write Elixir code. It mostly
           | just works with a few simple abstractions. Nim's more fun for
           | MCU's and fast code where allocations count and I don't care
           | about scalability of the application as much. I rather enjoy
           | both.
        
         | divs1210 wrote:
         | I have had the same experience!
         | 
         | The distinction b/w anonymous and named functions is especially
         | icky.
         | 
         | I also agree that Elixir leads to more readable code, lots of
         | people in the Clojure community tend to write dense one liners
         | to appear "cool".
        
           | IggleSniggle wrote:
           | I have a feeling it's not to appear "cool," but because when
           | you're _writing_ code there is a tendency to prefer higher
           | density.
           | 
           | Why?
           | 
           | Because higher density makes it easier to see the entirety of
           | a context: more code on the screen makes it easier to spot
           | the relationships.
           | 
           | This happens in other languages too, of course, but it's easy
           | to see why Closure pushes flow in that direction.
        
         | sandbags wrote:
         | Like others all of my Clojure code was in namespaces so I see
         | it as a wash between the two. In practice I cannot imagine any
         | real app not making use of such modularity.
         | 
         | I too found the "." syntax for anonymous functions a bit
         | jarring at first. Why treat them differently? In practice I
         | don't even notice it now. It's never been confusing, it's just
         | a wart.
         | 
         | Also, I found the one-struct-per-module thing a bit odd to
         | begin with but in practice it makes a lot of sense. Also since
         | you can put modules inside modules it's no encumberance if you
         | want to declare a number of related structs. Again, once I was
         | used to it I apprecitated the simplicity.
         | 
         | I disagree with your characterisation: I perceive no "class-
         | based"'ness about Elixir. Do you have some examples? Perhaps
         | there is somethign I have missed. So far, given that it's not
         | exposing a class based system underneath, Elixir has seemed
         | even further from this than Clojure.
         | 
         | And I have, in general, found the tooling support friendlier
         | for Elixir. The only thing that I really gripe about is the
         | inability to communicate between editor and REPL.
        
       ___________________________________________________________________
       (page generated 2021-07-17 23:01 UTC)