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.