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

Reply via email to