fsharp / fsharp/fslang-suggestions
Support attributes on lambda expressions
- Dominant language
- No language data
- Stars
- 373
- Forks
- 21
- PR merge metrics
- No merged PRs in 30d
Description
I propose we support attributes on lambda expressions. A way this could get used is in the experimental aspnet Houdini project, which is experimenting ways to cut the cruft in aspnet core service development, including an alternate routing system than MVC. One of their approaches would be mapping endpoints with lambdas:
```csharp
record Todo(int Id, string Name, bool IsComplete);
app.MapAction([HttpPost("/")] ([FromBody] Todo todo) : Todo => todo);
app.MapAction([HttpGet("/")] () : Todo => new(Id: 0, Name: "Play more!", IsComplete: false));
```
Note that the lambda itself has an atttribute. In F#, the above snippet would probably look something like this:
```fsharp
type Todo = { Id: int; Name: string; IsComplete: bool }
app.MapAction([] fun ([] todo) -> todo) |> ignore
app.MapAction([] fun () -> { Id = 0; Name = "Play more!"; IsComplete = false }) |> ignore
```
The existing way of approaching this problem in F#, using the above example, would be to pull out the lambda bodies into separate functions and pass them into a constructed `Func`:
```fsharp
type Todo = { Id: int; Name: string; IsComplete: bool }
[]
let echoTodo ([] todo) = todo
[]
let getTodo () = { Id = 0; Name = "Play more!"; IsComplete = false }
app.MapAction(Func(echoTodo)) |> ignore
app.MapAction(Func(getTodo)) |> ignore
```
This isn't really a bad alternative though, the main thing is that it's annoying to have to construct a func. Instead, lobbying to get `MapAction` to support equivalent `FSharpFunc` types as overloads and simply have those overloads construct the appropriate `Func` type could make this approach nice from an F# perspective.
However, I still think it's worth considering (even if people decide it's not really useful for F#) since this is an approach to programming against an API that more library authors may take in the future.
## Pros and Cons
The advantages of making this adjustment to F# are:
* Orthogonality I suppose, since you can decorate an F# function with an attribute. If you do this with a function and then want it to also work with a lambda, you're fine. Although lambdas aren't 100% in correspondence with a function - see use of byrefs for more information.
* Works nicely with APIs that expect people to use this sort of pattern
The disadvantages of making this adjustment to F# are:
* Allows for "call site complication" with lots of information stuffed into a lambda, making seemingly succinct code somewhat complex / difficult to understand
* Encourages stuffing lots of functionality into a lambda expression. Although this is somewhat common, especially in longer pipelines where you don't have a need to pull out an expression into its own function since it's only used once, it's still not "typical" F# code.
* Encourages a way to interact with APIs that we may not want or need
* Not terribly discoverable
## Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here)
## 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
Assessment
This issue has not been assessed yet.