Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-30 Thread Tom
I would like to thank you for that such a great explanation of the 
Template-based
programming in that unary example. I think it's great you have uploaded that to
the wiki4d, and it's definite will help a lot of people that come from other
common languages background (like C, C# and Python) that don't support full
templating, to understand that design pattern.
And with that close tracking to the functional.d code, I thing but not sure that
we've found some bugs. I will do some testing later today, and if I will see 
what
I think to be wrong, I'll update.

and again,
 Thanks


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-30 Thread Philippe Sigaud
On Sun, Jan 30, 2011 at 12:03, Tom t...@gmail.com wrote:
 I would like to thank you for that such a great explanation of the 
 Template-based
 programming in that unary example. I think it's great you have uploaded that 
 to
 the wiki4d, and it's definite will help a lot of people that come from other
 common languages background (like C, C# and Python) that don't support full
 templating, to understand that design pattern.
 And with that close tracking to the functional.d code, I thing but not sure 
 that
 we've found some bugs. I will do some testing later today, and if I will see 
 what
 I think to be wrong, I'll update.

If anyone is interested, I coded a n-args version of
unaryFun/binaryFun called naryFun. If you use 'a', 'b', ... as args
names, it can automatically determine the templated function arity.

So naryFun!a + b * c - sin(d-a) is a 4-args template function.

It's there:

http://svn.dsource.org/projects/dranges/trunk/dranges/docs/functional.html
(look for naryFun at the bottom)

code is here:
http://dsource.org/projects/dranges/browser/trunk/dranges/functional.d

It could be simpler now: when I did it 18 months ago, CTFE wasn't so
powerful. The looping templates can now easily be done with a simple
foreach. This has been on my todo list for quite some time...


Philippe


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-30 Thread Andrej Mitrovic
On 1/30/11, Philippe Sigaud philippe.sig...@gmail.com wrote:
 If anyone is interested, I coded a n-args version of
 unaryFun/binaryFun called naryFun. If you use 'a', 'b', ... as args
 names, it can automatically determine the templated function arity.

Is this going in the next release? There's an nary template in
std.functional right now but it's commented out. It does look like an
older attempt that probably didn't work.


How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Tom
Hi,
I am learning D for some time. I come from background of C, C# and Python.
When I saw the ways to use std.algorithem's functions, I have noticed that the
input lambda's can be writen as strings. Somewhat like the pythonic exec. I
went to the source of this feature in functional.d
(https://github.com/D-Programming-Language/phobos/blob/master/std/functional.d;).
The functions unaryFun and binaryFun. Is there a way I can read them and
understand them easily? or maybe I missed something?


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Tomek Sowiński
Tom napisał:

 I am learning D for some time. I come from background of C, C# and Python.
 When I saw the ways to use std.algorithem's functions, I have noticed that the
 input lambda's can be writen as strings. Somewhat like the pythonic exec. I
 went to the source of this feature in functional.d
 (https://github.com/D-Programming-Language/phobos/blob/master/std/functional.d;).
 The functions unaryFun and binaryFun. Is there a way I can read them and
 understand them easily? or maybe I missed something?

The standard library implementation must cater for a lot of corner-cases. But 
the essence is this:

template binaryFun(string expr) {
auto binaryFun(T, U)(T a, U b) {
return mixin(expr);
}
}

unittest {
assert (binaryFun!a+b(1,2) == 3);
assert (binaryFun!a-b(1,2) == -1);
}

The magic happens at the mixin line. It takes any expression or statement in 
string form and compiles it in context of the function. Unlike pythonic exec, 
the string must be known at compile-time.

-- 
Tomek



Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
P.S. Tom, I'm writing an explanation on how unaryFunImpl works right
now, but it's long. Give me a few more minutes and it'll be done. :)


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
I hope this gets pasted right, otherwise I'll have to open a freakin' blog. :)

Up until a few months ago, I had no experience with templates whatsoever.

At first, I started using function templates, because they were the
easiest to grasp. Or so I thought. Basically I just used function
templates as if they are a special kind of function that takes any
types of arguments. Sort of like having a regular Python function in
your D code. I didn't quite grasp the point of templates back then.

What really opened my eyes was the realization that in D there's a
distinct notion between manipulating types at compile-time and
manipulating types at run-time.

Once I've realized that, I knew why template arguments have to be
known at compile time, because templates are a compile-time feature.
And templates aren't really a type at runtime, they're only visible
at compile-time. They're just placeholders with their own scope, and
they hold declarations in that scope. And to access those declarations
(or fields would be a proper word), you generally use the dot
operator. There's also the eponymous trick where you can use the
template instantiation itself to refer to one of its fields (this is
useful when you're only interesting in getting back one result, as it
saves you the burden of having to explicitly specify that field when
instantiating the template).

Then, I've realized that templates can be used almost anywhere. A
template can have fields which are templated structs and classes,
which in turn can have templated functions, which in turn have
templated declarations in them, and the functions can have templated
return values.

So, let's talk about unaryFun now. unaryFun is a template which has
the ability to construct a function, by simply passing a string as an
argument. It's named *unary* because it constructs a function that
takes only a single argument. You pass the string in the syntax form
where it's as if you're only writing the return expression. unaryFun
has the ability to convert some special predefined characters to
parameters of a function. For example, it recognizes that 'a' should
be replaced with the argument to the newly constructed function.

Here's a simple instantiation of unaryFun:
unaryFun!((a  1) == 0)

unaryFun takes the string argument and might create this function:


Let me walk you through unaryFun line by line (I'm using DMD 2.051).
First, our example code:

alias unaryFun!((a  1) == 0) isEven;
assert(isEven(2)  !isEven(1));

Now open std.functional.

Line 40: unaryFun instantiates unaryFunImpl. You'll notice it passes
the same arguments to unaryFunImpl as the ones it got from the calling
code. We passed a string, and the two other arguments are set to
'false' and 'a' by default, since we didn't specify them. Once the
unaryFunImpl template is instantiated, we can select any of its fields
with the dot operator. In this case, we're interested in the result
field.
So.. what does the alias do? It's a nice thing called the eponymous
trick, where you can use the name of the template itself as the result
of the instantiation. In other words, if you alias the name of a
template to some declaration, when you instantiate that template you
won't have to use the dot prefix to get a single result.
A quick example without the eponymous trick:
template foo(int value)
{
int result = value;
}
void main()
{
writeln( foo!(4).result );
}

And here's one with the eponymous trick:
template foo(int value)
{
int result = value;
alias result foo;  // we've aliased the foo template name to the
result field
}
void main()
{
writeln( foo!(4) );  // no need to explicitly use .result here
}

This is very handy when you're only interested in getting one field of
a template.
Now let's see how unaryFunImpl works.

Line 45: This is a *compile-time* check. It tries to determine if the
fun argument is a string.
There's an else clause way down on line 98, which, in case the fun
argument isn't a string, simply aliases the fun argument to the name
'result'.
So, why do we need to check if the 'fun' argument is a string? Well,
because 'fun' in the template
signature of unaryFunImpl is defined as an 'alias' type. An alias is a
parameter type that can be a string, a value, a type, a function, or
any other valid D symbol name. The reason alias is used in
unaryFunImpl is because we can call unaryFunImpl in different ways. In
our own code we've used:

void main()
{
alias unaryFun!((a  1) == 0) isEven;
}

In this case the 'static if' check on line 45 will pass since the
argument is a string. But we could have called unaryFun like so:

void foo(int x)
{
}
void main()
{
alias unaryFun!(foo) isEven;
}

In this case we're passing a function parameter at compile time. The
'static if' check will evaluate to false since the fun parameter is an
actual function, not a string. This brings us to the else clause on
line 98. Since the whole purpose of unaryFun is to construct a
function out of a string, it doesn't make 

Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Woops, sorry about the missing function definition after the line:
unaryFun takes the string argument and might create this function:

This should be maybe:
int unaryFun(int a)
{
return (a  1) == 0;
}

But that's oversimplification since that instantiation is a function
template itself, not a specific function.


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Note when I said But, we *did* pass a valid argument, I was refering
to the original code example I gave at the top where we called
unaryFun for the first time.


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Fix: So essentially it allows us to use any string of characters instead of
b.

I've meant a here, not b.


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Trass3r

Save this somewhere or it will be lost here ;)


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Done: http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial/D2Templates

I've replaced my obvious English mistakes with slightly less obvious
ones. Kinda wish prowiki had a nicer code display though (syntax
highlighting would be nice).


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Wait, why won't this compile?:

template foo(int value)
{
int result;
alias result foo;
}

void main()
{
writeln( foo!(4) );
}


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Oh yeah, it's that damn bug where you can't have multiple
declarations, otherwise aliases don't work.

I still don't know if that bug will ever be fixed or if I should add
that to the tutorial.


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Well I've updated the tutorial anyway. I just left a note and used an
templateImpl companion template.


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Andrej Mitrovic
Well now I'm feeling really stupid because apparently this is how it
*should* work, at least according to the docs.

I'd love to see 'alias symbol this' work even with multiple
declarations. It'd be nicee..


Re: How can you read and understand the source of *naryFun in functional.d?

2011-01-29 Thread Jonathan M Davis
On Saturday 29 January 2011 16:01:06 Andrej Mitrovic wrote:
 Well now I'm feeling really stupid because apparently this is how it
 *should* work, at least according to the docs.
 
 I'd love to see 'alias symbol this' work even with multiple
 declarations. It'd be nicee..

It's how it should work according to TDPL. It'll get fixed It's just a question 
of when.

- Jonathan M Davis