Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

c-cube
Copy link
Contributor

@c-cube c-cube commented Jun 9, 2015

Similar to the existing construct in swift and rust (RFC for rust). If this construct is approved, I might implement while let (RFC for rust).

An expression if let Some x = e then a else b becomes match e with Some x -> a | _ -> b.

@yminsky
Copy link

yminsky commented Jun 9, 2015

This isn't terribly appealing to me on the face of it, since it encourages fragile matches. Given that the match syntax you show is readable and explicit and not materially less concise than what is described in this feature, the argument for its inclusion seems unclear to me.

To make a good argument for this idiom, I would argue that one should come up with a realistic example where this materially clarifies or shortens the code. At the moment, I'm having trouble imagining where that might be the case.

@c-cube
Copy link
Contributor Author

c-cube commented Jun 9, 2015

the use-cases I think of are mostly side-effectful tests without a else branch:

let f ?opt x =
  if let Some y = opt then printf "yolo %d\n" y;
  x+1

A realistic example: in this very PR I added:

let mkiflet bindings then_expr else_expr =
  begin match bindings.lbs_rec with
    | Recursive ->
       raise Syntaxerr.(Error(Not_expecting(
         bindings.lbs_loc, "recursive bindings in 'if let'")))
    | Nonrecursive -> ()
  end;
  ...

that could be shortened into

let mkiflet bindings then_expr else_expr =
  if let Recursive = bindings.lbs_rec
    then raise Syntaxerr.(Error(Not_expecting(
      bindings.lbs_loc, "recursive bindings in 'if let'")));
  ...

(yes, I dislike polymorphic equality)

@Drup
Copy link
Contributor

Drup commented Jun 9, 2015

let f ?opt x =
  Option.iter (printf "yolo %d\n") opt ;
  x+1
let mkiflet bindings then_expr else_expr =
  if Recursive = bindings.lbs_rec
    then raise Syntaxerr.(Error(Not_expecting(
      bindings.lbs_loc, "recursive bindings in 'if let'")));
  ...

It's even shorter. Those are not convincing use cases.

@lpw25
Copy link
Contributor

lpw25 commented Jun 9, 2015

See previous discussion: http://caml.inria.fr/mantis/view.php?id=6685

@c-cube
Copy link
Contributor Author

c-cube commented Jun 9, 2015

@lpw25 oh, my bad, didn't see this :(

@yminsky
Copy link

yminsky commented Jun 9, 2015

I don't find the use case all that compelling --- to me, the explicit match
in the Recursive/Nonrecursive case seems better, and in the case where you
do want to do this kind of thing because the alternatives are clear enough
to the user, special functions like Option.iter seem to cover that use case
nicely.

On Tue, Jun 9, 2015 at 8:24 AM Simon Cruanes notifications@github.com
wrote:

@lpw25 https://github.com/lpw25 oh, my bad, didn't see this :(


Reply to this email directly or view it on GitHub
#194 (comment).

@keleshev
Copy link
Contributor

Just wanted to highlight why this feature is so compelling in Rust and Swift, but less compelling in OCaml.

Rust

Before

match foo() {
    Some(x) => {
        doSomethingWith(x)
    }
    _ => {
        defaultBehavior()
    }
}

8 lines, 2 indents.

After

if let Some(x) = foo() {
    doSomethingWith(x)
} else {
    defaultBehavior()
}

5 lines, 1 indent.

OCaml

Before

match foo with
| Some x -> 
    do_something_with x
| _ ->
    default_behavior 

5 lines, 1 or 2 indents depending on style and how you count it.

After

if let Some x = foo then
  do_something_with x
else
  default_behavior 

4 lines, 1 indent.

@c-cube
Copy link
Contributor Author

c-cube commented Jun 11, 2015

@keleschev in a ;-separated sequence of expressions, the gain can be larger:

begin match foo with
| Some x ->
    do_something_with x
| _ ->
    default_behavior
end;

becomes

if let Some x = foo
    then do_something_with x
    else default_behavior;

@alainfrisch
Copy link
Contributor

I don't think we should focus on counting lines. This depends on formatting and on the need to wrap the pattern matching (and/or their branches) in begin...end (and same for the if-then-else branches).

I'm also not convinced by the proposal. Overloading the "if" syntax with a construction that binds values makes it more difficult to spot the binding site of a variable. Consider:

let x = ... in
if let Some x = foo then ... else ...

vs

let x = ... in
if Some x = foo then ... else ...

It's too easy to use one for the other, and it makes it harder to read the code.

@c-cube
Copy link
Contributor Author

c-cube commented Jun 11, 2015

Well, I might as well close the PR, seems like redditors of /r/ocaml do not like it either.

@c-cube c-cube closed this Jun 11, 2015
lukemaurer pushed a commit to lukemaurer/ocaml that referenced this pull request Jun 29, 2020
lthls pushed a commit to lthls/ocaml that referenced this pull request Sep 23, 2020
lthls pushed a commit to lthls/ocaml that referenced this pull request Sep 23, 2020
lthls pushed a commit to lthls/ocaml that referenced this pull request Sep 24, 2020
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
Signed-off-by: Paul-Elliot <peada@free.fr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.