Gleam, a statically typed language for the Erlang VM

Ecto and Phoenix very macro based, so we will never be able to make full use of them from Gleam, Erlang, or any other non-Elixir language.

Likely you would get the best experience from using Gleam modules as libraries in a way similar you might use Erlang modules.

Are you interested in the community exploring close interop with Ecto & Phoenix & Plug or would you much rather leave that and explore full Gleam solutions for web frameworks and database interactions?

We will never be able to have close interop with these Elixir projects as they are only designed with Elixir in mind and (quite rightly) make full use of Elixir features that cannot be used from other languages.

We will likely have a much better story for common Erlang libraries as they typically are easier to use from other BEAM languages.

2 Likes

Thanks for the information. Makes sense! Interesting that the macro-heavy nature of Elixir makes it harder to interact with. Understandable though. Unfortunately I’ve got no experience with Erlang at the moment but maybe one day :slight_smile:

1 Like

A quick question about the changelog:

  • Tuples can be indexed into using the var.1 syntax.

Are tuples in gleam 0-indexed (like Elixir) or 1-indexed (like Erlang)?

1 Like

They are 0 indexed like Elixir. :slight_smile:

4 Likes

Gleam v0.8 is here! :partying_face:

It’s quite a large one this time! Please see this post for more information: https://lpil.uk/blog/gleam-v0.8-released/

Thanks all!

14 Likes

Great stuff. :whale:

I particularly like the new documentation. Is how to add docs to a project documented anywhere?

1 Like

This is next up on my to-do list! Further documentation on how to use projects is needed for sure.

2 Likes

I noticed that the spectrum chat is no longer being used. Did you guys move somewhere?

We had problems with Spectrum so we have returned to IRC. You can find us in #gleam-lang on Freenode. https://webchat.freenode.net/#gleam-lang

1 Like

If you’re still looking for a more persistent home, I think our new community platform could actually be a really nice fit for you - I’ll send you some info when I get five mins :003:

4 Likes

That would be very interesting! Thanks

3 Likes

Hello everyone! There has been some discussion on whether we should add an Option type to Gleam.

If you have any thoughts please leave them here: https://github.com/gleam-lang/gleam/issues/591

I’m keen to get an idea of what the community thinks! Thank you!

4 Likes

I agree with you on syntax, AstonJ. I started out with C and C++ and then did Python for a long time. I’ve also programmed professionally in Perl, COBOL, Pascal, JavaScript, Haskell, Java, C#, TypeScript, Scala, Go, and Swift, so I’ve seen a lot of different styles of syntax. For me, Ruby and Elixir are the most readable and fit into my brain the best.

I’m not criticizing Gleam’s choice of syntax. I’m just saying that, in my opinion, there is more to syntax than familiarity. I’m probably most familiar with bracket-heavy languages but my brain likes that syntax the very least.

2 Likes

I think this can happen for anyone with any set of syntaxes, so there’s no cost best syntax.

For example, I’ve written code in 30+ languages, I’m most familiar with Elixir style syntax, but it’s far from my favourite.

1 Like

Coming back to this a little later, I think you’ll be surprised that Gleam manages to be more concise than Elixir in many places. For example, here’s a pipeline in Elixir:

local_function = &module.function/1

[1, 2, 3]
|> module.function()
|> module.args(1, 2)
|> (&module.reordered(1, 2, &1)).()
|> local_function.()

And the same in Gleam:

let local_function = module.function

[1, 2, 3]
|> module.function
|> module.args(1, 2)
|> module.reordered(1, 2, _)
|> local_function

The Gleam version also allocates fewer objects as it erases intermediate anonymous functions used for reordering arguments during compilation.

Here’s some error handling in Elixir

with {:ok, user} <- get_user(id),
     {:ok, membership} <- get_membership(user) do
  print(membership)
end

and the same in Gleam:

try user = get_user(id)
try membership = get_membership(user)
print(membership)
1 Like

How do you deal with the else case in Gleam?

1 Like

The else clause can’t be typed (as each clause can be for a different type), so we don’t have a direct mapping to that language construct. We’d likely do something like this instead:

with {:ok, user} <- get_user(id),
     {:ok, membership} <- get_membership(user) do
  print(membership)
else
  {:error, :no_user} -> 
    {:error, "The user could not be found"}

  {:error, :no_membership} -> 
    {:error, "The membership could not be found"}
end
try user = get_user(id)
  |> result.map_error(fn(_) { "The user could not be found" })
try membership = get_membership(user)
  |> result.map_error(fn(_) { "The membership could not be found" })
print(membership)

This is similar to how this would be handled in languages like Rust, OCaml, and Haskell.

Haskell:

do
  user <- left (\_ -> "The user could not be found")
          $ getUser id
  membership <- left (\_ -> "The membership could not be found")
                $ getMembership user
  print membership

Rust (assuming you’re not using std::error::Error):

let user = get_user(id)
    .map_error(|_| "The user could not be found")?;
let membership = get_membership(user)
    .map_error(|_| "The membership could not be found")?;
print(membership)

OCaml:

let* user = get_user id
  |> Result.map_error ~f:(fun _ -> "The user could not be found") in
let* membership = get_membership id
  |> Result.map_error ~f:(fun _ -> "The membership could not be found") in
print membership
2 Likes

Whoa this is pretty cool! How does the control flow work… does it essentially halt the flow if one of the try lines doesn’t return an OK? sort of like an early return? Also I haven’t been following Gleam as closely lately but is try already in the language or just a planned feature later?

1 Like

That’s right, it compiles to code like this:

case get_user(id) {
  Error(e) -> Error(e)
  Ok(user) -> case get_membership(user) {
    Error(e) -> Error(e)
    Ok(membership) -> print(membership)
  }
}

It’s implemented now and will be out in the next release, which will be very soon!

6 Likes

I just followed along with this blog post to start a Phoenix project with gleam as a mix compiler:

…however, when I make changes to the .gleam files, the application doesn’t pick them up unless I restart the server—even running mix compile won’t do it.

(I did already add a ~r"src/.*(gleam)$" pattern to the live_reload config in dev.exs, and that configures the page reloading successfully, but that doesn’t deal with the other issue.)

Anyone got this running in a more seamless way?

2 Likes