gleam icon indicating copy to clipboard operation
gleam copied to clipboard

Bug: Record update + pipe == Erlang binding errors

Open tynanbe opened this issue 1 year ago • 3 comments

This Gleam code

pub type Rad {
  Rad(some: String)
}

fn update(rad: Rad, with str: String) -> Rad {
  Rad(str)
}

pub fn main() {
  let rad = Rad("a")
  Rad(
    ..rad
    |> update("b")
  )
}

produces this invalid Erlang code

-module(main).
-compile(no_auto_import).

-export([main/0]).
-export_type([rad/0]).

-type rad() :: {rad, binary()}.

-spec update(rad(), binary()) -> rad().
update(Rad, Str) ->
    {rad, Str}.

-spec main() -> rad().
main() ->
    Rad = {rad, <<"a"/utf8>>},
    _pipe = Rad,                 % error: variable _pipe is bound multiple times in this pattern.
    update(_pipe, <<"b"/utf8>>). % error: variable _pipe is unbound

https://johndoneth.github.io/gleam-playground/?s=A4VwRgBALgnsCmEBKBDAJhA3gKAs9AFAM4D2AtvAFwQDKUATgJYB2A5gJTYC%2B22AZswghgaFFHgF66aqjQAaCAHdGUABYQiDanSZt2EALQA%2BfBhx5ZxBpx7ZQkARDIoWBfeYgAbeFAhSMALymBABEKCGcFoS4eBAAdHH%2BMXgAPibCouKhYBExNthAA%3D%3D

tynanbe avatar Jul 21 '22 17:07 tynanbe

Sorry, I'm a bit confused. I can only see the point variable being bound once there. Is this the right code snippet?

lpil avatar Jul 24 '22 11:07 lpil

Sorry, I didn't test this simplified snippet; looks like it's not quite enough.

The following Gleam compiles and runs fine for the JavaScript target.

fn iterable_builder() {
  Task(
    ..[]
    |> task.new(run: task.basic(["echo"]))
    |> task.flags(add: iterable_flags()),
    config: "gleam.toml"
    |> toml.parse_file
    |> result.lazy_unwrap(or: toml.new)
    |> Parsed,
  )
}

But produces this invalid Erlang.

-spec iterable_builder() -> rad@task:task({ok, binary()} | {error, snag:snag()}).
iterable_builder() ->
    erlang:setelement(
        9,
        _pipe = [],
        _pipe@1 = rad@task:new(_pipe, rad@task:basic([<<"echo"/utf8>>])),
        rad@task:flags(_pipe@1, iterable_flags()),
        begin
            _pipe@2 = <<"gleam.toml"/utf8>>,
            _pipe@3 = rad@toml:parse_file(_pipe@2),
            _pipe@4 = gleam@result:lazy_unwrap(_pipe@3, fun rad@toml:new/0),
            {parsed, _pipe@4}
        end
    ).

It looks like the problem manifests because the first pipe inside of setelement should be wrapped in a block.

tynanbe avatar Jul 24 '22 22:07 tynanbe

There it is! Thank you very much

lpil avatar Jul 28 '22 12:07 lpil