HNHacker News
TopNewBestAskShowJobs

OvermindDL1

109 karma · joined April 11, 2015

Programmer of Elixir, Erlang, C++, Rust, OCaml, and far more.

[ my public key: https://keybase.io/overminddl1; my proof: https://keybase.io/overminddl1/sigs/_yjDPOb-btS5kW2IkjXrNSAZBKTST1Uxo6O9Y8F__VQ ]

submissionscomments
OvermindDL1··on Declined Proposal: A built-in Go error check function, “try”
Honestly when I look to rewriting a python thing to be 'faster' either try using PyPy first, or rewrite it in OCaml instead. OCaml is extremely simple, similar to python in a lot of ways (GIL and all), but runs at native code speeds, near C the majority of the work, and super easy to bind to C libraries if you need.

Or try Rust. ^.^

OvermindDL1··on Why am I interested in Elixir?
> AFAIK, you're relegated to rather primitive "println debugging" with Elixir - has this been an issue for you in practice?

Not at all. The traditional BEAM way of debugging is the tracing modules. For little things an `IEx.pry()` is often good enough though.

OvermindDL1··on I can see your local web servers
Wait, doesn't the certbot DNS challenge query the nameservers of the domain being checked, not your local DNS resolver, otherwise my fast DNS challenges should fail?
OvermindDL1··on Finance makes Apple and Google forced friends
Not in the United States it's not at least. Even just the recent net neutrality pubic votes don't match what was done in the slightest. The USA is an oligarchy through and through.
OvermindDL1··on Shutting Down Google+ for Consumers
Yep, the privacy and sending specific things to specific circles and all was spot-on in G+. Or even specific people, groups, even non-G+ emails.
OvermindDL1··on Elixir at PagerDuty
Elixir defines its parts as either 'Language Syntax', 'Special Forms', 'Kernel', 'Standard Library', and of course user code.

Things like a function call is language syntax. You cannot replace language syntax with anything else. Special forms are things like `for` and `with`, and you can replace these with syntax (though that's going the wrong direction in my opinion). Kernel are the standard library bits that are auto-imported into every module (unless explicitly told not to via `except:` or so), these cannot replace special forms or syntax. Etc...

The Pipe operator is just a normal macro in the Kernel, it is redefinable and in fact there are a surprisingly large amount of libraries that do (to make it more monadic interestingly, which makes me think Elixir needs a binding operator in kernel, perhaps `~>` or so).

Things like `fn`/`end` are language constructs, just no way around that at all.

The match operator `=`, interestingly enough, is a special form and not a language construct, so there are times that you can override it as well.

> except of course for Scheme, which is perfect :D

Take a look at Racket, it is scheme refined into bliss. ^.^

> Elixir has some inconsistencies, but I don't think they make the language "hard-to-read" in any realistic way.

Not overall 'hard-to-read' (not like Java for example), but definitely harder than Erlang I'd state.

OvermindDL1··on Elixir at PagerDuty
This is precisely how I think as well, some declaration like `let` or `var` or so to say "This is a new binding"
OvermindDL1··on Elixir at PagerDuty
`|>` would replace the great majority of need for multi-staged named variables.

In addition, naming variables like that in Erlang is a mis-design, the names should be more descriptive.

OvermindDL1··on Elixir at PagerDuty
Oh yes! Elchemy! How'd I forget about that one (I keep pushing it around!)! ^.^;

It is based on Elm so it has a severely limited type system but it is the most complete on Elixir so far. :-)

OvermindDL1··on Elixir at PagerDuty
Eh, as far as I know I'm the only one doing that, and even then only as an experiment/playground, and I don't have the time to work on it lately (have to pay the bills after all).

It's not compiling to elixir, but the `alpaca` language compiles to the BEAM (via erlang core I think) so it gets you close, although they are not black boxing messages sadly.

If you know of someone else doing typing experiments on top of elixir, please link me (my playground code is on my github repo somewhere)!!!

OvermindDL1··on Elixir at PagerDuty
It's unnecessary in the 'erlang' ecosystem because erlang doesn't have variable rebinding, Elixir 'does' have variable rebinding so it needs some way to distinguish between rebinding and matching, and it was decided to use `^` to mark matching, when honestly I think it would have been smarter to specify it (or something similar) as rebinding. In quite a few cases rebinding leads to bugs (accidentally rebinding something that you still need an old value of).
OvermindDL1··on Elixir at PagerDuty
It still doesn't do the same thing as the erlang code as the elixir example is being run at the staged compile-time instead of run-time like elixir's would be though. And a superfluous `ok` atom is being returned from the erlang code when its `io:fwrite/2` already returns it, plus why call fwrite instead of just write out an iolist directly?! o.O
OvermindDL1··on Elixir at PagerDuty
Entirely subjective yes! ^.^

However what you show is not focusing on syntax differences but rather function differences, even `|>` is an (macro) operator. By syntax I'm talking about things like the `do`/`end` and `fn`/`end` and `,do:`/`do...end` mismatches, things like atom key short-form of `someatom: ...` (being short for `:someatom => ...`) only being useful at the end of it's list/map context instead of everywhere (which is not ambiguous nor have any other reason not to do it that I can see), having functions be callable with or without parenthesis (of which thankfully the formatter default puts parenthesis) when functions really should be defined with or without parenthesis and their usage enforced as such, mis-matches in the AST (when creating macro's) by special casing things like 2-tuples among others, and the really weird multi-arity functions of `for` and `with` that really should have been done via body expressions instead of `,` separated expressions (and thus would not need to be special forms but could then just be normal macros, but they seem extremely out of place for the rest of the language syntax), etc.... etc... etc..

It's just a lot of little inconsistencies like that.

Also, if you want pipes for erlang look at the https://github.com/rabbitmq/erlando parse transform (there are others as well, but I like this one), and if you want a shorter erlang form then look at erl2 (just a layer on top of erlang to shorten constructs like module definitions), and of course nothing beats `lfe` on the beam for succinctness and defineability (being a lisp after all).

Also, your Elixir and Erlang codes do not do the same thing. Your Elixir code is being run at compile-time where your Erlang code is not executed at all, only compiled, and thus will only be run if something calls the `tok:start/0` function. The equivalent elixir would be (formatted by the Elixir formatter):

  ```elixir
    defmodule :tok do
        def start() do
            "Hello,How,Are,You,Today"
            |> String.split(",")
            |> Enum.join(".")
            |> IO.puts()
        end
    end
  ```
And you can leave off the final `:ok` on both as both `IO.puts/1` and `io:fwrite/2` both return the atom `ok` in the end. And even then these are not equal as you are working with charlists with one and binaries with the other, so a more direct translation of the Erlang code to Elixir would probably actually be:

  ```elixir
    defmodule :tok do
        def start() do
            'Hello,How,Are,You,Today'
            |> :string.tokens(',')
            |> :string.join('.')
            |> (&:io.fwrite('~s~n', [&1])).()
        end
    end
  ```
That would make the functions equal.

As an aside, a few other bits, Elixir defines if a function is public/private via `def`/`defp`, meaning you have to search through a file to see what is exposed, where in Erlang you can see exactly what is and everything that is exposed by just looking at the top.

And yes, `do`/`end` may be longer by one line than Erlang's sequence operator `,` usage, but I don't mind it to be honest, and you can replicate it in Elixir anyway kind of like:

  ```elixir
    def start(), do: (
        lst = :string.tokens('Hello,How,Are,You,Today', ',');
        :io.fwrite('~s~n', [:string.join(lst,',')]);
        :ok)
  ```
Essentially just replace erlang's `->` with `,do: (`, replace erlang's `,` with `;`, and finally replace erlang's `.` with `)`.

Comparing 'function' differences between them is useless of course, they can call each other functions (though macro's are another issue, erlang cannot 'usefully' call elixir macro's, but then again elixir may not soon be able to use erlang's parse transforms either), the differences are the syntax, and Elixir just has a whole ton of oddities.

Overall I find the Erlang syntax (which is similar to SML/OCaml/etc...) far more uniform, sensible, readable, and that it has far less surprising syntactical cases (like why can't I do something like `%{some_atom: 42, "string key" => 6.28}` in Elixir, blah... you have to do `%{"string key" => 6.28, some_atom: 42}` instead for who knows why reasons...).

I do of course use Elixir for my day job, have for over 2 years now, and these are just a few constant things that bug me on a day-to-day basis. However the tooling, macro's, and community (come join us on the Elixir Forums!!!) are top-notch!

If I had my 'choice' of mythical language though, I'd pick something like OCaml with Rust-style ownership semantics with a full staged macro system (Elixir's is a staged macro system) if it were not otherwise possible to safely add in a full Lisp-style macro system (I really don't think so in a full setup like these though, you need a staged system for various corner-case reasons).

OvermindDL1··on Elixir at PagerDuty
Entirely agreed. Elixir's Macro's are awesome, and Erlang could definitely use an Elixir-Macro-Like Parse Transform library (could definitely exist), Erlang's syntax I find far more readable, consistent, and logical as well. Elixirs syntax has a lot needless, hard-to-read, noise, but it's not hard to overcome the noise to get the benefits of the overall ecosystem and macros.
OvermindDL1··on Elixir at PagerDuty
Remote nodes have overhead, however if you can handle that overhead then you definitely should use a remote node or Port over a NIF. However, NIF's taking a long time to run is not so much of an issue anymore now that the dirty NIF scheduler is enabled by default in the BEAM.
OvermindDL1··on Things I Regret About Node.js [video]
They don't mean immutable as in language form, but immutable packaging system is the general form where you can add but not remove packages to it so as to not break things, which is the common form among most maven/cargo/hunter/etc.../etc... dependency packaging systems. It's generally considered that npm supporting deleting packages was a major mis-design, which became very public when a popular tiny package got deleted, which then broke so many things, so they learned that the hard way instead of learning from the systems that came before (obviously not cargo, but you get the drift ^.^).
OvermindDL1··on Why Does “=” Mean Assignment?
Javascript itself supports destructuing fine, here's some javascript straight from the firefox console:

    > let a = [1,2,3]
    undefined
    > [x,y,z] = a
    Array(3) [ 1, 2, 3 ]
    > x
    1
    > y
    2
    > z
    3
OvermindDL1··on Avoid Else, Return Early (2013)
But Elixir 'does' have early returns, they are known as `Guards` as a language construct.
OvermindDL1··on Elixir 1.5 released
Not really any 'build' way, but the 'patterns' of it are more similar in that being immutable, functional, and single-owner languages.
OvermindDL1··on Elixir 1.5 released
Java and C# outclass performance in raw CPU work certainly. Phoenix does not do raw CPU work however, it is primarily a web dispatcher on top of cowboy and the BEAM will run circles around both Java and C# systems if they are programmed to anywhere near the same quality of failure handling that the BEAM implicitly supplies (/me has worked with both Java and the BEAM for over 10 years).

Also, the Erlang VM is older than the JVM, initially created in the late 1980's. The JVM, according to wikipedia, was introduced in 1994. Also the BEAM has significantly better GC handling that both the JVM and .NET both since it has a segmented memory model (each actor has segmented memory) unlike the JVM and .NET's monolithic Heap's, this allows it to perform vast optimizations that ensure that the GC is almost never called yet memory is properly and fully reclaimed due to the bounds of the individual Actor heaps, and even when the GC is called it does not stop-the-world or anything of the sort and has multiple layers of GC's that run for specific cases, the system stays running even as the GC's (rarely) runs. The average GC run time even when it does run is measured in the single-digit 'micro'seconds. If anything the BEAM VM is not only just much older than the JVM and .NET VM's, but also more advanced.

OvermindDL1··on Elixir 1.5 released
I've been working with the BEAM (via Erlang) for over a decade, and with Elixir for almost 1.5 years, and I'd still give up, well, probably my current job if I could get a fully Hindley-Milner Typed Elixir...
OvermindDL1··on Elixir 1.5 released
Bucklescript works fantastic in the Elixir system (I have a bucklescript-tea library that maps Elm code 'almost' verbatum to Bucklescript code too).

There is an ElixirScript project in current dev, still early but usable, that compiles Elixir code to javascript too.

OvermindDL1··on Elixir 1.5 released
I use it for everything from bots to interacting with and controlling Java and Python programs and a lot more. The concurrency abilities of the BEAM have a lot of applications.
OvermindDL1··on Elixir 1.5 released
> For single a web api server Elixir is going to be far behind, performance wise, against nodejs, the JVM and Go.

To some Go web api frameworks perhaps.

To the JVM, not really. The frameworks I used with it in the past (spring/play/coupleOtherSmallOnes) are throttled to the number of threads for concurrent connections. The BEAM (Erlang/Elixir) has no such limitation and it blew away my old Java servers handily just due to its concurrency alone.

And not to nodejs at all. Running a single BEAM vs a single node there is no comparison, the BEAM runs circles around it. With nodejs you can shard it out to multiple running instances to get concurrency better but you run into OS limits far before the workload that the BEAM can handle.

OvermindDL1··on Elixir 1.5 released
With the Rustler Rust library, almost blissfully easy. I highly recommend it.
OvermindDL1··on How Discord Scaled Elixir to 5M Concurrent Users
For note, luerl is more of a library for erlang/elixir/BEAM and not a full language, as it is basically just lua's interpreter rewritten in erlang with some modifications to make it fit the system a bit better than normal Lua (there is normal Lua available via a Port though).
OvermindDL1··on How Discord Scaled Elixir to 5M Concurrent Users
Actually you'd be surprised at just how fast the BEAM passes messages, especially as it also includes linking, monitoring, cross-process, cross-system, among other features. When creating a multi-thread atomic messaging system in C++ long ago I was able to out-perform the BEAM (though I'd not rank it as significantly out-perform), but once I added failure handling features among others then it never got close to BEAM's speed again in raw message passing.

However, the BEAM is not very fast on executing actual code, it is like Python in that way where it is good to slave out CPU-heavy work; the BEAM is built for async IO, and yes, running a JVM (or C++) system as a node on a BEAM mesh is fantastic for that (or a port, or NIF for small work).

OvermindDL1··on Programming languages that are actively developed on GitHub
Elixir has a little bit of Erlang in the compiler but at this point it would be fairly trivial to replace it with pure elixir, and most of the compiler is elixir already. However, Elixir does compile down to the EVM/BEAM (Erlang Virtual Machine) without using Erlang as a go-through. I'd argue that Elixir is 'mostly self-hosted'.
OvermindDL1··on Comparing Haskell and Node concurrency performance
Though, to be honest, most Erlang/Elixir devs would never think of using something like ZeroMQ as Erlang has more powerful and built in alternatives, or something like the Elixir Phoenix web framework that has built in much more powerful functionality. That seems to be an aspect of knowing the tools, easy to miss if you are new to the Erlang ecosystem. :-)
OvermindDL1··on Elm is Wrong
It seems most of his issues stem from the language and the FFI, not necessarily the TEA style 'library' (which he claims is 'great' at the start). There is a Haskell -> JS compiler and an OCaml -> JS compiler, as well as Bucklescript, which is another OCaml -> JS compiler but actually outputs very normal looking and readable JS, probably be better to use those.

Consequently I had many of the same complaints, though not quite to the extent or wording he does, so I made my own TEA-like library on Bucklescript/OCaml and ported many of the Elm examples to it, most were basic copy/pastes with the most minor of syntactical differences (`with` instead of `|` and so forth, basically Elm->OCaml differences), I have it up (with code link) at http://overminddl1.com/bucklescript/ if anyone is curious. Not production worthy by any stretch but I do clean it up and add more and more to it over time, already can do near all that Elm's libraries can do, in addition to some of the community libraries.

Continuing on the article, he basically re-implemented OCaml's Witness style (done via OCaml's modules), it was fascinating watching someone build it in Elm I must admit.

He does focus too much on typeclasses, the witnesses he wrote is the way OCaml does it (although with a bit less syntax, and much more an upcoming update), which is not a typeclass form, but something similar.

An aside, where he mentions 'If you don’t want to read the essay, SYTC essentially says “hey, why don’t we pass around an object that describes the implementation of the contract that we care about, rather than having the compiler infer it for us?”. If you’re familiar with Scala, this is how they implement typeclasses in terms of implicit parameters. If you’re not, SYTC is equivalent to passing around a vtable whenever you want to invoke code on a dynamic target.', that is just what OCaml is doing in a soon-coming version with its implicit modules. Definitely looking forward to that, even if they are just fluff. They are basically like Scala's implicit parameters but with type lookup based on module definitions, still explicit, but significantly reduces the code required to be written.

← PreviousPage 2 of 3Next →