Reason: Syntax proposal `if let`

Created on 15 Jun 2017  路  7Comments  路  Source: reasonml/reason

In swift, there's this nice construct for simple destructuring

if case .someEnumVariant(let value) {
 ...
} else {
 ...
}

It's basically a one-armed match.
It would be super handy to have that for reason, and I imagine it would look like

if let [%pattern] = [%value] {
  // x
} else {
  // y
}

which we'd translate to

switch [%value] {
| [%pattern] => // x
| _ => // y
}
Parser RFC

Most helpful comment

Another thing that swift's if let does might be quite useful (found myself wanting it in code I'm writing just now)

  let Some(x) = optx,
  let Some(y) = opty,
  let Some(z) = optz
{
 // all your things are here
}

is much nicer imo than

switch (optx, opty, optx) {
| (Some x, Some y, Some z) => ...

(especially if optx is some non-trivial expression)

All 7 comments

Yes its occasionally nice being able to do (a bit redundant here but this is the specific use case I had been thinking about):

if let aValue = anOptional {
    doSomethingWith(aValue)
}

Other discussion from the ocaml folks
https://github.com/ocaml/ocaml/pull/194
https://caml.inria.fr/mantis/view.php?id=6685

I'm not very moved by their counterarguments. I think if let is much more accessible to folks coming from javascript etc., to whom Option.iter would be foreign.

Another thing that swift's if let does might be quite useful (found myself wanting it in code I'm writing just now)

  let Some(x) = optx,
  let Some(y) = opty,
  let Some(z) = optz
{
 // all your things are here
}

is much nicer imo than

switch (optx, opty, optx) {
| (Some x, Some y, Some z) => ...

(especially if optx is some non-trivial expression)

I think using and instead of , let as a connector for multiple guards could work well particularly because it's the same syntax used with let rec x = ... and y = ...;

e.g.

if let Some(x) = optx
   and Some(y) = opty
   and Some(z) = optz
{
 // all your things are here
}

It's a cool idea! One thing that might be confusing is that I want successive cases to be able to use values from previous cases.
e.g.

if let Some(x) = optx,
   let Awesome(y) = doSomethingWith(x) {
}

and syntax in ocaml requires them to not use each other, and let rec and requires them to be functions. So something like

let x = 2
and y = x

is invalid.

Fair, this pattern seems like a pretty great way to guard:

if let Some(x) = getValue(),
   let Some(y) = doSomething(x),
   let Some(z) = doSomethingElse(z) {
  doSomethingCool(z);
} else {
  failwith("Couldn't do the thing!");
}

The ability to use the inner values makes it superior to

switch (a, b, c) {
  | (Some(a), Some(b), Some(c)) => ...,
  _ => ...
}

It'd have to be expressed as a series of nested switches or ifs, which would be less clear and add unnecessary nesting.

For reference, this is similar to Elixir's with statement:

opts = %{width: 10, height: 15}
with {:ok, width} <- Map.fetch(opts, :width),
     {:ok, height} <- Map.fetch(opts, :height),
     do: {:ok, width * height}
#=> {:ok, 150}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

chenglou picture chenglou  路  3Comments

ondrejsevcik picture ondrejsevcik  路  3Comments

braibant picture braibant  路  4Comments

TheSpyder picture TheSpyder  路  3Comments

bluddy picture bluddy  路  3Comments