fsharp / fsharp/fslang-suggestions

Inline bind operator for computation expressions

Open
#1,070 23 comments 28 reactions 0 assignees View on GitHub
approved-in-principle area: computation-expressions
Dominant language
No language data
Stars
373
Forks
21
PR merge metrics
No merged PRs in 30d

Description

I propose we add an operator or keyword which can be used to bind values in computation expressions deep inside expressions (potentially arbitrarily), similar to C#'s await keyword, which can be used in the middle of expressions, and is not limited to top-level expressions in the computation expression. The specific syntax is of lesser issue than the form of these expressions themselves. This proposal has been alluded up many times within the F# community.

For sake of discussion, I am going to use a ``bind!`` syntax in this proposal (which could easily be replaced with one of the alternative choices).

The following code:

```fsharp
if (f(bind! x) && bind! y) then // ...
```

would be lifted to something equivalent to:

```fsharp
let! x' = x
let! y' = y
if (f x' && y') then // ...
```

There are many more cases where this should likely work, such as:

```fsharp
// right-hand of let-expr
let x = bind! expr
// deep inside right-hand of let-expr
let x = (bind! expr) |> List.map string
// match expr
match bind! expr with
```

And so on -- there are likely more cases to consider and decide on.

However, this would not be allowed arbitrarily deep, as the following should obviously be disallowed:

```fsharp
async {
let f = (fun () -> bind! expr) // compiler error -- not allowed inside lambdas
let g x =
bind! expr // compiler error -- not allowed inside nested functions
}
```

There are also probably other exclusions that should be fleshed out.

The current way to approach this is to manually lift the bindable expression and bind it using ``let!``.

### Alternative keywords

* ``bind``
* ``bind!``
* ``await``
* ``await!``
* postfix ``!``

Postfix bang would look something like:

```fsharp
if (f(a!) && b!) then // ...
```

## Pros and Cons

The advantages of making this adjustment to F# are:

* More parity with C#'s deeply nestable ``await`` keyword
* Highly useful because it allows the elimination of many otherwise unnecessary variable names in source code
* Reduces the urgency for more bang-keywords

The disadvantages of making this adjustment to F# are:

* more complexity

## Extra information

Estimated cost (XS, S, M, L, XL, XXL): L (I'm guessing)

Related suggestions: [#572 (match-bang)](https://github.com/fsharp/fslang-suggestions/issues/572), [#651 (finally-bang)](https://github.com/fsharp/fslang-suggestions/issues/651), [#791 (pipe-bang)](https://github.com/fsharp/fslang-suggestions/issues/791), [#863 (if-bang)](https://github.com/fsharp/fslang-suggestions/issues/863), [#974 (function-bang)](https://github.com/fsharp/fslang-suggestions/issues/974), [#1038 (while-bang)](https://github.com/fsharp/fslang-suggestions/issues/1038)

## Affidavit (please submit!)

Please tick this by placing a cross in the box:
* [x] This is not a question (e.g. like one you might ask on [stackoverflow](http://stackoverflow.com)) and I have searched stackoverflow for discussions of this issue
* [x] I have [searched both open and closed suggestions on this site](http://github.com/fsharp/fslang-suggestions/issues) and believe this is not a duplicate
* [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:
* [x] This is not a breaking change to the F# language design
* [x] I or my company would be willing to help implement and/or test this

## For Readers

If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

Contributor guide

No contributing guide indexed for this repository

Research direction

No implementation files, tests, or compiler entry points are identified in the proposal. First clarify the syntax, expression-boundary rules, exclusions, and interaction with computation expressions; done would require an agreed language design plus corresponding compiler and test changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
fsharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.