Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RequireQualifiedAccess section #39

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions docs/fsharp-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1117,7 +1117,7 @@ module MyNamespace.SubNamespace.Functions

<div id="open-and-autoopen"></div>

## Open and AutoOpen
## Open
The `open` keyword can be used on `module`, `namespace`, and `type`.

```fsharp
@@ -1139,7 +1139,26 @@ open type System.Text.RegularExpressions.Regex // type
let isHttp url = IsMatch("^https?:", url) // Regex.IsMatch directly accessible
```

Available to `module` declarations only, is the `AutoOpen` attribute, which alleviates the need for an `open`.
### RequireQualifiedAccess Attribute

This attribute can be used on modules, records, and discriminated unions to avoid namespace collisions and unexpected "shadowing". It can also make your code more explicit and readable.

```fsharp
[<RequireQualifiedAccess>]
module Math =
let add x y = x + y
let subtract x y = x - y

open Math // Error! Although you may open the containing namespace, if allowed.

// As you can't open the module, you must use qualified names for module members.
let sum = Math.add 5 3 // Works
let diff = subtract 5 3 // Error!
```

### AutoOpen Attribute

Applicable to `module` declarations only, the `AutoOpen` attribute alleviates the need for an `open`.

```fsharp
[<AutoOpen>]
@@ -1151,11 +1170,10 @@ module Groceries =
let fruit = Banana
```

*However*, `AutoOpen` should be used cautiously. When an `open` or `AutoOpen` is used, all declarations in the containing element
will be brought into scope. This can lead to [shadowing](https://en.wikipedia.org/wiki/Variable_shadowing); where the last
named declaration replaces all prior identically-named declarations. There is *no* error - or even a warning - in F#, when shadowing occurs.
A [coding convention (MS Learn)](https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/conventions#sort-open-statements-topologically) exists for `open`
statements to avoid pitfalls; `AutoOpen` would sidestep this.
#### Use `AutoOpen` and/or ignore `RequireQualifiedAccess` best practice with caution!

Functions with identical names from different modules will silently "shadow" each other, causing the most recently imported definition to be used instead of the one you might expect. **The compiler will _not_ warn you that this has happened.** Even if your code works, you may encounter compiler errors if the `open` order changes. A [coding convention (MS Learn)](https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/conventions#sort-open-statements-topologically) exists for `open` statements to avoid pitfalls.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this warning about silent meaning changes is not inaccurate, but I can imagine it scaring people into thinking they might as well be using something typeless. I dont know how I'd convey it, but the only real problem it triggers is inferring the wrong type where it's not pinned, which then manifests as an error some distance away in terms of files or compile time.



## Accessibility Modifiers