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

RFC FS-1007: Additions to Option module #1781

Merged
merged 16 commits into from
Dec 17, 2016

Conversation

neoeinstein
Copy link
Contributor

This PR provides an implementation for RFC FS-1007 and is discussed in fslang-design.

Added functions:

val defaultIfNone :              'a         -> 'a option -> 'a
val defaultIfNoneFrom : (unit -> 'a)        -> 'a option -> 'a
val orElse :                     'a option  -> 'a option -> 'a option
val orElseFrom :        (unit -> 'a option) -> 'a option -> 'a option

val map2: ('a -> 'b -> 'c)       -> 'a option -> 'b option -> 'c option
val map3: ('a -> 'b -> 'c -> 'd) -> 'a option -> 'b option -> 'c option -> 'd option

val apply: 'a option -> ('a -> 'b) option -> 'b option

val contains: 'a -> 'a option -> bool

val flatten: 'a option option -> 'a option

This PR includes and supersedes #1636.

@msftclas
Copy link

Hi @neoeinstein, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
You've already signed the contribution license agreement. Thanks!

The agreement was validated by Microsoft and real humans are currently evaluating your PR.

TTYL, MSBOT;

@@ -16,6 +16,18 @@ namespace Microsoft.FSharp.Core
[<CompiledName("IsNone")>]
let inline isNone option = match option with None -> true | Some _ -> false

[<CompiledName("DefaultIfNone")>]
let defaultIfNone def option = match option with None -> def | Some v -> v
Copy link
Member

Choose a reason for hiding this comment

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

probably inline. I'm guessing this will be the most commonly used of these.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For use cases like this, is it more appropriate to give the JIT a hint to do the inlining with AggressiveInlining? I see the case for inline on contains, but still a bit unsure for defaultValue and orElse.

let defaultIfNoneFrom defThunk option = match option with None -> defThunk () | Some v -> v

[<CompiledName("OrElse")>]
let orElse ifNone option = match option with None -> ifNone | Some _ -> option
Copy link
Member

Choose a reason for hiding this comment

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

Probably inline.

@@ -31,15 +43,39 @@ namespace Microsoft.FSharp.Core
[<CompiledName("ForAll")>]
let forall p inp = match inp with None -> true | Some x -> p x

[<CompiledName("Contains")>]
let contains x inp = match inp with None -> false | Some v -> v = x
Copy link
Member

Choose a reason for hiding this comment

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

Inline I would think. Quite common too.

Copy link
Contributor Author

@neoeinstein neoeinstein Nov 22, 2016

Choose a reason for hiding this comment

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

I've been considering what the relative benefits of inline are to letting JIT handle it. I've posted a gist with the IL that was generated on my computer for the Option module. Most of the functions are less than 32 bytes of IL, with the only exceptions being get, map2, and map3, which makes them largely eligible for JIT-inlining. What incremental benefit does the inline keyword provide in this case?

Copy link
Contributor

Choose a reason for hiding this comment

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

What incremental benefit does the inline keyword provide in this case?

Generic equality is used in the body. That's expensive, but becomes cheap if type-specialized. Definitely an incentive to inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's exactly the information I was looking for. I'll add inlines appropriate to this advice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Inline for contains has been added.

@dsyme
Copy link
Contributor

dsyme commented Nov 22, 2016

I gave some feedback on the RFC here: fsharp/fslang-design#60 (comment). Just a couple of naming changes requested

Per @dsyme, generic equality is expensive but with inlining, the compiler
can type-specialize the call, making it much cheaper.
@KevinRansom
Copy link
Member

@dotnet-bot test this please

@KevinRansom
Copy link
Member

@dotnet-bot test this please

@KevinRansom KevinRansom merged commit ca2ed9b into dotnet:master Dec 17, 2016
@KevinRansom
Copy link
Member

@neoeinstein
Thank you for these great additions

Kevin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants