How To: Passing curried functions around
Ali Çehreli via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Sep 11 11:39:14 PDT 2015
On 09/11/2015 02:41 AM, Bahman Movaqar wrote:
> On Friday, 11 September 2015 at 06:14:18 UTC, Ali Çehreli wrote:
>> partial takes the function arguments as 'value template parameters'.
>> Unfortunately, a function pointer like &isEven cannot be 'value
>> template parameters'; only fundamental types and strings can... So,
>> 'partial' is not an option for this problem.
>
> Ah...now I understand the mysterious compiler errors.
I was wrong there: 'partial' does take its arguments as alias template
parameters but it still doesn't work probably because of a compiler or
language issue:
import std.functional;
alias Validator = bool function(int);
bool condition(int)
{
return true;
}
void foo(Validator validator)
{
validator(42);
}
void main()
{
alias f = partial!(foo, condition); // <-- ERROR
}
/usr/include/dmd/phobos/std/functional.d(662): Error: function
deneme.condition (int _param_0) is not callable using argument types ()
/usr/include/dmd/phobos/std/functional.d(662): Error: cannot return
non-void from void function
I wouldn't expect an actual call for that line of code but the compiler
thinks that there is a call to condition() without a parameter. (This
may be related to a syntax issue caused by no-parameter functions being
called without parentheses.)
>> Idiomatic D uses templates and passes behavior in the form of 'alias
>> template parameters.' Alias template parameters are the convenient way
>> of allowing anything that is callable, not just functions. For
>> example, foo() would be much more useful if it allowed a delegate or a
>> class object that has an overloaded opCall() operator.
>
> True. I guess I was just pushing D functions too far.
Not necessarily. You can do the same thing with function pointers as
well but I don't think 'partial' has much to offer over a lambda. I am
guessing that partial predates lambdas. (?)
>> http://ddili.org/ders/d.en/parallelism.html
>>
>> (Search for "The task function above has been specified as a template
>> parameter" on that page.)
>
> Actually, I *am* using your book (which is, by the way, very well
> written) plus the language specs to learn D. However, that section yet
> too advance for me to touch :-)
>
>> import std.stdio;
>>
>> bool isEven(int n) {
>> return !(n % 2);
>> }
>>
>> int readValidInt(alias validator)(string prompt) {
readValidInt() is a function template that takes two information:
1) The validator as its alias template parameter. alias template
parameter allows it to work with anything that can be called.
2) The prompt as its function parameter.
>> while (true) {
>> int i;
>> write(prompt);
>> readf(" %s", &i);
>> if (validator(i)) {
>> return i;
>> } else {
>> writeln("Sorry, that's not acceptable");
>> }
>> }
>> }
The should be obvious.
>> void foo(alias reader)() {
>> reader();
>> }
Another function template that takes a callable entity and calls it.
>> void main() {
>> auto reader = () => readValidInt!isEven("Enter an integer: ");
The syntax above creates a lambda with this definition: Call
readValidInt!isEven with the string argument "Enter an integer: ".
>> foo!reader();
foo takes that lambda. When foo eventually calls the lambda,
readValidInt!isEven("Enter an integer: ") will be called.
>> }
>>
>> You can add template constraints to make the code easier to use.
>
> Clean one! Even though I don't know what's going behind the scenes, I
> can easily read and understand it.
>
> Thanks for the help.
Ali
More information about the Digitalmars-d-learn
mailing list