1. 3

    Best price per performance is a very important server metric. Does this telegraph a move into the server space?

    1. 8

      ARM on AWS is already extremely competitive and for many workloads is more cost efficient.

      1. 1

        Not everyone has AWS’ scale to make their own chips. Seems like the little guys might consider buying chips from Apple.

        1. 2

          I like the idea, but I don’t see Apple earnestly moving into a space unless they really find it exciting. And they just don’t love the backend world; the company treats it like a chore.

          1. 1

            Not everyone has AWS’ scale to make their own chips. Seems like the little guys might consider buying chips from Apple.

            Given how much Apple is positioning first-party silicon as a differentiator, it’s highly unlikely that they’d sell chips to anyone else. Even if they did, there’s a lot of work to do to make this into a good datacenter chip. Phone, laptop, and tablet SoCs are a lot more similar to each other than any of them are to server SoCs.

            1. 1

              AWS chips use stock Arm cores, not any custom design. The only benefit of custom SoC for them is that they can integrate their “Nitro” peripherals (NIC/storage/security) onto the SoC directly.

              The little guys can buy Ampere (or Nuvia when that happens?) and enjoy better performance (I’m pretty sure Ampere Altra will clock higher than Graviton2 and it has more cores).

              Though of course it would be a dream if Apple did an ARM Xserve, with full ACPI standard support and everything :)

          2. 2

            Not a chance. Apple tolerates professional users who aren’t in media production, but they’re a consumer product company.

            1. 2

              Maybe for their own datacenters, but I don’t really see them getting back into selling them externally again.
              They kicked Xserve to the curb back in 2011 – I assume it just ended up not being worth it. Maybe one of: inability to differentiate in on a market segment that is typically only price sensitive (eg. server market is not really UI/UX driven), thinner margins, customers wanting long support lifetimes, longer product lifetimes to ensure capex… who knows?

              1. 9

                They kicked Xserve to the curb back in 2011 – I assume it just ended up not being worth it.

                The Xserve was built for a single customer: Pixar. Back in 2002, Steve Jobs was CEO of Pixar and Apple and, as Apple CEO, was telling the world that Apple made the fastest computer. At the same time, as Pixar CEO, he was buying huge numbers of Dell servers for his render farms. This was incredibly bad for Apple’s marketing. It made sense to create the Xserve so that Pixar could loudly tell everyone that they were buying Apple hardware for their render farms.

                Disney bought Pixar in 2006 and Jobs took a less active role. The last Xserves were released in 2009 and by then Apple was the iPhone company, no one cared if Pixar render farms used their hardware.

                1. 2

                  I never made that connection, and this makes a ton of sense. Thanks for sharing!

            1. 5

              pattern matching doesn’t work all that well

              Anybody know what the author means by this? I haven’t used Rust a whole lot but pattern matching seemed fine to me, other than having to add a few &s here and there to satisfy the compiler.

              1. 15

                In Rust, you can’t pattern match through Box<T> or Vec<T>. But you often need those indirection to implement recursive data types.

                That means that, practically, you are restricted to one-layer pattern matching for recursive types, and have to split deep matches into a series of nested shallow matches.

                1. 5

                  There is a nightly feature (box_patterns) that lets you match on boxes.

                  1. 6

                    Sadly, that isn’t generalizable, so marching on nested String, Vec, etc. remains cumbersome.

                    1. 1

                      Could you not match on the slice? Or perhaps I’m misunderstanding

                      1. 4

                        Say if you match on a variant that contains a Vec, you can’t match on that directly - you have to pull it out, then call as_slice on it.

                        1. 2

                          Oh yes! My eyes skipped over the word “nested”. Thank you

                        2. 2

                          To Rust, Vec is just a regular struct {len, capacity, pointer}, so that’s what it’s pattern-matching on, not its elements.

                          For values at the top level you can usually easily transform them like match vec.as_slice() {}, but if you want to match a nested value, there’s no room for that:

                          match compound_value {
                             Foo(Bar([first, ..])) => …
                          }
                          

                          Then in Foo(Bar(Vec)) Rust doesn’t know how to match on Vec‘s content. There’s no language feature to explain that [first, ..] should compile to first = vec.remove(0) or that it should perform vec.as_slice() before matching.

                          1. 1

                            I think match_default_bindings might do this.

                            1. 2

                              match_default_bindings (match ergonomics RFC) is for now only a syntax sugar that makes patterns forgiving about missing ref or &, but the actual behavior stays the same, with the same fundamental limitations.

                              Specifically moving out of a Vec is far off, as it depends on DerefMove, which is at the stage of “hmm, maybe we should have something like that, but not sure how to pull that off”.

                      2. 2

                        I think they are now preferring match_default_bindings, but I could be wrong. This is definitely a pain for me as a language implementer. :(

                    2. 7

                      It’s discussed on the other post at https://blog.darklang.com/first-thoughts-on-rust-vs-ocaml/#pattern-matching.

                      That section is just a summary of the last post, sorry for the confusion!

                    1. 10

                      Seems entirely fair: author doesn’t need the low-level control and performance that Rust offers, and prefers ease and flexibility that comes from having a GC in the language.

                      1. 14

                        I think Rust is a wonderful community, ecosystem, and tooling, wrapping a language that nicely solves a problem very few of us have.

                        This is my feeling exactly. I think it is head and shoulders above the alternatives in the space it’s in, but I have never needed to work in that space, because for the problems I work on, the downsides of GC tends to be irrelevant.

                        I am very glad it exists, because it prevents more new code from being written in C and C++. I just don’t have a use for it myself.

                        1. 2

                          And not just GC per se. I have written very little code in the last decade that would have benefitted from Rust’s ownership model (which to me is the language’s killer feature) so there would be no payoff from the added cognitive overhead.

                          I’ve worked on low-level code bases earlier in my career that would have been great fits for Rust had it existed (lots of parallelism and mutable shared state that needed careful lock management and disciplined adherence to order-of-operations rules) so I’m well aware of the pain points it addresses, but it appears to bring very little of use to the table for a lot of software.

                          The right tool for the job!

                          1. 8

                            And not just GC per se. I have written very little code in the last decade that would have benefitted from Rust’s ownership model (which to me is the language’s killer feature) so there would be no payoff from the added cognitive overhead.

                            Hm, interesting, because I see that very differently: I write a lot of code where “handing from one component to another” is a fundamental operation that Rust makes strict. Think “write this to a channel/database/etc., invalidating usage on my side”.

                            I could live without borrowed references and with pervasive and more ergonomic smart pointers much more.

                            1. 6

                              I suspect this is a matter of personal taste. I’m working on a high level project now and I’m not finding Rust’s ownership any more hassle now that I’m comfortable with the language, and web applications ported from Go became less code + easier to work with.

                              It was however a real pain learning how to use Rust because of ownership.

                              1. 1

                                And not just GC per se. I have written very little code in the last decade that would have benefitted from Rust’s ownership model (which to me is the language’s killer feature)

                                Interesting; having not used Rust, I assumed that the ownership model existed primarily in order to support avoiding GC. Is there more to it than that? I guess it can also solve data race conditions when sharing mutable data across threads? (another problem I don’t have, because I never write concurrent code without immutable data structures!)

                                1. 3

                                  Single ownership gives you automatic and deterministic resource cleanup as a side effect. You don’t need to remember to write defer f.close() or be limited to a single scope with f.open().

                                  Another benefit is that you don’t have shared mutable state, but you don’t have to go all the way to purely immutable. Exclusive owners can mutate their data without causing side effects. This helps understanding what is going on in a program: if I pass an object to a function is it going to keep a copy or reference the original? Can I mutate that object afterwards? Always clear with ownership.

                                  1. 3

                                    Sure but there are other languages where you do not need to remember these things either or have shared mutable state. I think F# is a sweet spot because I can do ~90% immutable ~10% mutable code and it just works extremely well. The 10% mutability happens in a short context and I never give out mutable references. Having to deal with mutability or disposable things in a small amount of your code is doable and I do not need to fight with the compiler to get basic code to work (as opposed to Rust).

                                    I pass an object to a function is it going to keep a copy or reference the original? Can I mutate that object afterwards?

                                    These are sort of questions we do not need to ask with F# either.

                                  2. 1

                                    Rust used to have a GC, in its early days (@T), so it can’t be just that. I don’t know if there is an official answer to “why rust”. There is a section in the old FAQ about the garbage collector that tells a bit more about the other benefits of tracking ownership: https://prev.rust-lang.org/en-US/faq.html#is-rust-garbage-collected (got to scroll up a bit because the “try the new site” banner hides the start of the section).

                                    Apart from the matter of concurrency, there’s also non-memory resources (like file handles), which get tracked like memory.

                            1. 2

                              What is the motivation behind Gleam? Are there different design choices that you wanted to explore compared to Elixir?

                              1. 5

                                I believe the big one is a static type system, but there’s more on the Gleam website: https://gleam.run/

                                1. 3

                                  Like Elixir it aims to bring a new style of programming to the Erlang VM.

                                  Elixir polymorphism and metaprogramming inspired by Clojure, and Ruby. Gleam brings type safety and static analysis inspired by Elm, OCaml, and Rust.

                                1. 5

                                  Not sure if I’m misunderstanding something, but sounds like you’re planning on re-implementing OTP in Gleam? Which would be impressive, but also sounds like users will not be able to make use of the awesomeness of Erlang OTP. Or will you be able to bridge the Gleam abstractions to Erlang’s OTP?

                                  1. 1

                                    We have reimplemented OTP in Gleam, yes.

                                    I tried to explain in the article that it maintains full compatibility with Erlang’s OTP (in the “primary goals” section) so Gleam users can use Erlang OTP and Erlang users can use Gleam OTP transparently and without problems. Sorry if I didn’t make that clear!

                                    1. 2

                                      On re-reading, yes it is clear! I was probably just too surprised to fully take it in. Again — impressive!

                                  1. 7

                                    Gleam is my favorite new language in 2020. I hope it is taking off.

                                    1. 3

                                      Thank you!

                                    1. 4

                                      Looks really good. I like that the syntax is basically rust/ML, on the Beam runtime. I wonder if there’ll be a way to write reasonably self-contained programs with it (a bit like deno does for javascript), especially since the compiler is in rust?

                                      1. 5

                                        You still will need BEAM runtime. Doesn’t matter what is the language the compiler is written in, the output is what matters

                                        1. 2

                                          Maybe the beam runtime can be linked against a rust-compiled binary? Deno uses bindings to V8 to do the equivalent with javascript.

                                          1. 2

                                            I couldn’t say whats possible there, I’m not a C programmer and I’ve not looked into this. It would be a very cool feature though! Maybe one day

                                            1. 2

                                              I have been meaning to see if Gleam will run on https://github.com/lumen/lumen a BEAM VM written in Rust that targets Wasm.

                                              1. 2

                                                I intend to investigate this future. I’ve had some quick chats with the Lumen devs and it sounds like it would work nicely.

                                                One of the main things I’m interested in is providing additional type information to Lumen so that they can enable type based optimsations. This would make Gleam on Lumen outperform Erlang on Lumen, which is an exciting idea!

                                                1. 1

                                                  What are some mechanisms to deliver type information to the VM? Could it be generalized so that other languages on the BEAM could also benefit?

                                                  1. 1

                                                    At present there’s no type based optimisations AFAIK on the BEAM or Lumen, but Lumen’s dev team said they may be able to add an API for this at a later date. Gleam and Lumen are both written in Rust so I could imagine Gleam having a backend that generated type annotated Lumen IR.

                                                    1. 1

                                                      Right, but I was thinking of a how to encode the type information in-band so that other typed languages on the Beam could also take advantage of any possible speedups.

                                                      Like if a module had a Map(Fn => TypeTuple{}) if it exists, the alternative Beam implementation (Lumen in this case) could use it, it might even be a way to provide entirely alternate implementations for functions, it could be a Map(Fn => WasmBlob) and implement BIFS.

                                            2. 1

                                              There is no fully working BEAM runtime implemented in Rust right now. AFAIK Lumen is still in progress and other implementations didn’t lift off.

                                              EDIT: And releases (the deployment units in Erlang) often contains BEAM implementation provided, so if you build release for your target machine and the external libraries have compatible versions (libc and OpenSSL) then it should work with plain tarball of release.

                                              1. 2

                                                I was more thinking of binding against an existing BEAM runtime, like deno does with V8 :-)

                                                1. 3

                                                  The BEAM was not designed to be embeddable like JS engines.

                                                  If you just want self-contained apps, “releases” are that.

                                                  1. 1

                                                    They’re not really self contained in the way that a static binary is, they depend on libraries being installed on the host.

                                          2. 2

                                            What’s the appeal of shipping a completely static binary? I don’t think it’s hard to just install Erlang or include in your package.

                                            1. 5

                                              A lot of people say that their favorite feature of Go is that it gives you a single static binary, which is easy to copy around. I think that’s a good argument, particularly after seeing what node_modules and pip directories look like.

                                              1. 3

                                                Hmmmm, maybe I’m from a different world here, where foopkg add libfoo or tar cvf foo.tar foo.js node_modules/npm install isn’t a hard thing to do, and shipping libraries/vendoring them if you REALLY hate that is common practice on Windows anyways.

                                                1. 6

                                                  If you are to redistribute your solution (in binary form) to into various, separate, customer (or internal enterprise) environment running, different versions or patches of OSes,

                                                  would > foopkg add libfoo or tar cvf foo.tar foo.js node_modules/npm install isn’t a hard thing to do, and shipping libraries/vendoring them

                                                  be as convenient as a single binary distribution ?

                                                  1. 2

                                                    That approach is possible but you’d also need to ensure that the right C libraries are installed on the target machine too. It’s all doable but it requires additional work and a degree of technical knowledge compared to “copy this to your computer and double click on it”

                                                  2. 3

                                                    isn’t this what containers are for these days? Can’t you just ship a docker or flatpak (or the mac/windows equivalent) and be done with it?

                                                    1. 3

                                                      They do a good job for many uses cases but there are limitations. They require more technical knowledge to install and run than a file you can double click on, and there are performance + access implications of running software inside a container.

                                                    2. 1

                                                      after seeing what node_modules […] directories look like

                                                      On a related tangent, we’re starting to use webpack to bundle files for NodeJS apps at work, which so far seems to be worth it for us. (No minification though, that would be awful.)

                                                      I’ve seen a couple hundred MB node_modules result in around 10-20MB unminified bundle files. Deployment goes faster with one moderately big file than 100ks of tiny files. In the process we dropped the need for production to run npm install --production. Also in particular we see Azure app service is really slow at reading lots of small files: bundling reduced start up time for some services from ~30s to ~5s.

                                                      So I think bundling things into a smaller number of files makes deployments nicer even when that smaller number isn’t as small as 1.

                                                      In both the before-bundling and after-bundling states we have been doing installations using a single zip file: what changed is mainly the number of files in it.

                                                1. 5

                                                  A really interesting and clear iterview! Thank you.

                                                  That stack usage static analysis is interesting. Does it have a way of verifying that the C annotation is correct, or is that a matter of trust? Also does the static analysis behave differently on different platforms? As stack sizes may be different.

                                                  1. 19

                                                    Thanks for sharing this! I’m the author of Gleam (and this post). Very happy to answer any questions :)

                                                    1. 6

                                                      Thank you for your work on Gleam! It looks really promising, and it’s been great seeing it progress from the sideline.

                                                      Is it easy to integrate it (e.g. writing one module in Gleam) in an existing Erlang + rebar3 project? (Is this documented somewhere?)

                                                      1. 7

                                                        Yes for sure. Currently we don’t have a dedicated build tool so all Gleam projects are rebar3 projects with a project plugin (https://github.com/gleam-lang/rebar_gleam), so compilation of Erlang works as per usual.

                                                        There’s also a mix plugin for Elixir projects (https://github.com/gleam-lang/mix_gleam).

                                                        The tooling is a bit rough-and-ready at the moment, I’m hoping to improve it in the near future.

                                                    1. 7

                                                      I think what this comes down to is that there isn’t a great language for building languages :-/

                                                      OCaml is supposed to be that language, and I even wrote in ~2015 on my website that I would write all future language projects in OCaml. Yet I didn’t go down that path for Oil, and I don’t regret it.

                                                      Instead I came up with this somewhat weird Python + ASDL + multiple code generator combo, but it has worked out well, and compiles to nice C++.

                                                      It’s both low level and high level at the same time. Languages need both because they’re extremely repetitive tree matching on the one hand, and very performance sensitive on the other (which I learned the hard way).


                                                      A few more threads about metalanguages, with extensive comments on using Rust to implement languages:

                                                      https://old.reddit.com/r/ProgrammingLanguages/comments/bkohba/what_language_did_you_use_to_implement_your/

                                                      https://old.reddit.com/r/ProgrammingLanguages/comments/ays7d7/languages_used_to_implement_compilers/

                                                      https://notamonadtutorial.com/an-interview-with-the-creator-of-gleam-an-ml-like-language-for-the-erlang-vm-with-a-compiler-e94775f60dc7


                                                      This is the programmer’s version of Guy Steele’s computer science complaint: https://www.youtube.com/watch?v=7HKbjYqqPPQ

                                                      That is, that the language used for describing languages is horribly imprecise and inconsistent.

                                                      1. 5

                                                        I guess it is supposed to be Racket … and yet often it doesn’t seem to play out that way.

                                                        As an outside observer, I wonder why that is.

                                                        1. 7

                                                          Yes exactly, Racket is supposed to be a language for languages. A bunch of reasons that I see:

                                                          1. Performance. As mentioned, I learned the hard way how performance-sensitive languages are. Racket was a CPython-like interpreter in C until recently: https://blog.racket-lang.org/2020/02/racket-on-chez-status.html

                                                          I wrote Oil in Python and it was way too slow. Racket would have been also too slow, and even with the new runtime, I doubt it would be fast for parsing shell. JITs tend to speed up numeric workloads more than string workloads. String workloads are dominated by allocations and the JIT may not see through those.

                                                          1. Algebraic data types. I’m not up to date on what Racket offers here, but all the Lispy mechanisms I’ve seen fall somewhat short of the real thing. Algebraic data types really help when dealing with languages. They affect 50-80% of the lines of code. Compilers and interpreters are full of conditionals, and it’s a huge help to encode those as data rather than code you have to step through.

                                                          2. Static types help too. Oil started out dynamically typed and is now statically typed with MyPy.

                                                          3. Syntax. Racket does support syntax unlike other lisps, but I think it’s not culturally there, and the support for parsing is relatively weak. For example, the C ecosystem has re2c, which I used in Oil, etc. The Python ecosystem has a number of options for parsing as well.

                                                          4. Runtime dependencies (for interpreters). As far as I call, the Shill shell (a research project) was written with Racket. But then they switched to something else because the runtime got in the way.

                                                          5. Build time dependencies (for compilers). Compilers are often bootstrapped in a unique way – e.g. Go compilers in Go, Rust in Rust, Zig in Zig, Clang in C++, etc. Compiler writers want to use their own language, and not someone else’s.

                                                          So in all of those areas, OCaml and Rust beat Racket IMO. And on top of that, I agree with the downsides about both OCaml and Rust. (Not that my own solution doesn’t have a lot of downsides. The important thing is that they’re all fixable because the code is small and under my control!)

                                                          I think Racket is probably very nice for prototyping languages. I’m not sure it’s good for production quality implementations, at least when you’re talking about competitors to CPython, LLVM, rustc, Go, Julia, etc.

                                                          Julia was bootstrapped in femtolisp though, which is interesting. I hacked on it at the beginning of Oil, but decided I didn’t like that style.

                                                        2. 3

                                                          From my perspective, as someone who’s spent the past 5 years doing more pure functional programming (Elm and Haskell) professionally than anything else, and who’s been working on a compiler written in Rust outside work…I would gladly describe Rust as “great for building languages.”

                                                          The learning curve was substantial, but now that I’m comfortable with Rust, I don’t think anyone could sell me on OCaml or Haskell (or any other language I’ve heard of) as a better choice for building a compiler.

                                                          Granted, that’s in large part because execution speed is extremely important to me. I have very high standards for how fast I think a compiler should run!

                                                          1. 6

                                                            I have very high standards for how fast I think a compiler should run!

                                                            Kind of ironic, since you’re using Rust. (I kid, I kid!)

                                                            1. 1

                                                              Haha yeah rustc is definitely way below my bar!

                                                              1. 1

                                                                To be fair it is doing some amazing things :)

                                                            2. 2

                                                              Purely opinion, based on looking at some code like

                                                              https://github.com/gleam-lang/gleam/blob/main/src/typ/expr.rs

                                                              (linked in the above threads)

                                                              It looks more concise than C++, but a lot more wordy than OCaml (or Elm). I’d be interested in seeing other idiomatic Rust code that implements languages (compilers, interpreters, runtimes).

                                                              1. 2

                                                                I’m the author of this code. :)

                                                                I did experiment with using OCaml to start with, and yes, the Rust version is a lot more verbose, especially when using shared mutable references (which are very concise in OCaml). Despite this I prefer the Rust experience, and I think it’s a more generally useful language to know.

                                                                1. 2

                                                                  Yes I think we talked on the original Reddit thread which I quoted here

                                                                  https://lobste.rs/s/vmkv3r/first_thoughts_on_rust_vs_ocaml#c_v5ch1q (as well as your article)

                                                                  I think you said you prefer Rust there. That is a useful data point for sure. I’m not experienced with Rust but I can definitely see why it’s appealing for languages.

                                                                  I actually think that “procedural” / stateful code with algebraic data types is a pretty good combo. That’s basically how my Oil project is written, with statically typed Python + ASDL.


                                                                  I heard someone say that Rust shows you can “just mutate”. In other words, some languages like Clojure and Erlang rely on immutability for concurrency. But Rust relies on its type system for that, so you are safe with mutation.

                                                                  And I just read someone say something similar here:

                                                                  https://news.ycombinator.com/item?id=24295408

                                                                  Others sometimes don’t like to hear this, but IMO, Rust is not at all functional. … Rust is very much procedural

                                                                  Although not everyone agrees.

                                                                  I have come around to this viewpoint. I used to program in more of an immutable style, but now I favor local mutation and “principled” global mutation. It seems to work well for languages, e.g. lexing and parsing are inherently stateful. And that style does seems to be in line with Rust’s design.

                                                            3. 1

                                                              Thanks for these resources, will read them!

                                                            1. 2

                                                              It’s annoying that Elixir or Erlang languages are only good for writing web applications. You can’t write CLI tools as starting the BEAM doesn’t make sense for it. Unless I’m mistaken.

                                                              With Go for example, you can write the same highly concurrent web apps but also write CLIs thus use one language for everything + Go LSP is more mature.

                                                              I never tried out Elixir/Gleam though, perhaps its functional & expressive features are really that good.

                                                              1. 9

                                                                You can write command line applications in Erlang based languages, it’ll just be a bit slower to start and harder to distribute than a language that complies to binary, similar to tools written in Ruby, etc.

                                                                I wouldn’t pick Erlang for a general purpose CLI but I might for a tool for a larger Erlang project. This is a common approach: iex, mix, rebar3, rabbitmq CLI, etc.

                                                                Go does a great job of making easy to distribute binaries, but sadly it is lacking many of the concurrency and durability features of Erlang. Ideally there would be a language with both! I’m hoping Lumen, the LLVM compiler for Erlang, will deliver here in future.

                                                                1. 7

                                                                  (On a second read of your comment, I can’t tell if you have experience in the Erlang world. If you do, my apologies if you already know what I’ve written below. I’m learning about a new topic and I’m some what excited.)

                                                                  I have been messing around with Elixir for a few weeks and I love the pattern matching, function overloading, and expression oriented syntax. It’s a very fun, expressive language. I would recommend checking it out!

                                                                  I believe that there are some frameworks to make TUIs, but it is probably not suitable for short lived command line tools. Specifically, I understand that it is not very fast when it comes to text processing.

                                                                  One important thing to note about the erlang virtual machine (BEAM) is that it is built for low and consistent latency. You could run an infinite, cpu bound loop in one process and the rest of the processes would keep chugging along. This means that it is not necessarily built for high throughput. (The runtime interrupts each process after a certain number of “reductions”.)

                                                                  So while Go might be able to build highly concurrent systems I think you would have to put a lot of work into making the latency consistent and to build fault tolerance into your application. That said, throughput is more important than responsiveness for some applications so it is a reasonable trade-off to make.

                                                                  1. 6

                                                                    Use escript. It doesn’t start OTP which is where the startup time is spent. Starting escript is pretty much instantaneous. If you need distribution access you can still call net_kernel:start/2 manually and send messages to other instances.

                                                                    http://erlang.org/doc/man/escript.html

                                                                    1. 5

                                                                      As a follow up to my previous reply (https://lobste.rs/s/q66slp/v0_10_gleam_statically_typed_language_for#c_upesnz) I would like to say that I’ve been thinking about how Go could be a complication target for Gleam. I keep hitting into problems of not being able to replicate some Erlang features using the Go concurrency primitives (namely monitors, process isolation, and links). If you or anyone has an idea of how we could tackle this I’d love to explore this area!

                                                                      1. 1

                                                                        Go LSP

                                                                        LSP?

                                                                        1. 1

                                                                          Language server protocol. It’s a common API for IDE engines so that one program can be made per language and then shared with all editors, rather than each editor implement their own language tooling.

                                                                        1. 1

                                                                          Thank you!

                                                                        1. 8

                                                                          Interesting. I have been having similar thoughts about error handling in my own current language project. Algebraic result types are awesome, but there needs to be a good way to solve the ‘Hadouken Problem’.

                                                                          1. 7

                                                                            I love the name ‘Hadouken Problem’. I’m going to have to remember that one!

                                                                            If you’re interested in some prior art, when designing try we mostly looked at Haskell’s <-, OCaml’s rebindable let*, Scala’s for, Rust’s ?, Swift’s try, Zig’s catch, Elixir’s with, and some of the proposals for error handling in Go 2.

                                                                            1. 4

                                                                              Why not a more general monad sequencing syntax, like Scala for? The same issue arises with options.

                                                                              1. 5

                                                                                A great question, thank you.

                                                                                Scala’s for is made possible by interfaces, a feature that Gleam does not have. In future we may add some kind of interface-like polymorphism (such as traits) and then we can revisit try.

                                                                                Another reason is that Gleam aims to be very simple, predictable, and conventional. Having monomorphic constructs in the langauge encourages users to all write similar code, which makes the language more easier to learn. We value approachability, productivity, and ease of adoption over conciseness or more exciting language features.

                                                                                1. 2

                                                                                  All good reasons, and I applaud restraint in language features and syntax. I haven’t looked in detail at the docs, but presumably adding monadic interfaces similar to Scala’s option would be another way to solve the hadouken problem without new syntax.

                                                                                  1. 5

                                                                                    We do have a result.then function in the standard library (which is >>= in Haskell, but specialised to Result). It works nicely but can get quite verbose when depending on multiple previous results, so this syntax is a welcome addition.

                                                                                    I was lucky enough to be able to test out try with a junior developer and they found it much more understandable than result.then, which I took as a good omen.

                                                                              2. 3

                                                                                Have you had a chance to look into the way Frank and Unison do algebraic effects and handlers (Unison uses a strange term ‘ability’ for this)? The nice thing is that you can have multiple effects for different error cases, without needing to build up the error conversion machinery that you would need to do in Rust. The plumbing is also done in a more automatic way, without need for an explicit do/try/for*.

                                                                                1. 1

                                                                                  I’ve not no. I did look in a few other places but I wasn’t able to get a good idea of how it worked in practice, so we opted to stick with what was familiar to us (Result/Either).

                                                                                  Sorry for the slow reply!

                                                                              3. 2

                                                                                just use goto ;)

                                                                                function register()
                                                                                {
                                                                                	$msg = '';
                                                                                
                                                                                	if (empty($_POST)) {
                                                                                		goto err;
                                                                                	} else if (!$_POST['user_name']) {
                                                                                		$msg = 'Empty Username'
                                                                                		goto err_msg;
                                                                                	} else if (!$_POST['user_password_new']) {
                                                                                		$msg = 'Empty Password';
                                                                                		goto err_msg;
                                                                                	} /* etc */
                                                                                
                                                                                	create_user();
                                                                                	$_SESSION['msg'] = 'You are now registered so please login';
                                                                                	header('Location: ' . $_SERVER('PHP_SELF']);
                                                                                	exit();
                                                                                		
                                                                                err_msg:
                                                                                	$_SESSION['msg'] = $msg;
                                                                                err:
                                                                                	register_form();
                                                                                }
                                                                                
                                                                                1. 1

                                                                                  I agree. I’ve spent years using goto-less programming languages of all kinds and interestingly, I use goto rather often when I go back to C. Not only for the error handling pattern illustrated in your example but even for loops sometimes. Quite often, goto really makes sense where you would recurse in a functional programming language.

                                                                                  1. 1

                                                                                    Genuinely not the worst solution but I think 52 years after Dijkstra’s missive we can do a bit better :-)

                                                                                1. 3

                                                                                  Gleam looks more and more appealing with such nice libraries.

                                                                                  Slightly out of scope but, it would definitely help adoption if there was a simple example of deploying such an app on a platform like Heroku. I’d be happy to help on the Heroku part, I’m very unfamiliar with the Erlang deployment process.

                                                                                  1. 2

                                                                                    Hello! Deployment documentation is certainly a top priority, and something we consider a responsibility of the core team!

                                                                                    Right now I’m working a lot on tooling so it’s hard to write documentation as it’s in a state of flux. For now users will have to refer to the Erlang documentation I’m afraid https://www.rebar3.org/docs/releases

                                                                                    1. 2

                                                                                      For now we could have a guide about using heroku + Mix/Elixir with some Gleam modules. That’s what I am currently doing for my Gleam deployments, though my set up is rather messy.

                                                                                    1. 11

                                                                                      I am a full-time BEAM programmer and the one thing I find myself missing is a really robust type-driven programming approach. I’m so excited for Gleam and I really hope it becomes a major player in the Erlang VM ecosystem!

                                                                                      1. 1

                                                                                        I hope so too! Thank you!

                                                                                      1. 1

                                                                                        Why make try a keyword instead of a method on your object type?

                                                                                        1. 4

                                                                                          Thanks for the question! Gleam doesn’t have methods or objects, it is a functional language based on lambda calculus. We did have try implemented as a function in the standard library, this new try sugar takes that established pattern and made it much more ergonomic.

                                                                                          1. 2

                                                                                            Ah, I see now your response above. That’s more in line with what I was (poorly) trying to ask. It is good to know that it’s not extra required syntax, and available as a function call.

                                                                                        1. 4

                                                                                          Very interesting that it’s faster than the previous version written in Haskell. I’d love to hear more about what the contributing factors were to the performance increase.

                                                                                          1. 25

                                                                                            This question has come up a few times, so I’ve rattled off a thing that I think covers the main factors: https://www.type-driven.org.uk/edwinb/why-is-idris-2-so-much-faster-than-idris-1.html

                                                                                            tl;dr: it turns out it’s much easier to improve performance spectacularly when it starts so bad :)

                                                                                            1. 2

                                                                                              While you are here, is the Type Driven Development book still relevant? It’s from 2017 so I am somewhat skeptical how relevant it is now.

                                                                                              I’d like to give Idris a go :)

                                                                                                1. 3

                                                                                                  Once Idris 2 is released, do you have any plans to update the book / produce a new edition?

                                                                                              1. 1

                                                                                                Thank you!

                                                                                            1. 2

                                                                                              Louis, is Gleam based on the lambda-calculus like other ML are, with a CoreFn backend at the bottom, or is the ML syntax just on the surface? I’m asking because I saw purerl and I am interested in how you did everything. Cheers!

                                                                                              1. 2

                                                                                                Gleam’s type system is based upon the lambda-calculus, it’s a good fit for Erlang.

                                                                                                CoreFn I believe is an intemediate representation in the PureScript compiler. The Gleam compiler is written from scratch and shares no code with PureScript, so we don’t use CoreFn. We do have 2 internal ways of representing Gleam code, though I imagine both are very simple compared to PureScript as we have a smaller feature set at present.

                                                                                                1. 3

                                                                                                  Thank you very much for the answer! I am always interested in BEAM languages that are based on Lambda-calculus, as I am an Elixir and Haskell developer. Thank you for filling the gap. :)

                                                                                              1. 2

                                                                                                Really digging the new features, should definitely help with getting more people to try out the language (myself included). Thanks and congrats on the release!

                                                                                                1. 1

                                                                                                  Thank you very much!

                                                                                                1. 2

                                                                                                  This is great. Please keep it up!

                                                                                                  1. 2

                                                                                                    Thank you!