Gleams use expression

The Gleam hype started and I was curious about some language goodies.
While reading the language tour (a lot of similar stuff to Rescript), I stopped at the use expression.

Use what? The use expression is just some syntactic sugar for (nested) callbacks.

There are already many discussions (some are a bit older) and I don’t want to bother anyone, but well …

  1. F# with computation expressions (I hate to implement them, but I like to use them)
  2. Scala with for comprehensions
  3. Haskell with monad comprehensions
  4. OCaml with let op

And now Gleam with use.

All of these languages offer some kind of syntactic sugar for combining multiple results, options, etc.
Some are builtin, some have to be implemented by yourself and can be extended immeasurably.

I think overriding the let binding (OCaml version) or implementing custom computation expressions (F#) could “destory” the simplicity of Rescript and could confuse other devs while reading your code, but the use expression looks like a simple and generic way to hide callback hells.

What do you think?

roc-lang has something similar, which they call backpassing.

It looks elegant indeed! What I don’t like with all those sugars, though, is that it makes you focus on the happy path and often leads to overall bad error handling.

I’ve never been a fan of ocaml let op for example. I find it hurts readability a lot.

2 Likes

An elegant way to solve the problem in rescript actually already exists, just use exceptions instead of result / option monads and use reanalyze to track exceptions statically.

While chaining promises (without async/await) there is also the focus on the happy path.
Don’t know if you handle it in another way?

let result = promise->then()->then()->then()->catch()

Exceptions would solve the problem, but never thought about using exceptions instead of options for example :thinking:
And as you mentioned: You have to use another tool to track them.

I use pattern matching on awaits, whenever possible, if I use promises. This way I’m forced to think / handle errors as well.

let f = async x =>
  switch await x() {
  | result => Console.log(result)
  | exception JsError(err) => Console.error(err)
  }

5 Likes