www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Compile delegate with enum into proper function?

reply jmh530 <john.michael.hall gmail.com> writes:
In the code below, there is a two parameter function `foo` and an 
override of it with only one parameter. In the override case, I 
force the second one to be 1, but ideally there should be a way 
to specify it at compile-time.

It would be kind of nice to be able to do it with an enum and a 
delegate or something, perhaps like `foo2`. However, that is 
still generating a delegate. Something like `foo3` also works, 
but I can't create that within a main function like I can for the 
delegate.

I suppose the question is why can't I tell the compiler to 
compile a delegate into a proper function? I suppose this also 
holds for a function pointer. The difference I suppose is that 
the delegate with enums isn't really taking advantage of the 
features of a delegate, at least as far as I can tell.

```d
int foo(int x, int a) {
     return x + a;
}

int foo(int x) {
     return x + 1;
}

enum int a = 1;
auto foo2 = (int x) => {foo(x, a)};
int foo3(int x) {
     return x + a;
}
```
May 07 2022
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 7 May 2022 at 18:36:40 UTC, jmh530 wrote:
 In the code below, there is a two parameter function `foo` and 
 an override of it with only one parameter. In the override 
 case, I force the second one to be 1, but ideally there should 
 be a way to specify it at compile-time.
Have you tried [`std.functional.partial`][1]? Using it, your example could be written like this: ```d import std.functional: partial; enum int a = 1; alias foo2 = partial!(foo, a); ``` Or, if `a` absolutely has to be the second argument, you can combine it with [`std.functional.reverseArgs`][2]: ```d import std.functional: partial, reverseArgs; enum int a = 1; alias foo2 = partial!(reverseArgs!foo, a); ``` [1]: https://phobos.dpldocs.info/std.functional.partial.html [2]: https://phobos.dpldocs.info/std.functional.reverseArgs.html
May 07 2022
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Saturday, 7 May 2022 at 18:46:03 UTC, Paul Backus wrote:
 On Saturday, 7 May 2022 at 18:36:40 UTC, jmh530 wrote:
 In the code below, there is a two parameter function `foo` and 
 an override of it with only one parameter. In the override 
 case, I force the second one to be 1, but ideally there should 
 be a way to specify it at compile-time.
Have you tried [`std.functional.partial`][1]? Using it, your example could be written like this: ```d import std.functional: partial; enum int a = 1; alias foo2 = partial!(foo, a); ``` [snip]
Thanks. This is basically equivalent to ```d int foo(int a)(int x) { return x + a; } alias foo2 = foo!a; ``` The downside is that you wouldn't be able to `alias foo = foo!a`. Another approach would be to do something like ```d int foo(int b = a)(int x) { return x + b; } ``` so that the default case could be handled.
May 07 2022
parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 7 May 2022 at 20:24:39 UTC, jmh530 wrote:
 On Saturday, 7 May 2022 at 18:46:03 UTC, Paul Backus wrote:
 ```d
 import std.functional: partial;

 enum int a = 1;
 alias foo2 = partial!(foo, a);
 ```

 [snip]
Thanks. This is basically equivalent to ```d int foo(int a)(int x) { return x + a; } alias foo2 = foo!a; ``` The downside is that you wouldn't be able to `alias foo = foo!a`.
Worth noting that you *can* write ```d alias foo = partial!(foo, a); ``` ...which will add the partially-applied version to `foo`'s overload set.
May 07 2022
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Saturday, 7 May 2022 at 23:30:37 UTC, Paul Backus wrote:
 [snip]

 Worth noting that you *can* write

 ```d
 alias foo = partial!(foo, a);
 ```

 ...which will add the partially-applied version to `foo`'s 
 overload set.
You sure about that? Below fails to compile on godbolt with ldc 1.27.1 [1]. For some reason run.dlang.org is just hanging... ```d import core.stdc.stdio: printf; import std: partial; int foo(int x, int a) { return x + a; } enum int a = 2; alias foo = partial!(foo, a); void main() { int x = 2; int y = foo(x, a); printf("the value of y is %i", y); auto z = foo(x); printf("the value of z is %i", z); } ``` [1] https://d.godbolt.org/z/dx8aWfjYW
May 07 2022
parent reply Tejas <notrealemail gmail.com> writes:
On Sunday, 8 May 2022 at 01:38:55 UTC, jmh530 wrote:
 On Saturday, 7 May 2022 at 23:30:37 UTC, Paul Backus wrote:
 [snip]

 Worth noting that you *can* write

 ```d
 alias foo = partial!(foo, a);
 ```

 ...which will add the partially-applied version to `foo`'s 
 overload set.
You sure about that? Below fails to compile on godbolt with ldc 1.27.1 [1]. For some reason run.dlang.org is just hanging... ```d import core.stdc.stdio: printf; import std: partial; int foo(int x, int a) { return x + a; } enum int a = 2; alias foo = partial!(foo, a); void main() { int x = 2; int y = foo(x, a); printf("the value of y is %i", y); auto z = foo(x); printf("the value of z is %i", z); } ``` [1] https://d.godbolt.org/z/dx8aWfjYW
If there is only one possible value for the overload, is there an issue with using default arguments? ```d int foo(int x, int a = 1) { return x + a; } void main() { import std.stdio:writeln; writeln(foo(5)); writeln(foo(6, 7)); } ```
May 07 2022
next sibling parent Salih Dincer <salihdb hotmail.com> writes:
Either we didn't understand the question, or this is not what 
you're talking about:

On Sunday, 8 May 2022 at 03:58:06 UTC,
Tejas wrote:
 If there is only one possible value for the  overload, is there 
 an issue with using default arguments?
 ```d
 int foo(int x, int a = 1) {
     return x + a;
 }
 ```
Are the default arguments not enough for you? SDB 79
May 07 2022
prev sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Sunday, 8 May 2022 at 03:58:06 UTC, Tejas wrote:
 [snip]

 If there is only one possible value for the  overload, is there 
 an issue with using default arguments?
 [snip]
Default arguments are intended to be resolved at runtime. That is, if you compile a function with two parameters and one of them has a default, then the compiler will compile one function that has two parameters as inputs. However, since `foo` above is a relatively simple function, if you compile with -O, then it gets inlined. It doesn't matter so much that whether `a` is an enum or a literal since the compiler knows what it is at compile time and will inline it to remove the call to `foo` anyway. I am interested in more complex cases where the compiler isn't able to inline the function and where the behavior of the second parameter might be more significant. The default parameter would then be doing the calculation at runtime when ideally may be known at compile-time and the compiler could generate a separate function that is simpler taking only one parameter.
May 08 2022
prev sibling parent Tejas <notrealemail gmail.com> writes:
On Saturday, 7 May 2022 at 18:36:40 UTC, jmh530 wrote:
 In the code below, there is a two parameter function `foo` and 
 an override of it with only one parameter. In the override 
 case, I force the second one to be 1, but ideally there should 
 be a way to specify it at compile-time.

 It would be kind of nice to be able to do it with an enum and a 
 delegate or something, perhaps like `foo2`. However, that is 
 still generating a delegate. Something like `foo3` also works, 
 but I can't create that within a main function like I can for 
 the delegate.

 I suppose the question is why can't I tell the compiler to 
 compile a delegate into a proper function? I suppose this also 
 holds for a function pointer. The difference I suppose is that 
 the delegate with enums isn't really taking advantage of the 
 features of a delegate, at least as far as I can tell.

 ```d
 int foo(int x, int a) {
     return x + a;
 }

 int foo(int x) {
     return x + 1;
 }

 enum int a = 1;
 auto foo2 = (int x) => {foo(x, a)};
 int foo3(int x) {
     return x + a;
 }
 ```

```d
  auto foo2 = (int x) => {foo(x, a)};

```

Why did you use the `{ }` when you already used `=>`???
The following code compiles `foo2` as a function

```d
int foo(int x, int a)   nogc
{
     return x + a;
}

int foo(int x)
{
     return x + 1;
}

enum int a = 1;
auto foo2 = (int x)  nogc => foo(x, a);

int foo3(int x)
{
     return x + a;
}

void main() nogc
{
     foo2(5);
     pragma(msg, typeof(foo2)); //int function(int x)  nogc  system
}
```

I still recommend using my default argument values solution 
though if it is feasible.
May 08 2022