Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-09 Thread Jacob Carlborg

On 2014-01-09 18:57, H. S. Teoh wrote:


I'm afraid that this might become ambiguous, for example:

int* gun(...) {...}

func (x==0)
*gun(y);

Does the second statement mean `func!(() => *gun(y))(x==0)`, or does it
mean `func(x==0) * gun(y)`? While it's not hard to disambiguate this
semantically, it means it's impossible to parse before you analyze it,
which is probably a bad idea.


Right, probably not a good idea.

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-09 Thread H. S. Teoh
On Thu, Jan 09, 2014 at 09:49:17AM +0100, Jacob Carlborg wrote:
> On 2014-01-08 19:04, H. S. Teoh wrote:
[...]
> >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.

True. So this should be one of the motivating use cases for our DIP.


> >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.
[...]

I'm afraid that this might become ambiguous, for example:

int* gun(...) {...}

func (x==0)
*gun(y);

Does the second statement mean `func!(() => *gun(y))(x==0)`, or does it
mean `func(x==0) * gun(y)`? While it's not hard to disambiguate this
semantically, it means it's impossible to parse before you analyze it,
which is probably a bad idea.


T

-- 
Nobody is perfect.  I am Nobody. -- pepoluan, GKC forum


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-09 Thread Jacob Carlborg

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


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-08 Thread H. S. Teoh
On Wed, Jan 08, 2014 at 08:32:15AM +0100, Jacob Carlborg wrote:
> On 2014-01-07 21:44, H. S. Teoh wrote:
[...]
> >I like the alias idea, so here's the revised proposal:
> >
> >1) Argumentless trailing-delegate syntax:
> >
> > // Given this declaration:
> > void foo(alias dg)();
> >
> > // We can write this:
> > foo {
> > // body
> > }
> >
> > // which will get translated into:
> > foo!({ /* body */ });
> >
> >2) With arguments:
> >
> > // Given this declaration:
> > void foo(alias dg, A...)(A args);
> >
> > // Or its non-template equivalent:
> > void foo(alias dg)(A arg1, B arg2, C arg3, ...);
> >
> > // We can write this:
> > foo(a,b,c,...) {
> > // body
> > }
> >
> > // which gets translated into:
> > foo!({ /* body */})(a,b,c,...);
> >
> >3) With indexing arguments:
> >
> > // Given this declaration:
> > void foo(alias dg, I..., A...)(A args)
> > if (is(typeof(dg(I;
> >
> > // Or its non-template equivalent:
> > void foo(alias dg)(A arg1, B arg2, C arg3, ...) {
> > ...
> > dg(i, j, k);
> > ...
> > }
> >
> > // We can write this:
> > foo(i,j,k,... ; a,b,c,...) {
> > // body
> > }
> 
> I would prefer to have the delegate arguments last.

The reason I wrote it this way is so that it parallels the foreach
construction better:

my_foreach (i; range) {
...
}

parallels:

foreach (i; range) {
...
}


[...]
> >EXAMPLE:
> >
> > void for_every_other(alias loopBody, R)(R range)
> > if (is(typeof(loopBody(ElementType!R.init
> > {
> > while (!range.empty) {
> > loopBody(range.front);
> > range.popFront();
> > if (!range.empty)
> > range.popFront();
> > }
> > }
> >
> > // Prints:
> > // ---
> > // 1
> > // 3
> > // 5
> > // ---
> > for_every_other (i; [1,2,3,4,5,6]) {
> > writeln(i);
> > }
> 
> If we instead have the delegate argument last UFCS still works:
> 
> [1,2,3,4,5,6].for_every_other(i) {
> writeln(i);
> }
> 
> Hmm. Actually, your example is more D like. I don't know which I
> example I like best.
[...]

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));

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);`.

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 */
});

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.

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:

void pure_block(alias dg)() pure
if (is(typeof(dg(
{
dg();
}

void nothrow_block(alias dg)() nothrow
if (is(typeof(dg(
{

Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread Jacob Carlborg

On 2014-01-07 21:44, H. S. Teoh wrote:


If you have a good motivating use case in favor of this addition that
can be used in a DIP, I'd vote for it.


I'm usually not good at these arguments. I mean, it would be nice to 
have but I don't have any strong arguments for it. It's just syntax sugar.



I like the alias idea, so here's the revised proposal:

1) Argumentless trailing-delegate syntax:

// Given this declaration:
void foo(alias dg)();

// We can write this:
foo {
// body
}

// which will get translated into:
foo!({ /* body */ });

2) With arguments:

// Given this declaration:
void foo(alias dg, A...)(A args);

// Or its non-template equivalent:
void foo(alias dg)(A arg1, B arg2, C arg3, ...);

// We can write this:
foo(a,b,c,...) {
// body
}

// which gets translated into:
foo!({ /* body */})(a,b,c,...);

3) With indexing arguments:

// Given this declaration:
void foo(alias dg, I..., A...)(A args)
if (is(typeof(dg(I;

// Or its non-template equivalent:
void foo(alias dg)(A arg1, B arg2, C arg3, ...) {
...
dg(i, j, k);
...
}

// We can write this:
foo(i,j,k,... ; a,b,c,...) {
// body
}


I would prefer to have the delegate arguments last.


// which gets translated into:
foo!((i,j,k,...) { /* body */ })(a,b,c,...);


EXAMPLE:

void for_every_other(alias loopBody, R)(R range)
if (is(typeof(loopBody(ElementType!R.init
{
while (!range.empty) {
loopBody(range.front);
range.popFront();
if (!range.empty)
range.popFront();
}
}

// Prints:
// ---
// 1
// 3
// 5
// ---
for_every_other (i; [1,2,3,4,5,6]) {
writeln(i);
}


If we instead have the delegate argument last UFCS still works:

[1,2,3,4,5,6].for_every_other(i) {
writeln(i);
}

Hmm. Actually, your example is more D like. I don't know which I example 
I like best.


I'll see if I can write something down.

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread H. S. Teoh
On Tue, Jan 07, 2014 at 09:18:48PM +0100, Jacob Carlborg wrote:
> On 2014-01-07 16:58, H. S. Teoh wrote:
> 
> >Y'know, I've always wanted "trailing delegate syntax":
> >
> > func(x, y, z; p, q, r) {
> > // body
> > }
> >
> >gets translated into:
> >
> > func(p, q, r, (x, y, z) => /* body */);
> >
> >Since we already have UFCS, which translates a leading fragment into
> >the first argument (x.func(y) --> func(x,y)), it seems perfectly
> >reasonable to do something with the final argument too, like the
> >above.
> >
> >This would allow one to implement, for example, foreach_reverse as a
> >library function instead of a language keyword:
> >
> > void foreach_reverse(I, R)(R range, void delegate(I) dg)
> > {
> > ...
> > dg(idx);
> > ...
> > }
> >
> > // Gets translated to:
> > //  foreach_reverse(range, (uint i) => /* body */);
> > foreach_reverse (uint i; range) {
> > ... // body
> > }
> >
> > // And you can use UFCS too:
> > range.foreach_reverse(uint i) {
> > ... // body
> > }
> 
> Exactly, that's what it is for. Perhaps supporting an alias
> parameter would be good as well, since those are inlined:
> 
> void foo (alias dg) ();
> 
> foo {
> // body
> }
> 
> Translated to:
> 
> foo!({
> // body
> });
> 
> >I'm not holding my breath on this one, though. It's a rather big
> >change and ultimately is just syntactic sugar. Maybe it can go on the
> >list of features for D3... ;-)
> 
> I've brought this up before. If I recall correctly, it didn't was
> that much resistance as one could think. Although this was before we
> had the lambda syntax.
[...]

If you have a good motivating use case in favor of this addition that
can be used in a DIP, I'd vote for it.

I like the alias idea, so here's the revised proposal:

1) Argumentless trailing-delegate syntax:

// Given this declaration:
void foo(alias dg)();

// We can write this:
foo {
// body
}

// which will get translated into:
foo!({ /* body */ });

2) With arguments:

// Given this declaration:
void foo(alias dg, A...)(A args);

// Or its non-template equivalent:
void foo(alias dg)(A arg1, B arg2, C arg3, ...);

// We can write this:
foo(a,b,c,...) {
// body
}

// which gets translated into:
foo!({ /* body */})(a,b,c,...);

3) With indexing arguments:

// Given this declaration:
void foo(alias dg, I..., A...)(A args)
if (is(typeof(dg(I;

// Or its non-template equivalent:
void foo(alias dg)(A arg1, B arg2, C arg3, ...) {
...
dg(i, j, k);
...
}

// We can write this:
foo(i,j,k,... ; a,b,c,...) {
// body
}

// which gets translated into:
foo!((i,j,k,...) { /* body */ })(a,b,c,...);


EXAMPLE:

void for_every_other(alias loopBody, R)(R range)
if (is(typeof(loopBody(ElementType!R.init
{
while (!range.empty) {
loopBody(range.front);
range.popFront();
if (!range.empty)
range.popFront();
}
}

// Prints:
// ---
// 1
// 3
// 5
// ---
for_every_other (i; [1,2,3,4,5,6]) {
writeln(i);
}

EXTENDED EXAMPLE:

void for_every_other(alias loopBody, R)(R range)
if (is(typeof(loopBody(size_t.init, ElementType!R.init
{
size_t i=0;
while (!range.empty) {
loopBody(i, range.front);

range.popFront();
if (!range.empty) {
range.popFront();
i += 2;
}
}
}

// Prints:
// ---
// 0: "a"
// 2: "c"
// 4: "e"
// ---
for_every_other (i, j; ["a", "b", "c", "d", "e", "f"]) {
writefln("%s: %s", i, j);
}


T

-- 
Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANG


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread Jacob Carlborg

On 2014-01-07 16:58, H. S. Teoh wrote:


Y'know, I've always wanted "trailing delegate syntax":

func(x, y, z; p, q, r) {
// body
}

gets translated into:

func(p, q, r, (x, y, z) => /* body */);

Since we already have UFCS, which translates a leading fragment into the
first argument (x.func(y) --> func(x,y)), it seems perfectly reasonable
to do something with the final argument too, like the above.

This would allow one to implement, for example, foreach_reverse as a
library function instead of a language keyword:

void foreach_reverse(I, R)(R range, void delegate(I) dg)
{
...
dg(idx);
...
}

// Gets translated to:
//  foreach_reverse(range, (uint i) => /* body */);
foreach_reverse (uint i; range) {
... // body
}

// And you can use UFCS too:
range.foreach_reverse(uint i) {
... // body
}


Exactly, that's what it is for. Perhaps supporting an alias parameter 
would be good as well, since those are inlined:


void foo (alias dg) ();

foo {
// body
}

Translated to:

foo!({
// body
});


I'm not holding my breath on this one, though. It's a rather big change
and ultimately is just syntactic sugar. Maybe it can go on the list of
features for D3... ;-)


I've brought this up before. If I recall correctly, it didn't was that 
much resistance as one could think. Although this was before we had the 
lambda syntax.


--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread H. S. Teoh
On Tue, Jan 07, 2014 at 03:35:43PM +0100, Jacob Carlborg wrote:
> On 2014-01-07 13:22, Philippe Sigaud wrote:
> 
> >What about:
> >
> >void loop(void delegate() dg);
> >
> >loop({
> >...
> >
> >});
> >
> >Since any block is a void delegate().
> 
> That's what we have now, and that doesn't look like a built-in
> statement ;)
[...]

Y'know, I've always wanted "trailing delegate syntax":

func(x, y, z; p, q, r) {
// body
}

gets translated into:

func(p, q, r, (x, y, z) => /* body */);

Since we already have UFCS, which translates a leading fragment into the
first argument (x.func(y) --> func(x,y)), it seems perfectly reasonable
to do something with the final argument too, like the above.

This would allow one to implement, for example, foreach_reverse as a
library function instead of a language keyword:

void foreach_reverse(I, R)(R range, void delegate(I) dg)
{
...
dg(idx);
...
}

// Gets translated to:
//  foreach_reverse(range, (uint i) => /* body */);
foreach_reverse (uint i; range) {
... // body
}

// And you can use UFCS too:
range.foreach_reverse(uint i) {
... // body
}

I'm not holding my breath on this one, though. It's a rather big change
and ultimately is just syntactic sugar. Maybe it can go on the list of
features for D3... ;-)


T

-- 
Famous last words: I wonder what will happen if I do *this*...


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread Jacob Carlborg

On 2014-01-07 13:22, Philippe Sigaud wrote:


What about:

void loop(void delegate() dg);

loop({
...

});

Since any block is a void delegate().


That's what we have now, and that doesn't look like a built-in statement ;)

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-07 Thread Philippe Sigaud
On Tue, Jan 7, 2014 at 8:50 AM, Jacob Carlborg  wrote:
> I would like to have that in D as well, but with braces instead:
>
> void loop (void delegate () dg);
>
> loop {
> // endless loop
> }

What about:

void loop(void delegate() dg);

loop({
...

});

Since any block is a void delegate().


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-06 Thread Jacob Carlborg

On 2014-01-06 22:07, Philippe Sigaud wrote:


Ruby does have a clean syntax (though I find blocks to be a bit heavy).


I like the block syntax. It allows one to create what looks like new 
statements:


loop do
  # endless loop
end

I would like to have that in D as well, but with braces instead:

void loop (void delegate () dg);

loop {
// endless loop
}

In Ruby 1.9 they introduced a slight more lightweight syntax for lambdas:

callback = -> { p "foo" }
bar(callback)


But I'm not overloading any syntax here. I'm using a closure, not an
expression template.

Table.where!(e => e.first_name != "foo" && e.first_name.length > 4).first;


How is that being transformed in to SQL then?

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-06 Thread Philippe Sigaud
>> I didn't know that, thanks. I read it during the holidays in Martin
>> Fowler's book on DSL, but indeed that book is from 2005, IIRC.
>
>
> That's a bit old :). According to this site[1] Rails 1.0 was released in
> December 2005. Rails 4.0 was released in June 2013.

Ouch, that was 2010, my bad.


>
> I think there are two reasons why they deprecated that syntax:
>
> * They want to avoid method_missing (same as opDispatch in D)
>
> * They want to have the name of a column close to the value of that column.
> Example:
>
> Table.find_first_by_fist_name_and_last_name("foo", "bar")
>
> In the above example the values and the columns they belongs to are quite
> disconnected. The column names are far to the right and the values are far
> to the left. With the AA syntax you get the column name and its value
> closely connected. It's clear to see which value belongs to which column.

Yes indeed. Too clever for its own good.


> I have to admit that it looks a lot better in Ruby than in D.

Ruby does have a clean syntax (though I find blocks to be a bit heavy).

>
>
>> Some other possibilities could be:
>>
>> Table.where!(e => e.first_name == "foo").first; // Similar to
>> std.range.filter
>
>
> This is the one I like best and it's possible to have the same syntax in
> Ruby as well with a plugin, Squeel[2]. This allows to have more advanced
> quires containing "or" and negation.
>
> The problem is it's basically only equality that works with this syntax. You
> cannot overload !=, && or || in D. You could of course use method names like
> "equals", "and" and "or".

But I'm not overloading any syntax here. I'm using a closure, not an
expression template.

Table.where!(e => e.first_name != "foo" && e.first_name.length > 4).first;


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-06 Thread Jacob Carlborg

On 2014-01-05 22:44, Philippe Sigaud wrote:


I didn't know that, thanks. I read it during the holidays in Martin
Fowler's book on DSL, but indeed that book is from 2005, IIRC.


That's a bit old :). According to this site[1] Rails 1.0 was released in 
December 2005. Rails 4.0 was released in June 2013.


I think there are two reasons why they deprecated that syntax:

* They want to avoid method_missing (same as opDispatch in D)

* They want to have the name of a column close to the value of that 
column. Example:


Table.find_first_by_fist_name_and_last_name("foo", "bar")

In the above example the values and the columns they belongs to are 
quite disconnected. The column names are far to the right and the values 
are far to the left. With the AA syntax you get the column name and its 
value closely connected. It's clear to see which value belongs to which 
column.



Yes, using AA is a nice idea, which avoids introducing first_name in
the current scope.


I have to admit that it looks a lot better in Ruby than in D.


Some other possibilities could be:

Table.where!(e => e.first_name == "foo").first; // Similar to std.range.filter


This is the one I like best and it's possible to have the same syntax in 
Ruby as well with a plugin, Squeel[2]. This allows to have more advanced 
quires containing "or" and negation.


The problem is it's basically only equality that works with this syntax. 
You cannot overload !=, && or || in D. You could of course use method 
names like "equals", "and" and "or".


In Squeel they "solved" it by overloading | and & to mean "or" and 
"and". That causes other problems with operator precedence, one needs to 
wrap everything in parentheses.


In D we would need more finer grained control of operator overloading, 
like overload == separately from !=. Or, I come back to this all the 
time, AST macros.



Table.where.first_name!(e => e == "foo").first;


If I look at the API in Rails I think this could cause some conflicts 
with all the methods that are available on the object returned by 
Table.where.



Table.where((string first_name) => first_name == "foo").first; // By
extracting the parameter name

The syntax is heavier than your example, but some nice logic can put
into a closure.


Same problem as above.


Some also advocate:

Table.where.first_name.equals("foo").first;

But I find it a bit too clunky.


Same problem as above.

[1] http://railsapps.github.io/rails-release-history.html
[2] https://github.com/activerecord-hackery/squeel

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread Philippe Sigaud
On Sun, Jan 5, 2014 at 5:18 PM, Jacob Carlborg  wrote:

> Just for the record. In Rails, that's the old, now discourage, Rails 2
> syntax.

I didn't know that, thanks. I read it during the holidays in Martin
Fowler's book on DSL, but indeed that book is from 2005, IIRC.

> In Rails 3 and later the following syntax is preferred:
>
> Table.where(first_name: "foo").first
>
> Which in D would look like:
>
> Table.where(["first_name": "foo"]).first;

Yes, using AA is a nice idea, which avoids introducing first_name in
the current scope.

Some other possibilities could be:

Table.where!(e => e.first_name == "foo").first; // Similar to std.range.filter

Table.where.first_name!(e => e == "foo").first;

Table.where((string first_name) => first_name == "foo").first; // By
extracting the parameter name

The syntax is heavier than your example, but some nice logic can put
into a closure.

Some also advocate:

Table.where.first_name.equals("foo").first;

But I find it a bit too clunky.


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread TheFlyingFiddle

On Sunday, 5 January 2014 at 17:17:27 UTC, Artur Skawina wrote:
While 'void' is not a first class type in D, there /is/ a 
special
case for returning 'void' from functions - so all of the above 
can

simply be written as:

   struct gl {
  static auto ref opDispatch(string name, Args...)(Args 
args) {

 scope (exit) checkGLError();
 return mixin("gl"~name~"(args)");
  }
   }

artur


That's awesome! Thanks for enlightening me!


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread Artur Skawina
On 01/05/14 15:36, TheFlyingFiddle wrote:
> Another simple example that have helped me tremendously when debugging OpenGL 
> calls. A simple dispatcher that checks glGetError after every call.
> 
> struct GL
> {
> auto opDispatch(string name, Args...)(Args args)
> {
> enum glName = "gl" ~ name;
> mixin(format("
> static if(is(ReturnType!%1$s == void))
> {
> %1$s(args);
> checkGLError();
> }
> else
> {
> auto r = %1$s(args);
> checkGLError();
> return r;
>  }", glName));
> 
> }
> }
> GL gl;
> 
> I simply use gl.funcName instead of glFuncName. opDispatch rules!.

While 'void' is not a first class type in D, there /is/ a special
case for returning 'void' from functions - so all of the above can
simply be written as:

   struct gl {
  static auto ref opDispatch(string name, Args...)(Args args) {
 scope (exit) checkGLError();
 return mixin("gl"~name~"(args)");
  }
   }

artur


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread Jacob Carlborg

On 2014-01-05 14:09, Philippe Sigaud wrote:


As Adam showed, it's very nice to make some clean API (or DSL).

Another example I like is generating queries:

auto result = table.findByFirstName;

If Table has a "FirstName" field, then opDispatch will catch any
findByX and generate the related query. A bit like Activerecord
for Ruby.


Just for the record. In Rails, that's the old, now discourage, Rails 2 
syntax. In Rails 3 and later the following syntax is preferred:


Table.where(first_name: "foo").first

Which in D would look like:

Table.where(["first_name": "foo"]).first;

--
/Jacob Carlborg


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread TheFlyingFiddle
Another simple example that have helped me tremendously when 
debugging OpenGL calls. A simple dispatcher that checks 
glGetError after every call.


struct GL
{
auto opDispatch(string name, Args...)(Args args)
{
enum glName = "gl" ~ name;
mixin(format("
static if(is(ReturnType!%1$s == void))
{
%1$s(args);
checkGLError();
}
else
{
auto r = %1$s(args);
checkGLError();
return r;
 }", glName));

}
}
GL gl;

I simply use gl.funcName instead of glFuncName. opDispatch rules!.


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-05 Thread Philippe Sigaud
On Sat, Jan 4, 2014 at 10:08 PM, H. S. Teoh  wrote:

> Of course, these are arguably clever hacks than true, properly-motivated
> examples, but still, they exemplify what Andrei meant when he said that
> the power of opDispatch is largely still unexplored territory.

As Adam showed, it's very nice to make some clean API (or DSL).

Another example I like is generating queries:

auto result = table.findByFirstName;

If Table has a "FirstName" field, then opDispatch will catch any
findByX and generate the related query. A bit like Activerecord
for Ruby.


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread H. S. Teoh
On Sat, Jan 04, 2014 at 07:52:11PM +, Adam D. Ruppe wrote:
> On Saturday, 4 January 2014 at 19:26:50 UTC, Gary Willoughby wrote:
> >Got it!
> 
> opDispatch rox, and there's all kinds of crazy stuff you can do with
> it. In my dom.d, I used it for three things:
[...]

Somebody has also used opDispatch to do vector swizzling, such that:

auto v = vec.wxzy;

is equivalent to:

auto v = [vec[0], vec[1], vec[2], vec[1]];

It's also possible to implement Roman numerals with opDispatch that
doesn't require a string literal:

Roman.II == 2
Roman.VII == 7
... etc.

by parsing the identifier passed to opDispatch at compile-time.

Of course, these are arguably clever hacks than true, properly-motivated
examples, but still, they exemplify what Andrei meant when he said that
the power of opDispatch is largely still unexplored territory.


T

-- 
It's amazing how careful choice of punctuation can leave you hanging:


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread Adam D. Ruppe
On Saturday, 4 January 2014 at 19:26:50 UTC, Gary Willoughby 
wrote:

Got it!


opDispatch rox, and there's all kinds of crazy stuff you can do 
with it. In my dom.d, I used it for three things:


https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/dom.d

1) easy access to attributes (node.href = "dlang.org"; and auto 
href = node.href;) using the technique you just showed.


2) the style stuff, which does a little rewriting:

node.style.marginLeft = "10px"; -> adds "margin-left: 10px;" to 
the style attribute


3) Forwarding collections:

document[".cool"].addClass("cool2");

uses opDispatch to forward any method to the collection without 
me writing much boilerplate code.



This is also nice for calling external dynamic apis, you can use 
opDispatch to forward over a network call or something like that.




I also used it in my jsvar.d file to make a var type in D, very 
similar to in Javascript:


https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/jsvar.d

var a = var.emptyObject;
a.cool = { writeln("hello world!"); }
a.cool()(); // double parens needed due to broken @property

a.bar = 10;
writeln(a.bar); // works

and so on. D rox so much.


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread Gary Willoughby
On Saturday, 4 January 2014 at 19:19:43 UTC, Gary Willoughby 
wrote:
On Saturday, 4 January 2014 at 19:17:31 UTC, Gary Willoughby 
wrote:

OMG i've just found opDispatch!

http://dlang.org/operatoroverloading.html#Dispatch

Fantastic!


How to handle returning a value from a non-existent property?


Got it!

public void opDispatch(string s)(string value)
{
// handle.
}

public string opDispatch(string s)()
{
return "value";
}


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread Gary Willoughby
On Saturday, 4 January 2014 at 19:17:31 UTC, Gary Willoughby 
wrote:

OMG i've just found opDispatch!

http://dlang.org/operatoroverloading.html#Dispatch

Fantastic!


How to handle returning a value from a non-existent property?


Re: Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread Gary Willoughby
On Saturday, 4 January 2014 at 19:08:45 UTC, Gary Willoughby 
wrote:
In D is it possible to handle accessing class properties that 
don't exist, similar to PHP's magic methods?


http://www.php.net/manual/en/language.oop5.overloading.php#object.set

For example, the below class doesn't have the 'x' property:

class T
{
this()
{
this.x = "hello world!";
}
}

Can i handle this in a programmatic way to intercept the 
property and deal with it?


Something like this:

class T
{
this()
{
this.x = "hello world!";
}

opMagic(A, B)(A property, B value)
{
// property = "x", value = "hello world!"
}
}


OMG i've just found opDispatch!

http://dlang.org/operatoroverloading.html#Dispatch

Fantastic!


Is it possible to handle 'magic' property assignments a'la PHP?

2014-01-04 Thread Gary Willoughby
In D is it possible to handle accessing class properties that 
don't exist, similar to PHP's magic methods?


http://www.php.net/manual/en/language.oop5.overloading.php#object.set

For example, the below class doesn't have the 'x' property:

class T
{
this()
{
this.x = "hello world!";
}
}

Can i handle this in a programmatic way to intercept the property 
and deal with it?


Something like this:

class T
{
this()
{
this.x = "hello world!";
}

opMagic(A, B)(A property, B value)
{
// property = "x", value = "hello world!"
}
}