Is it possible to handle 'magic' property assignments a'la PHP?
Jacob Carlborg
doob at me.com
Thu Jan 9 00:49:17 PST 2014
On 2014-01-08 19:04, H. S. Teoh wrote:
> The reason I wrote it this way is so that it parallels the foreach
> construction better:
>
> my_foreach (i; range) {
> ...
> }
>
> parallels:
>
> foreach (i; range) {
> ...
> }
I guessed that.
> Keep in mind that the identifier list before the ';' is actually the
> delegate's parameter list, it's not passing anything in. They are
> placeholders for what the function will pass to the delegate. So:
>
> my_foreach (i,j ; range) {
> writeln(i + j);
> }
>
> actually means:
>
> my_foreach(range, (i,j) => writeln(i + j));
Yeah, I know.
> and my_foreach could be implemented something like this:
>
> void my_foreach(alias dg, R)(R range)
> if (is(typeof(dg(size_t.init, ElementType!R.init))))
> {
> size_t idx = 0;
> while (!range.empty) {
> // N.B.: calls dg with i = idx, j = range.front
> dg(idx, range.front);
>
> range.popFront();
> idx++;
> }
> }
>
>
> If we go by this, then UFCS should still work:
>
> range.my_foreach(i,j) { /* body */ }
>
> should be translated to:
>
> my_foreach(i, j ; range) { /* body */ }
>
> which in turn translates to:
>
> my_foreach!((i, j) { /* body */ })(range);
>
> In the first case, there is no ambiguity with `range.my_foreach(i,j);`,
> which should translate to `my_foreach(range,i,j);`, because the presence
> of the trailing code block without an intervening ';' makes it clear
> that the above is intended, rather than `my_foreach(range,i,j);`.
Didn't think of that.
> In fact, we can already almost get the desired syntax in the current
> language:
>
> /* Current D already supports this: */
> range.my_foreach!((i,j) {
> /* body */
> });
Almost ;)
> which isn't that much different from the proposed syntactic sugar:
>
> range.my_foreach(i,j) {
> /* body */
> }
>
> We're just saving on the '!', ';', and an extra pair of parentheses.
It quickly get clumsy when you need to pass regular arguments to the
function:
void foo (alias dg) (int a, int b);
foo!((i, j) {
// body
})(1, 2);
Not pretty.
> I guess the only real advantage is that we get to imitate built-in
> foreach syntax. E.g., if we use the form with arguments but no indexing
> arguments, we can pretend to be an if-statement:
>
> // (Whatever "dynamic if" means...)
> void dynamic_if(alias dg)(bool cond)
> if (is(typeof(dg())))
> {
> // Haha, we're just wrapping the built-in 'if' cuz we
> // can.
> if (cond) dg();
> }
>
> int x;
> dynamic_if (x==0) {
> writeln("Boo yah!");
> }
>
> Or if we use the argumentless form to implement custom block constructs:
BTW, what do you think about not needing braces if the delegate body
only contains a single statement, like with regular statements:
dynamic_if (x==0)
writeln("foo");
With the alias syntax, I'm wondering if the compiler will have any
problem with that you can pass almost anything to an alias parameter and
not just a delegate.
--
/Jacob Carlborg
More information about the Digitalmars-d-learn
mailing list