# Sugar: Some 10 |> function (Some x) -> x | ... #605

Closed
opened this Issue Sep 10, 2017 · 10 comments

Projects
None yet
5 participants

# sugar: a |> function (Some x) -> x | ...

I propose we ... (describe your suggestion here)

```let a = Some 10
a |> function (Some x) -> x  | ...```

replace `| _ -> failwith "never"` with new structure `| ...`
The existing way of approaching this problem in F# is ...

```let a = Some 10
a |> function (Some x) -> x  | _ -> failwith "never"```

a alternative sugar is four `|`:

`function (Some x) -> x  ||||`

## Pros and Cons

Silence Speaks Better Than Sounds

new structure `| ...` will be introduced.

### xuanduc987 commented Sep 10, 2017 • edited

 Or you can just use `#nowarn "25"`

### rmunn commented Sep 11, 2017

 Neither of those suggestions communicates clearly what they do. I would have no idea what `| ...` meant, and `||||` is even worse. Thank you for making the suggestion, though. Although I disagree with this one, I'm glad that you're interested in helping to improve F# and make it easier to learn. Please continue to make suggestions — your idea in #604 was quite interesting.

### Rickasaurus commented Sep 13, 2017

 You can already do something like this pattern matching in a normal lambda: ```let a = Some 10 a |> fun (Some x) -> x ```

### abelbraaksma commented Sep 19, 2017 • edited

 While I find the idea intriguing, I don't think the benefits outweigh the costs. I have often struggled with how to clearly finish unfinished cases. I usually end up doing something like the following: ``````let (|MySome|) x = match x with Some x -> x | _ -> failwith "never" let testMeAlt1 = let a = Some 10 a |> function MySome x -> x `````` But if quirky syntax is your thing, you could perhaps make it abundantly clear writing something like the following instead. ``````let inline (!!!!) _ = failwith "never" let testMeAlt2 = let a = Some 10 a |> function Some x -> x | _ -> !!!!() `````` If you want to make it (much) clearer what is going on, this approach might be better: ``````let (|Never|) x = Unchecked.defaultof<_> // or raise exception let testMeAlt3 = let a = Some 10 a |> function Some x -> x | Never x -> x `````` All these approaches can be made to work with any DU. And while I have never used the last approach above, I do like to occasionally use the first approach. I typically name such methods `OnlyXXX` where XXX is the DU type it should match. Still, apart from rare cases, needing this is often a sign of code smell, and for code smell you shouldn't have specific syntax as people might actually use it and ruin the safety of their code (warning `25` is there for a reason!).

### xp44mm commented Sep 21, 2017 • edited

 @abelbraaksma thank you for your knowledge. i like the first method. i never think to it. both 2nd and 3rd are longer than `| _ -> failwith ""`, maybe i can define a module named `Only`, and summary every cases.

### abelbraaksma commented Sep 21, 2017 • edited

 Yes, that sounds like a viable approach for your use case (btw, if you count the characters, the other approaches are not smaller, unless you mean the added extension functions, but these can be used for any situation, so you only have to define them once). Either way, don't forget that if others need to understand your code, good naming of active patterns is important. Also, having a clear `failwith "unexpected program point"` (or putting this in a specific exception) is a good way of telling anyone in your team what is supposed to happen. If you agree that adding extra syntax sugar here has no significant benefits, feel free to close the thread (click [Close And Comment] button).

### xp44mm commented Sep 21, 2017 • edited

 @abelbraaksma maybe just code following ```let never<'a> = failwith<'a> "never" let a = Some 10 let b = match a with | Some x -> x | _ -> never``` i used to read the fyacc generated code, the code have a lot of not complete pattern match. and i also have many match is not complete. may i get the first line from `fsharp.core` in the future?

### abelbraaksma commented Sep 22, 2017

 may i get the first line from fsharp.core in the future? Not sure what you mean, but if you mean to make `let never<'a> = failwith<'a> "never"` a function in the core, that's most likely not going to happen (though it is not me who has any say in that). It's a simple one liner that anyone can make, and it contains user-specific strings that would end up being part of the exception. If we were to make it useful, we would have to parameterize it, i.e. `let never<'a> s = failwith<'a> s`, which makes it synonymous to `failwith`, which is already there. So there's no gain by adding to the language what's already in the language. As an example, many of my projects contain something like the following, where I raise a `NotSupportedException` when a program condition occurs that was unexpected (i.e., like your example with `never`). But since each situation is different, even in my own code, I still like to add a message and not force the message to be the same all the time. ``````/// Raises a not-supported exception for operations that are not supported or unexpected let inline raiseNotSupported message = sprintf "Unexpected operation or program point: %s" message |> NotSupportedException |> raise `````` And then, if for one module I need the same messages anyway, I can always simplify it: ``````let inline raiseNotSupported() = raiseNotSupported "this was really unexpected!" ``````

### xp44mm commented Sep 22, 2017

 i like your passion and your knowledge. i hope to standard `never`, because i don't want to break my thought about bussiness logic to be more fluent. after module separate and unit test, the exception prompt has been not very important as past. especially in a coder's internal code. too many exceptions all over code is less than just several exceptions indeed important. so, i have given up this propose. i explain my opinion.

### abelbraaksma commented Sep 22, 2017 • edited

 too many exceptions all over code is less than just several exceptions indeed important. You will find that coding with F# requires hardly any exceptions. And a good coding practice is to define them centrally, but give specific messages for each situation (which you can define in a resource file). F# 4.1 added a few new easy-access exceptions for the common case, but specific cases like these naturally aren't in there, as they only apply to one or a few situations. Since you can override everything in F# and even redefine `failwith` to become a function that doesn't take a string, I think you'll have plenty of tools at hand to write your own libraries. That's what programming is about. And if you think your library makes sense to be used by others, you can share it here on github, as you do now, or elsewhere. A good starting point for sharing your snippets is: http://www.fssnip.net/.