July 08, 2015
On 7/8/15 11:49 AM, jmh530 wrote:
> On Wednesday, 8 July 2015 at 14:37:23 UTC, jmh530 wrote:
>> Thanks. I was worried I was doing something wrong.
>
> It seems like if you wrap the intrinsic function in another function
> than it works fine (below). Easy enough work-around, I suppose.
>
> If there is no intention to fix the pointer to assembly function issue
> (I have zero clue how to go about it, maybe there is a good reason it
> can't be fixed), this work-around could be implemented in the std.math
> library for those functions. I.e., put the assembly code in separate
> functions and then have the existing intrinsic functions act as wrappers
> to those.
>
> import std.math : cos;
>
> real cos_wrap(real x) pure nothrow @nogc @safe
> {
>      return cos(x);
> }
>
> void main()
> {
>      auto fp = &cos_wrap;
>      real x = 0;
>      real y = fp(x);
> }

You can use a function lambda:

auto fp = (real a) => cos(a);

Note, I had to put (real a) even though I would have expected "a => cos(a)" to work.

-Steve

July 08, 2015
On Wednesday, 8 July 2015 at 18:31:00 UTC, Steven Schveighoffer wrote:
> You can use a function lambda:
>
> auto fp = (real a) => cos(a);
>
> Note, I had to put (real a) even though I would have expected "a => cos(a)" to work.
>
> -Steve

Interesting. You have to put real because there is also a float and double version of cos.
July 09, 2015
On Wednesday, 8 July 2015 at 21:04:27 UTC, jmh530 wrote:
> On Wednesday, 8 July 2015 at 18:31:00 UTC, Steven Schveighoffer wrote:
>> You can use a function lambda:
>>
>> auto fp = (real a) => cos(a);
>>
>> Note, I had to put (real a) even though I would have expected "a => cos(a)" to work.
>>
>> -Steve
>
> Interesting. You have to put real because there is also a float and double version of cos.

Even if there are no overloads, you'd still need to specify the type. That's because `a => cos(a)` is not a function, but a function template, and therefore can't be store in a variable.
July 09, 2015
On 7/9/15 4:44 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:
> On Wednesday, 8 July 2015 at 21:04:27 UTC, jmh530 wrote:
>> On Wednesday, 8 July 2015 at 18:31:00 UTC, Steven Schveighoffer wrote:
>>> You can use a function lambda:
>>>
>>> auto fp = (real a) => cos(a);
>>>
>>> Note, I had to put (real a) even though I would have expected "a =>
>>> cos(a)" to work.
>>>
>>
>> Interesting. You have to put real because there is also a float and
>> double version of cos.
>
> Even if there are no overloads, you'd still need to specify the type.
> That's because `a => cos(a)` is not a function, but a function template,
> and therefore can't be store in a variable.

I didn't know this! I thought it would infer the type if there wasn't any overloads (or in this case, I thought there was a weird issue with the fact that cos is intrinsic).

This is good to know.

-Steve
July 12, 2015
On Wednesday, 8 July 2015 at 18:31:00 UTC, Steven Schveighoffer wrote:
>
> You can use a function lambda:
>
> auto fp = (real a) => cos(a);
>
> Note, I had to put (real a) even though I would have expected "a => cos(a)" to work.
>
> -Steve

I've been playing around with this a little more. I wrote this function to encapsulate a simple operation on arrays.

U array_fun(T, U)(T fp, U x)
	if (isFunctionPointer!(T) && isArray!(U))
{
	return x.map!(a => fp(a)).array;
}

Then I wrote a cos function that calls it on using a function pointer.

T cos(T : U[], U)(T x)
	if (isArray!(T))
{
	auto fp = (U a) => cos(a);
	return array_fun(fp, x);
}

This seems to work just fine, but for some reason this only seems to work when I import std.math : cos. It doesn't work when I just do import std.math. Bug?

Nevertheless, if I want to implement it for another function, then I have to write it all over again. So I wrote a mixin that would encapsulate that idea (I put in the \n, \t for formatting purposes because I like to be able to writeln it out and see that it matches the original).

template mixin_builder(string function_name)
{
	const char[] mixin_builder =
		"T " ~ function_name ~ "(T : U[], U)(T x)\n" ~
			"\tif (isArray!(T))\n" ~
		"{\n" ~
			"\tauto fp = (U a) => " ~ function_name ~ "(a);\n" ~
			"\treturn array_fun(fp, x);\n" ~
		"}";
}

Then I can just call
mixin(mixin_builder!("cos"));
mixin(mixin_builder!("sin"));

While it works, it feels a bit hackish. I'm not sure I can think of a generic way to do this without mixins.
July 12, 2015
On Sunday, 12 July 2015 at 16:34:17 UTC, jmh530 wrote:
> I've been playing around with this a little more. I wrote this function to encapsulate a simple operation on arrays.
>
> U array_fun(T, U)(T fp, U x)
> 	if (isFunctionPointer!(T) && isArray!(U))
> {
> 	return x.map!(a => fp(a)).array;
> }
>
> Then I wrote a cos function that calls it on using a function pointer.
>
> T cos(T : U[], U)(T x)
> 	if (isArray!(T))
> {
> 	auto fp = (U a) => cos(a);
> 	return array_fun(fp, x);
> }
>
> This seems to work just fine, but for some reason this only seems to work when I import std.math : cos. It doesn't work when I just do import std.math. Bug?

Your function is called cos, too. So you need your local cos and std.math.cos to form an overload set. This isn't automatically done with implicitly imported functions to avoid hijacking [1] (accidentally calling the wrong function). Selectively imported functions are added to the overload set, as you (the programmer) are obviously aware of them and want them in the overload set. An alternative would be to use an alias:
----
import std.math;
alias cos = std.math.cos;
----

> Nevertheless, if I want to implement it for another function, then I have to write it all over again. So I wrote a mixin that would encapsulate that idea (I put in the \n, \t for formatting purposes because I like to be able to writeln it out and see that it matches the original).
>
> template mixin_builder(string function_name)
> {
> 	const char[] mixin_builder =
> 		"T " ~ function_name ~ "(T : U[], U)(T x)\n" ~
> 			"\tif (isArray!(T))\n" ~
> 		"{\n" ~
> 			"\tauto fp = (U a) => " ~ function_name ~ "(a);\n" ~
> 			"\treturn array_fun(fp, x);\n" ~
> 		"}";
> }
>
> Then I can just call
> mixin(mixin_builder!("cos"));
> mixin(mixin_builder!("sin"));
>
> While it works, it feels a bit hackish. I'm not sure I can think of a generic way to do this without mixins.

Take the function via an alias parameter:
----
template givemeabettername(alias fun)
{
    T givemeabettername(T : U[], U)(T x)
        if (isArray!(T))
    {
        auto fp = (U a) => fun(a);
        return array_fun(fp, x);
    }
}
alias cos = givemeabettername!(std.math.cos);
alias sin = givemeabettername!(std.math.sin);
----

But turning a statically known function to a function pointer only to pass it to `map` seems pointless to me. So:
----
template givemeabettername(alias fun)
{
    T givemeabettername(T : U[], U)(T x)
        if (isArray!(T)) /* With the specialization above, this is redundant, isn't it?  */
    {
        return x.map!fun.array;
    }
}
----

And personally, I'd probably just type out `x.map!fun.array` every time.

[1] http://dlang.org/hijack.html
July 12, 2015
On Sunday, 12 July 2015 at 17:11:04 UTC, anonymous wrote:
>
> And personally, I'd probably just type out `x.map!fun.array` every time.
>
> [1] http://dlang.org/hijack.html

Thanks for the comments.
July 12, 2015
On Sunday, 12 July 2015 at 20:31:20 UTC, jmh530 wrote:
> On Sunday, 12 July 2015 at 17:11:04 UTC, anonymous wrote:
>>
>> And personally, I'd probably just type out `x.map!fun.array` every time.
>>
>> [1] http://dlang.org/hijack.html
>
> Thanks for the comments.

After thinking it over, I think you're absolutely right about the function pointers. I made a slight change to just this:

private template givemeabettername(alias fun)
{
    T givemeabettername(T : U[], U)(T x)
        if (isArray!(T))
    {
        return x.map!(a => fun(a)).array;
    }
}

Very cool. I guess I'm still left with the issue that I don't know how to loop through a bunch of different functions at compile time, but this is so elegant that it doesn't seem like that big a deal.

I'll admit, I still don't think I really have a handle on alias (i.e., it's not something I immediately think of; I understand what it does). It seems like you can do so many things with it. It's just not something that I used in other languages much.
July 12, 2015
On Sunday, 12 July 2015 at 21:07:34 UTC, jmh530 wrote:
> private template givemeabettername(alias fun)
> {
>     T givemeabettername(T : U[], U)(T x)
>         if (isArray!(T))
>     {
>         return x.map!(a => fun(a)).array;

You don't need the lambda, do you? -> return x.map!fun.array;

>     }
> }
>
> Very cool. I guess I'm still left with the issue that I don't know how to loop through a bunch of different functions at compile time, but this is so elegant that it doesn't seem like that big a deal.

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 .. $])();
    }
}
----
July 13, 2015
On Sunday, 12 July 2015 at 22:26:44 UTC, anonymous wrote:
>
> You don't need the lambda, do you? -> return x.map!fun.array;
>

You're right.

>
> 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);
}