Thread overview
Using a macro for a function signature
Apr 05, 2016
pineapple
Apr 05, 2016
pineapple
Apr 05, 2016
Anonymouse
Apr 05, 2016
pineapple
Apr 05, 2016
ag0aep6g
April 05, 2016
If I have a common function signature I'm using throughout my code, and I feel like there should be a way to condense it using a macro. The intuitive method isn't working, but this seems like something D would be able to do. What've I got wrong in this example?



alias somelongsignature = int(in int x);

int examplefunc0(in int x){
    return x * 2;
}

somelongsignature testfunc0 = examplefunc1;
somelongsignature testfunc1 = somelongsignature {return x + 3};

public void main(){
    import std.stdio;
    writeln(testfunc0(5)); // Should output 10
    writeln(testfunc1(5)); // Should output 8
}



Thanks!
April 05, 2016
Ah, aside from the mismatched "examplefunc" numbers - please disregard

Can't post example code without stupid typos for the life of me
April 05, 2016
On Tuesday, 5 April 2016 at 11:35:24 UTC, pineapple wrote:
> If I have a common function signature I'm using throughout my code, and I feel like there should be a way to condense it using a macro. The intuitive method isn't working, but this seems like something D would be able to do. What've I got wrong in this example?
>
>
>
> alias somelongsignature = int(in int x);

alias somelongsignature = int function(in int);

> int examplefunc0(in int x){
>     return x * 2;
> }
>
> somelongsignature testfunc0 = examplefunc1;
> somelongsignature testfunc1 = somelongsignature {return x + 3};

somelongsignature testfunc0 = &examplefunc0;
somelongsignature testfunc1 = function(in int x){return x + 3;};
somelongsignature testfunc2 = function(x){return x + 15;};
somelongsignature testfunc3 = (in int x){return x + 20;};
somelongsignature testfunc4 = (x){return x + 25;};
somelongsignature testfunc5 = (x => x+30);
// probably more

You can't get rid of the signature completely as the functions still need a parameter list with x declared. You will get "Error: undefined identifier 'x'" otherwise. You can largely omit the *type* of x if it can be inferred from the signature, but you can't have its name be solely in the signature alias.

Parantheses are optional when calling functions without arguments. This is valid D:

void main() {
    import std.stdio;
    writeln;  // valid, no parantheses makes it writeln(), compare 'testfunc0 = examplefunc1/*()*/;'
    writeln = "Hello world!";  // valid, looks funky but helps with properties

    // auto doesntwork = writeln;  // invalid, writeln() returns void
    // auto doesntworkeither = &writeln;  // invalid, writeln is a template

    alias println = writeln;  // valid, aliases to templates work
    println("Hello world again!");
    println;
    println(3.14);
}

So the original code was trying to assign testfunc0 the return value of a call to examplefunc1(), which doesn't exist. You want the function pointer instead.
April 05, 2016
On 05.04.2016 13:35, pineapple wrote:
> alias somelongsignature = int(in int x);

alias somelongsignature = int function(in int);

Or if you want to accept methods and such:

alias somelongsignature = int delegate(in int);

You can name the parameter, but it won't be part of the type.

> int examplefunc0(in int x){
>      return x * 2;
> }
>
> somelongsignature testfunc0 = examplefunc1;

somelongsignature testfunc0 = &examplefunc0;

Note the ampersand.

> somelongsignature testfunc1 = somelongsignature {return x + 3};

I don't think there's a way to do this as nicely as you want.

One thing you can do is declare the parameters without types:

somelongsignature testfunc1 = (x) {return x + 3;};

Saves you some typing, especially with complicated parameter types.

Another thing is std.traits.Parameters:

alias F = int function(int, float, string, void*);
import std.traits: Parameters;
F testfunc2 = (Parameters!F args) {return args[0] + 3;};

This way you don't have to type out a long list of parameters, but `args[0]` isn't as nice as `x`, of course.

There may be a way to transfer the parameter names as well, but I suspect that's going to be a little more fiddly.
April 05, 2016
On Tuesday, 5 April 2016 at 13:17:38 UTC, Anonymouse wrote:
> You can't get rid of the signature completely as the functions still need a parameter list with x declared. You will get "Error: undefined identifier 'x'" otherwise. You can largely omit the *type* of x if it can be inferred from the signature, but you can't have its name be solely in the signature alias.

On Tuesday, 5 April 2016 at 13:19:43 UTC, ag0aep6g wrote:
> On 05.04.2016 13:35, pineapple wrote:
> Saves you some typing, especially with complicated parameter types.
>
> Another thing is std.traits.Parameters

You are both wonderful, this is exactly what I was trying to work out. Thank you so much!