fsharp / fsharp/fslang-suggestions

Allow attributes after the module keyword

Open
#757 5 comments 6 reactions 0 assignees View on GitHub
approved-in-principle area: syntax
Dominant language
No language data
Stars
373
Forks
21
PR merge metrics
No merged PRs in 30d

Description

RFC https://github.com/fsharp/fslang-design/blob/main/preview/FS-1107-Allow-attributes-after-the-module-keyword.md

# Allow attributes after the module keyword

Consider:
```fs
[]
module M =
[]
type C() = class end
[]
let X = 3
```
The `Literal` attribute can be embedded into the `let`:
```fs
[]
module M =
[]
type C() = class end
let [] X = 3 // ✓
```
Same for the `AbstractClass`:
```fs
[]
module M =
type [] C() = class end // ✓
let [] X = 3
```
But not the `AutoOpen`.
```fs
module [] M = // FS0010: Unexpected start of structured construct in definition. Expected identifier, 'global' or other token.
type [] C() = class end // FS0010: Unexpected keyword 'type' in implementation file
let [] X = 3
```

The existing way of approaching this problem in F# is leaving the `AutoOpen` above the `module`.

## Pros and Cons

The advantages of making this adjustment to F# are
1. Consistency - `module`s are just specialized `type`s, so placing attributes after the keyword should be allowed as well.
2. Conciseness - we can utilize the horizontal space to our advantage, thus scrolling less.

The disadvantage of making this adjustment to F# is having more ways to do the same thing. However, precedence has been already made for `type`s and `let`s.

## Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions:
#33
I would say that this should be allowed for `member`s as well.
```fs
// Not using a module to ensure that the module suffix is not added
type MyList() =
// Fields omitted
[]
static member map f l =
// Implementation omitted
```
> Thanks for the suggestion
However I will decline this: what we have works, and the proposed saving is only one line, and the lines become loooong. In balance I don't see a net benefit.

Sure, what we have works, but inconsistent language features are worse than having multiple ways to do the same thing. (Recall: Unification of List, Array, Seq functions in F# 4.0)

Whether the lines become long depends on the length of the name of members and attributes. If they are short enough, they deserve to be combined to utilize more horizontal space.

## 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.
(This has sort of been decided for members, but not modules. Module definitions tend to be much shorter than member definitions anyways.)

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

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.