July 13, 2015
>> I don't know what exactly you're after, but you can use foreach on a whatever-they're-called-now tuple (there's been a discussion about the name which I haven't followed; I mean the kind you get from a TemplateTupleParameter):
>> ----
>> void f1() {}
>> void f2() {}
>> void callThemAll(functions ...)()
>> {
>>     foreach(f; functions) /* The loop is unrolled at compile time. */
>>     {
>>         f();
>>     }
>> }
>> void main()
>> {
>>     callThemAll!(f1, f2)();
>> }
>> ----
>>
>> As usual, recursion is an alternative:
>> ----
>> void callThemAll(functions ...)()
>> {
>>     static if(functions.length > 0)
>>     {
>>         functions[0]();
>>         callThemAll!(functions[1 .. $])();
>>     }
>> }
>> ----
>
> Sorry, I don't think I made myself clear enough. Your code allows you to do something like call multiple functions in a loop. I'm talking about the fact that
>
> alias cos = givemeabettername!(std.math.cos);
> alias sin = givemeabettername!(std.math.sin);
>
> are just two functions of many in std.math. Suppose I wanted to write it so that every function in std.math had an array version generated by this code. I would be repeating this alias line once each time. My point is that I don't see a way to do this in a loop. I don't think I can do something like
>
> void callThemAll(functions ...)()
> {
>     foreach(f; functions)
>     {
>         alias __Function__ = givemeabettername!(f); //where __Function__ is the name of the function for f, not callThemAll
>     }
> }
>
> callThemAll(std.math.cos, std.math.sin);
>
> void main()
> {
>     real[] x = [0, PI];
>     auto y = cos(x);
>     auto z = sin(x);
> }

I am venturing in territory still new to me, but I think that was his point - foreach with tuples looks like it is looping, but really it is unpacking them statically at compile time.  And similarly with the recursive version.  I don't know if you can avoid the mixin, but you can make it a little tidier.

import std.math;
import std.stdio;
import std.traits;

mixin template callThemAll(functions...)
{
   	mixin("alias foo"~__traits(identifier,functions[0])~"="~__traits(identifier,functions[0])~";");
    static if(functions.length >1)
   		mixin callThemAll!(functions[1..$]);
}

void main()
{
	mixin callThemAll!(sin,cos,tan);
	writefln("%s",foosin(1));
	writefln("%s",foocos(1));
	writefln("%s",footan(1.0));
}

Not sure if you knew this already and still found it too messy.



July 14, 2015
On Monday, 13 July 2015 at 02:52:11 UTC, Laeeth Isharc wrote:
>
> I am venturing in territory still new to me, but I think that was his point - foreach with tuples looks like it is looping, but really it is unpacking them statically at compile time.  And similarly with the recursive version.  I don't know if you can avoid the mixin, but you can make it a little tidier.
>
> import std.math;
> import std.stdio;
> import std.traits;
>
> mixin template callThemAll(functions...)
> {
>    	mixin("alias foo"~__traits(identifier,functions[0])~"="~__traits(identifier,functions[0])~";");
>     static if(functions.length >1)
>    		mixin callThemAll!(functions[1..$]);
> }
>
> void main()
> {
> 	mixin callThemAll!(sin,cos,tan);
> 	writefln("%s",foosin(1));
> 	writefln("%s",foocos(1));
> 	writefln("%s",footan(1.0));
> }
>
> Not sure if you knew this already and still found it too messy.

I had considered mixins as messy, but my original one was way messier than this. By comparison, it's not so bad.

Beyond the mixins, what I find most interesting was the __traits(identifier,functions[0]). Hadn't seen that before. I was only familiar with __FUNCTION__. It definitely simplifies it

Anyway, the downside of the approach so far is that I can't quite understand why some versions have worked, but not others. For your foo version (with a few modifications to better match what I'm doing), I was able to get it working regardless of whether it was in main or not. That's good. Further, when I got rid of the foo, but kept it in main, it still worked (after changing the function names). However, when I moved it back out of main I was getting messages about there being no cos/sin available for those types.

Note: some of the above seemed to only work when I kept the std.math.cos, std.math.sin text in there. When I take it out, I get warnings about recursive aliases. But, I can't seem to use a foreach loop. The recursive mixin template seems to be required.

So this is the last thing I did (that didn't work). Adding foo back to the alias works.

mixin template callThemAll(functions...)
{
   mixin("alias " ~__traits(identifier, functions[0]) ~
		  " = givemeabettername!(std.math."~__traits(identifier, functions[0]) ~ ");");
    static if(functions.length >1)
   		mixin callThemAll!(functions[1..$]);
}

mixin callThemAll!(cos, sin);
July 14, 2015
On Tuesday, 14 July 2015 at 01:05:21 UTC, jmh530 wrote:
> Note: some of the above seemed to only work when I kept the std.math.cos, std.math.sin text in there. When I take it out, I get warnings about recursive aliases.

Yeah, you can't do `alias cos = givemeabettername!cos;`. That would define the new cos in terms of itself.

> But, I can't seem to use a foreach loop. The recursive mixin template seems to be required.

You can only use the implicitly static foreach where the normal, dynamic foreach is allowed, i.e. in function bodies. This is a syntactic restriction. If we had `static foreach` (like we have `static if`), that would presumably work everywhere.

>
> So this is the last thing I did (that didn't work). Adding foo back to the alias works.
>
> mixin template callThemAll(functions...)
> {
>    mixin("alias " ~__traits(identifier, functions[0]) ~
> 		  " = givemeabettername!(std.math."~__traits(identifier, functions[0]) ~ ");");
>     static if(functions.length >1)
>    		mixin callThemAll!(functions[1..$]);
> }
>
> mixin callThemAll!(cos, sin);

Works for me. Please show the complete code and the error message you get.

Here's what works for me:
----
import std.algorithm: map;
import std.math;
import std.array: array;

template givemeabettername(alias fun)
{
    T givemeabettername(T : U[], U)(T x)
    {
        return x.map!fun.array;
    }
}

mixin template callThemAll(functions...)
{
    mixin("alias " ~__traits(identifier, functions[0]) ~
        " = givemeabettername!(std.math."~__traits(identifier, functions[0]) ~ ");");
    static if(functions.length >1)
        mixin callThemAll!(functions[1..$]);
}

mixin callThemAll!(cos, sin);

void main()
{
    real[] a = [1, 2, 3];
    auto c = cos(a);
    auto s = sin(a);
}
----
July 14, 2015
On Tuesday, 14 July 2015 at 12:12:41 UTC, anonymous wrote:
>
> Works for me. Please show the complete code and the error message you get.
>
> Here's what works for me:


Thanks for posting that. I figured out the issue. Before you had recommended that I use
alias cos = std.math.cos;
I had kept that text in. When I removed it, everything worked just fine. I'm still not sure I grasp the subtleties of alias when used with templates.
July 14, 2015
On Tuesday, 14 July 2015 at 14:02:46 UTC, jmh530 wrote:
> Thanks for posting that. I figured out the issue. Before you had recommended that I use
> alias cos = std.math.cos;
> I had kept that text in. When I removed it, everything worked just fine. I'm still not sure I grasp the subtleties of alias when used with templates.

Oh that's another goodie. So you had a situation like this:
----
import std.math;

alias cos = std.math.cos;

mixin template t()
{
    void cos(real[] arr) {/* ... */}
}

mixin t!();

void main()
{
    cos([1, 2, 3]);
}
----

This fails with "Error: None of the overloads of 'cos' are callable using argument types (int[])".

The problem is that template mixins cannot add to existing overload sets. The spec says: "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" [1]. That means, the `cos` from `alias cos = std.math.cos;` completely overrides the one from `mixin t!();`. I guess this is a measure against function hijacking again.

I'm not sure if it's supposed to work like it does when the alias is removed, two implicitly imported/generated symbols forming an overload set. But I can't immediately see a problem with it either.

[1] http://dlang.org/template-mixin.html - see "Mixin Scope"
July 14, 2015
On Tuesday, 14 July 2015 at 17:24:41 UTC, anonymous wrote:
>
> This fails with "Error: None of the overloads of 'cos' are callable using argument types (int[])".
>
> The problem is that template mixins cannot add to existing overload sets. The spec says: "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" [1]. That means, the `cos` from `alias cos = std.math.cos;` completely overrides the one from `mixin t!();`. I guess this is a measure against function hijacking again.
>
> I'm not sure if it's supposed to work like it does when the alias is removed, two implicitly imported/generated symbols forming an overload set. But I can't immediately see a problem with it either.
>
> [1] http://dlang.org/template-mixin.html - see "Mixin Scope"

That's a great explanation. It doesn't seem like a bug or anything. It's just alias and template mixins are two areas of D that I'm less familiar with. Combining them together pushes my understanding a bit.

July 15, 2015
On Tuesday, 14 July 2015 at 17:24:41 UTC, anonymous wrote:
> This fails with "Error: None of the overloads of 'cos' are callable using argument types (int[])".
>
> The problem is that template mixins cannot add to existing overload sets. The spec says: "If the name of a declaration in a mixin is the same as a declaration in the surrounding scope, the surrounding declaration overrides the mixin one" [1]. That means, the `cos` from `alias cos = std.math.cos;` completely overrides the one from `mixin t!();`. I guess this is a measure against function hijacking again.
>
> I'm not sure if it's supposed to work like it does when the alias is removed, two implicitly imported/generated symbols forming an overload set. But I can't immediately see a problem with it either.
>
> [1] http://dlang.org/template-mixin.html - see "Mixin Scope"



Now - is there a way to rewrite my code without mixins?
July 15, 2015
On Wednesday, 15 July 2015 at 11:45:00 UTC, Laeeth Isharc wrote:
> Now - is there a way to rewrite my code without mixins?

Not sure that is possible. It would be interesting if someone could figure it out though.

I'm more focused on making the "givemeabettername" a bit more general. Someone above had sort of asked why bother for the simple case. True enough, but if I can write something generic enough to work on a wide variety of function types, then I would consider it a win. E.g., below.

template givemeabettername(alias fun)
{
	static if (arity!fun == 1)
	{
		T givemeabettername(T)(T x)
			if (isDynamicArray!(T))
		{
			return x.map!fun.array;
		}
		
		T givemeabettername(T)(T x)
			if (isStaticArray!(T))
		{
			T result = x.dup;
			foreach(ref elem; result)
			{
				elem = fun(elem);
			}
			return result;
		}
	}
}
1 2 3
Next ›   Last »