top | item 41812336

Gleam: A Basic Introduction

139 points| Alupis | 1 year ago |peq42.com

73 comments

order
[+] cedws|1 year ago|reply
I've been interested in Gleam, but I didn't realise it just transpiles to Erlang, I thought it compiled directly to BEAM bytecode. Bit of a turnoff to be honest, I really don't want to deal with transpilation.
[+] Ndymium|1 year ago|reply
Which part do you feel like would be an issue? When you run `gleam compile`, it will automatically call the Erlang compiler to finish the job.

I find it very handy that the intermediate Erlang (or JS) files are available in the build directory. It lets you easily see what form your code will take when compiled.

[+] Muromec|1 year ago|reply
It makes perfect sense to target erlang and not BEAM directly as allows erlang compiler to optimize the code for the newer BEAM runtime with newer fancier opcodes.
[+] josevalim|1 year ago|reply
Yes, unfortunately transpilation comes with real downsides. Up until recently, logger events, error messages and stacktraces were displayed in Erlang formatting. It has improved in few cases, but not all, and the line numbers in stacktraces do not align with the source code. And if you want to use a REPL, you must use Erlang/JS ones, etc.
[+] lpil|1 year ago|reply
What do you mean by deal with transpiration? Elixir and LFE also both compile to Erlang and then run the BEAM compiler to generate bytecode. Erlang is the only BEAM language which goes to bytecode directly today.
[+] drdaeman|1 year ago|reply
One niche feature of Erlang that I love is live module upgrades, particularly via gen_server's code_change/3 callback. It's a neat little trick that seems to be rarely used in practice, but every single time I've used it I just loved how everything simply clicked together, providing zero disruption with nearly minimal effort (for simple state upgrades or downgrades).

I wonder if it's supported with Gleam and/or gleam_otp? Don't see it in the docs.

[+] sbrother|1 year ago|reply
Do you know the current status of gleam_otp? I’ve been in the erlang (and more recently elixir) world for a long time and am quite excited about gleam, but when I looked at it early on it didn’t seem to have a great solution for OTP. Can I write genservers in gleam now, and can they run as part of an elixir/erlang application/supervision tree?
[+] lpil|1 year ago|reply
No particular support but you can use all the regular Erlang OTP APIs for this. The trade off is that you lose type safety.
[+] jeremy_k|1 year ago|reply
Gleam has been great as I've started messing around with it recently. Coming from primarily Ruby, it feels much different and I'm liking expanding my thought process around programming. I'm struggling a bit with learning how to think in the type system though. Without unions and a requirement that case statements all return a single type, I just haven't quite grasped the right pattern to make it all click. Enjoying the process none the less.
[+] systems|1 year ago|reply
the gleam tour is also very good https://tour.gleam.run/

very very good

[+] xorvoid|1 year ago|reply
From the tutorial:

// Division by zero is not an error

io.debug(3.14 /. 0.0)

It prints 0

Yuck. Division by zero is an unfortunate reality but basically nobody with mathematical background thinks that just defining x/0 = 0 is a good solution.

Often in numerical computing, getting an NaN or Inf is a blessing in that it’s a hint that your algorithm is numerically buggy, in the same way that a crash or a exception would indicate a program bug.

This approach is the numeric equivalent of a program continuing on after an undefined variable, just assuming it’s 0. That was tried by scripting languages in the 90s and these days most folks think it was a bad approach.

[+] floodfx|1 year ago|reply
I like the look of Gleam over Elixir for sure. I’d love to see some example code showing Gleam-based LiveViews but I haven’t been able to find it anywhere. Is it possible? Anyone have some code to point me at?
[+] innocentoldguy|1 year ago|reply
I like the look of Elixir over Gleam for sure because:

• Elixir allows for more flexibility and faster prototyping. • Elixir's ecosystem is superior and more mature. • Elixir compiles to BEAM bytecode whereas Gleam compiles to Erlang which then compiles to BEAM bytecode. • Elixir supports Lisp-style macros. • Elixir excels at web development, data processing, and distributed systems. • Elixir's OTP implementation is better.

Since Gleam doesn't support macros, my guess is that Gleam isn't going to be able to run Phoenix-like or LiveView-like frameworks, but I haven't really looked at it, so I could be wrong (edited because what I said wasn't clear, and probably still isn't).

I don't mean to knock Gleam, but it feels to me like a project that came about to add static typing to what Elixir already does, and while it has accomplished that, it has failed, so far, to live up to all the other great things Elixir and Erlang do. I know it's still a young language, so maybe someday they'll get there, but they're not there yet. After coding for 33+ years, I just don't find static typing to be all that compelling or important to me, so I would never choose Gleam over Elixir as things currently stand.

[+] lpil|1 year ago|reply
The Lustre framework supports LiveView as well as entirely in-browser state management, which Elixir LiveView cannot do.
[+] pipeline_peak|1 year ago|reply
> fn add(x: Int, y: Int) -> Int

Why do language authors insist the majority of programmers want to type this way? Meaningless arrows and redundant colons.

Is it constructive, like it will lead us to think differently? It feels more like a contest in overcomplicating something as innocent as:

int add(int x, int y)

[+] mcintyre1994|1 year ago|reply
I think it’s because generally the type annotations are optional and it’s much easier to parse that version. Typescript uses a colon instead of arrow for the return type so I think that’s just preference though.

In particular if you removed the types from yours it’d be add(x, y) and the parser wouldn’t be able to distinguish that from a function call. I think that’s why the fn keyword is really useful for the parser.

[+] giraffe_lady|1 year ago|reply
I think there's a pretty good case for the arrow being easier to reason about especially with anonymous functions or if currying gets involved. The other way is lacking a "verb" and it becomes harder to keep track of what's going on in some cases.

The arrow is also conventional in ML family languages, which are a venerable branch of programming whose traditions I respect and enjoy. That's not enough reason alone to keep it maybe but it's not nothing either.

The colon thing whatever, I truly just can't bring myself to care about such fine-grained specifics of syntax. It sounds like a rough life honestly.

[+] mkehrt|1 year ago|reply
The answer is this is how theoretical programming languages have done it since the 1920s, borrowing from the mathematical notation of the time. As programming language theory has made more inroads into practical programming languages in the last 10-20 years, newer languages have borrowed the notation.

I'm biased, having been immersed in PL thoery for a while, but I prefer the colon notation. It works better with type inference, for example. Consider declaring a variable in two ways:

  var x: int = 3;
  // Now add type inference
  var x = 3;
Vs

  int x = 3;
  // Now add type inference
  var x = 3; // We've just changed the type to a keyword and that's weird.
But that's just a personal preference.
[+] lpil|1 year ago|reply
It’s so they are readable left to right, which is typically easier. The difference can be seen most clearly with writing the type of functions as arguments.
[+] written-beyond|1 year ago|reply
I honestly gave gleam a serious look, considering it to build a system that might really benefit from it's concurrency model. However the lack of Macros/macro-style reflection capabilities really put me off. It makes working with SQL databases needlessly verbose. It's the same with go, though go posses the capabilities to directly unmarshal SQL rows into a structure with tags, it's far from straightforward.
[+] Alupis|1 year ago|reply
This is the sentiment many have when transitioning from OOP -> FP paradigms.

That's not to say ORM's don't exist in FP, but they are not nearly as common because their concept doesn't directly translate into what you expect from a functional language.

That is to say this is not a Gleam problem, it is a FP problem, if we can even call it a problem (it's mostly just different).

[+] klabb3|1 year ago|reply
> It's the same with go, though go posses the capabilities to directly unmarshal SQL rows into a structure with tags

Go also has best-in-class support for code generation. It isn’t as good as the best macro systems, but it works really well in my experience, despite the duct-tape. It also doesn’t obliterate compile times. Check out Ent - it’s a really pleasant “ORM”.

[+] lawn|1 year ago|reply
For me the big problem with the lack of macros is the unergonomic json conversions.

In Rust for example you use a simple declarative approach and it uses the type system to serialize/deserialize properly.

But in Gleam you need to do everything manually. Even with libraries that's a ton of manual work you need to do.

It's the single reason why I shy away from using Gleam actually.

[+] asplake|1 year ago|reply
“Gleam is a statically-typed language, meaning you must declare the type of a variable before using it.”

That second part is wrong. Gleam has type inference.

[+] pxc|1 year ago|reply
In the era of type checkers for dynamic languages, it might be better to write

> Gleam is a statically-typed language, meaning if you declare the type of a variable before using it, that will actually do something.

:)

[+] vivzkestrel|1 year ago|reply
golang concurrency vs gleam concurrency vs rust concurrency? for a webserver?
[+] rixed|1 year ago|reply
> Gleam is a statically-typed language, meaning you must declare the type of a variable before using it.

What year is this from?

[+] lpil|1 year ago|reply
It’s incorrect, Gleam has full type inference and doesn’t require variable annotation.