On Sunday, April 01, 2018 22:34:16 Seb via Digitalmars-d-learn wrote:
> On Sunday, 1 April 2018 at 15:54:16 UTC, Steven Schveighoffer
>
> wrote:
> > I currently have a situation where I want to have a function
> > that accepts a parameter optionally.
> >
> > I thought maybe Nullable!int might work:
> >
> > void foo(Nullable!int) {}
> >
> > void main()
> > {
> >
> >    foo(1); // error
> >    int x;
> >    foo(x); // error
> >
> > }
> >
> > Apparently, I have to manually wrap an int to get it to pass.
> > In other languages that support optional types, I can do such
> > things, and it works without issues.
> >
> > I know I can do things like this:
> >
> > void foo(int x) { return foo(nullable(x)); }
> >
> > But I'd rather avoid such things if possible. Is there a way
> > around this? Seems rather limiting that I can do:
> >
> > Nullable!int x = 1;
> >
> > but I can't implicitly convert 1 to a Nullable!int for function
> > calls.
> >
> > -Steve
>
> My workaround is to use struct initialization:
>
> ---
> import std.stdio, std.typecons;
>
> static struct FooConfig
> {
>      Nullable!int a;
> }
>
> void foo(FooConfig optionalConfig = FooConfig.init)
> {
>      optionalConfig.writeln;
> }
>
> void main()
> {
>      foo();
>
>      FooConfig params = {
>         a: 42,
>      };
>      foo(params);
>      //foo(FooConfig(42)); // <- hehe, no implicit conversion
> }
> ---
>
> https://run.dlang.io/is/HvN701
>
> I know the separate line and variable is annoying.
> With the in-place struct-initialization DIP
> (https://github.com/dlang/DIPs/pull/71), it would become sth.
> like:
>
> foo(FooConfig({a : 42}));
> foo(FooConfig{a : 42});
>
> (syntax is not clear yet and I still haven't gotten around
> implementing this in DMD)

How is any of that better than just using nullable(42)? The whole annoyance
here is that there is no implicit conversion and that something explicit is
required. Changing what the explicit construction is doesn't help much, from
where I sit, something like

foo(FooConfig({a : 42:}));

is way worse than

foo(nullable(42));

and even if you're sticking to FooConfig,

foo(FooConfig(42));

would be less verbose. The whole {a : 42} thing only starts making sense
when you have a struct with several members where you want to be able to
initialize only certain ones at a time without declaring all of the various
constructors to allow all of the combinations and/or you have enough members
of the same type that you pretty much need to provide the names with the
arguments for it to be clear what's being initialized. Otherwise, normal
construction works just fine, and it wouldn't help at all in a case like
Steven has where he's trying to pass a type and have it implicitly converted
to another when it's passed. If you're going to do something explicit,
nullable(value) works just fine. It's the fact that something explicit is
required at all that's the problem.

- Jonathan M Davis

Reply via email to