digitalmars.D.learn - Compile delegate with enum into proper function?
- jmh530 (27/27) May 07 2022 In the code below, there is a two parameter function `foo` and an
- Paul Backus (17/21) May 07 2022 Have you tried [`std.functional.partial`][1]? Using it, your
- jmh530 (12/25) May 07 2022 Thanks. This is basically equivalent to
- Paul Backus (7/23) May 07 2022 Worth noting that you *can* write
- jmh530 (20/27) May 07 2022 You sure about that? Below fails to compile on godbolt with ldc
- Tejas (14/44) May 07 2022 If there is only one possible value for the overload, is there
- Salih Dincer (6/13) May 07 2022 Either we didn't understand the question, or this is not what
- jmh530 (16/20) May 08 2022 Default arguments are intended to be resolved at runtime. That
- Tejas (29/56) May 08 2022 ```d
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
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
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: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.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]
May 07 2022
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:Worth noting that you *can* write ```d alias foo = partial!(foo, a); ``` ...which will add the partially-applied version to `foo`'s overload set.```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`.
May 07 2022
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
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: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)); } ```[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
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
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
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