Thread overview
Create module-level function using mixin template?
Apr 25
monkyyy
Apr 25
monkyyy
5 days ago
cc
5 days ago
Andy Valencia
April 25

I have a code pattern, and would like to generate rather than copy/paste. It seems like mixin templates apply, but I'm not having much luck. I saw one comment that templates always expand in their own context, so perhaps they're not useful for generating a top-level function?

Andy

bool bigtest(in string s) {
    return true;
}

bool test1(in char c) {
    return false;
}
bool test2(in char c) {
    return true;
}

mixin template MyFunc(alias fn) {
    bool fn(in string s) {
        if (!bigtest(s)) {
            return false;
        }
        foreach(c; s) {
            if (!fn(c)) {
                return false;
            }
        }
        return true;
    }
}

mixin MyFunc!test1;
mixin MyFunc!test2;

int main() {
    if (!test1("Hello, world")) {
        return(1);
    }
    if (!test2("Hello, world")) {
        return(1);
    }
    return(0);
}
April 25

On Friday, 25 April 2025 at 16:14:49 UTC, Andy Valencia wrote:

>

I have a code pattern, and would like to generate rather than copy/paste. It seems like mixin templates apply, but I'm not having much luck. I saw one comment that templates always expand in their own context, so perhaps they're not useful for generating a top-level function?

Andy

its extremely unclear what your trying to do my best geuss:

int func1()=>3;
int func2()=>4;

mixin template makenewfunction(alias F,int reference){
    int newfunction(int i:reference)(){
	return F()*100;
}}

mixin makenewfunction!(func1,2);
mixin makenewfunction!(func2,1);

import std;
void main(){
    newfunction!1.writeln;
    newfunction!2.writeln;
}

contexts airnt quite the same as unreachable, but you will need to have a bunch of tricks to disambiguate in practice

April 25

On Friday, 25 April 2025 at 16:59:16 UTC, monkyyy wrote:

>

its extremely unclear what your trying to do my best geuss:

I want to use a mixin template to generate a top-level function. Like, is there a variant of the following which makes a function named "foo1" available?

Andy

mixin template Foo(alias fn) {
    int fn() { return 1; }
}

mixin Foo!foo1;

void main() {
    import std.stdio : writeln;

    writeln(foo1());
}
April 25
On 4/25/25 10:24 AM, Andy Valencia wrote:
> On Friday, 25 April 2025 at 16:59:16 UTC, monkyyy wrote:
>> its extremely unclear what your trying to do my best geuss:
> 
> I want to use a mixin template to generate a top-level function. Like, is there a variant of the following which makes a function named "foo1" available?
> 
> Andy
> 
> ```d
> mixin template Foo(alias fn) {
>      int fn() { return 1; }
> }
> 
> mixin Foo!foo1;
> 
> void main() {
>      import std.stdio : writeln;
> 
>      writeln(foo1());
> }
> ```

I think an 'alias' template parameter must refer to an existing symbol, which you don't have. Although I've been missing a feature of "string parameters without quotes", here is a solution:

mixin template Foo(string fn, int i) {
    int Foo() { return i; }

    mixin ("alias " ~ fn ~ " = Foo;");
}

mixin Foo!("foo1", 1);
mixin Foo!("foo2", 2);

void main() {
    import std.stdio : writeln;

    writeln(foo1());
    writeln(foo2());
}

Ali

April 25
On Fri, Apr 25, 2025 at 05:24:18PM +0000, Andy Valencia via Digitalmars-d-learn wrote:
> On Friday, 25 April 2025 at 16:59:16 UTC, monkyyy wrote:
> > its extremely unclear what your trying to do my best geuss:
> 
> I want to use a mixin template to generate a top-level function.

Your best bet actually is to use a string mixin.  The quoted token string can help make the generating code more readable. For example:

```d
	string makeFunc(string name) {
		return q{
			int }~name~q{() {
				return 1;
			}
		};
	}

	mixin(makeFunc("myfunc"));

	void main() {
		assert(myfunc() == 1);
	}
```


T

-- 
I see that you JS got Bach.
April 25

On Friday, 25 April 2025 at 17:24:18 UTC, Andy Valencia wrote:

>

On Friday, 25 April 2025 at 16:59:16 UTC, monkyyy wrote:

>

its extremely unclear what your trying to do my best geuss:

I want to use a mixin template to generate a top-level function. Like, is there a variant of the following which makes a function named "foo1" available?

Andy

mixin template Foo(alias fn) {
    int fn() { return 1; }
}

mixin Foo!foo1;

void main() {
    import std.stdio : writeln;

    writeln(foo1());
}

If we ever get string mixins of identifiers maybe, but as is it wont go that well

like you have the identifier at programing time, use an alias alias foo1=Foo(...)
if you need a list, use an int and specialization, you can then access it with static foreach(I;0..N){
if you have arguements, use a standard template
if you need to use features from a struct; use propertys of the struct in line of a meta program

5 days ago

On Friday, 25 April 2025 at 16:14:49 UTC, Andy Valencia wrote:

>

I have a code pattern, and would like to generate rather than copy/paste. It seems like mixin templates apply, but I'm not having much luck. I saw one comment that templates always expand in their own context, so perhaps they're not useful for generating a top-level function?

I assume this is what you wanted to do (given existing functions that take a char, create overloads that take a whole string)?

bool bigtest(in string s) {
    return true;
}

bool test1(in char c) {
    return false;
}
bool test2(in char c) {
    return true;
}

bool MyFunc(alias fn)(in string s) {
    if (!bigtest(s)) {
        return false;
    }
    foreach(c; s) {
        if (!fn(c)) {
            return false;
        }
    }
    return true;
}

alias test1 = MyFunc!test1;
alias test2 = MyFunc!test2;

int main() {
    if (!test1("Hello, world")) {
        return(1);
    }
    if (!test2("Hello, world")) {
        return(1);
    }
    return(0);
}

Alternatively you could replace the alias lines with something like:

static foreach (funcname; ["test1", "test2"]) {
	mixin(format(`alias %s = MyFunc!(%s);`, funcname, funcname));
}

Note: mixin abc; and mixin(abc); do two related but different things.
Though personally I would advise against either of these, and just call the templated function directly from your code, which makes it much more self-documenting about what's going on:

int main() {
    if (!MyFunc!test1("Hello, world")) {
        return(1);
    }
    if (!MyFunc!test2("Hello, world")) {
        return(1);
    }
    return(0);
}
5 days ago

On Wednesday, 30 April 2025 at 06:08:23 UTC, cc wrote:

>

On Friday, 25 April 2025 at 16:14:49 UTC, Andy Valencia wrote:

>

I have a code pattern, and would like to generate rather than copy/paste. It seems like mixin templates apply, but I'm not having much luck. I saw one comment that templates always expand in their own context, so perhaps they're not useful for generating a top-level function?

I assume this is what you wanted to do (given existing functions that take a char, create overloads that take a whole string)?

bool bigtest(in string s) {
    return true;
}

bool test1(in char c) {
    return false;
}
bool test2(in char c) {
    return true;
}

bool MyFunc(alias fn)(in string s) {
    if (!bigtest(s)) {
        return false;
    }
    foreach(c; s) {
        if (!fn(c)) {
            return false;
        }
    }
    return true;
}

alias test1 = MyFunc!test1;
alias test2 = MyFunc!test2;

int main() {
    if (!test1("Hello, world")) {
        return(1);
    }
    if (!test2("Hello, world")) {
        return(1);
    }
    return(0);
}

As a workaround, I had just used a pointer to a function argument. I assumed this--which would make the leaf function visible during compilation of the string function--would perform better. But, on 1.40.1 with x86-64, it's about twice as slow! But it does show a useful technique which I'm sure I'll use at some point.

Thanks,
Andy