On Friday, 11 September 2015 at 06:14:18 UTC, Ali Çehreli wrote:
On 09/06/2015 12:05 PM, Bahman Movaqar wrote:
>      alias bool function(int n) validator_t;

There is the relatively newer alias syntax which is more intuitive:

alias Validator = bool function(int n);

Great.  This is easily read by my eyes.

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.

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.

> and even
> if this is the correct way of currying `readInt`, what should
be the
> signature of `foo`?

I think 'int delegate()' would do because all foo needs is a function that returns an int.

That's correct. I realised this subtle point later on, but had already switched to a `struct`y approach.


The idiomatic way is to leave it as a template parameter. However, this has the problem of making each instantiation of the foo template a different type, making them incompatible to be elements of the same array:

[ &(foo!myReader), &(foo!yourReader) ]  // <-- compilation error

One solution is to do what std.parallelism.task does: to provide both a foo template and another foo function that takes an 'int delegate()':

  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) {
    while (true) {
        int i;
        write(prompt);
        readf(" %s", &i);
        if (validator(i)) {
            return i;
        } else {
            writeln("Sorry, that's not acceptable");
        }
    }
}

void foo(alias reader)() {
    reader();
}

void main() {
auto reader = () => readValidInt!isEven("Enter an integer: ");

    foo!reader();
}

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.


Reply via email to