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

ProvidedParameter: make it optional without a default value #312

Closed
ivelten opened this issue May 17, 2019 · 3 comments
Closed

ProvidedParameter: make it optional without a default value #312

ivelten opened this issue May 17, 2019 · 3 comments

Comments

@ivelten
Copy link

ivelten commented May 17, 2019

Description

I am developing a provided type having properties that can be options. For this type, I want a constructor that takes all those properties as arguments, to fill them (more or less like the constructor of a record type). However, properties that are options are being mapped to optional arguments.

But those arguments are not Options, instead, they take the underlying option type as the type. For example a type Record with two properties, A : int and B: int option would have a constructor with this signature:

new(a: int, ?b: int)

The second parameter of the constructor would need to be mapped with optionalValue filled, but I can't assume a default value for int as zero. If I try passing None or null, and coerce it as an object inside the quotation, it gives me zero as a value:

// ...
let prm = ProvidedParameter("b", typeof<int>, optionalValue = null)
// ...
let invoker (args : Expr list) =
    let b = Expr.Coerce(args.[1], typeof<obj>) // This returns zero instead of null

Expected behavior

I expect to have an optional parameter of a value type and have the option to know if the user didn't pass a value, without having to explicitly receive a default value.

Actual behavior

If I want to provide an optional parameter, I must explicitly pass a default value, and that value needs to be the same type of the parameter, so value types can not have a valid representation of "empty" or a way to know "if the user didn't provide a value".

Known workarounds

1. Make optional parameters of Option types. That would be a design that I would like to avoid since if I don't want to pass a value, I should just not be passing a parameter, or if I want to pass a value, I should not pass it as Some value, but simply as value.

2. Make constructor overloads. This is the thing I am trying at the moment. However, that could become hard to manage if I have a provided type with a lot of optional properties.

@Tarmil
Copy link
Contributor

Tarmil commented Jun 18, 2019

The reason for this is that the TP generates C#-style optionals, ie the equivalent of this:

new(a: int, [<Optional; DefaultParameterValue 0>] b: int)

aka this in C#:

MyClass(int a, int b = 0)

and not F#-style optionals, ie the equivalent of this:

new(a: int, ?b: int)

@ivelten
Copy link
Author

ivelten commented Jun 19, 2019

Yes, I figured it out, @Tarmil. I just ended an implementation of a combination function to generate overloads for optional parameters. It's working well, even with a lot of overloads. I guess this will not be an issue, since in theory, optional parameters seems to be compiled into method overloads at the IL.

@dsyme
Copy link
Contributor

dsyme commented Sep 21, 2021

Closing this old issue

@dsyme dsyme closed this as completed Sep 21, 2021
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

No branches or pull requests

3 participants