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 d...@me.com 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-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: libphobos.so and loading libraries at runtime

2014-01-07 Thread Sean Kelly

On Sunday, 5 January 2014 at 20:47:44 UTC, FreeSlave wrote:

import core.runtime;

int main()
{
Runtime.loadLibrary(does not care);
Runtime.unloadLibrary(null);
return 0;
}

When I try to compile this code with 'dmd main.d', I get errors

main.o: In function 
`_D4core7runtime7Runtime17__T11loadLibraryZ11loadLibraryFxAaZPv':
main.d:(.text._D4core7runtime7Runtime17__T11loadLibraryZ11loadLibraryFxAaZPv+0x4d): 
undefined reference to `rt_loadLibrary'
main.o: In function 
`_D4core7runtime7Runtime19__T13unloadLibraryZ13unloadLibraryFPvZb':
main.d:(.text._D4core7runtime7Runtime19__T13unloadLibraryZ13unloadLibraryFPvZb+0x8): 
undefined reference to `rt_unloadLibrary'


But it's built without errors when I separate compile and link 
parts:

dmd -c main.d
gcc main.o -lphobos2 -o main

I checked libraries with nm utility and actually found no such 
symbols in static version of libphobos. But shared one has 
these symbols.


Well, I'm aware of that runtime loading requires shared version 
of phobos2 to avoid duplicating of D runtime. But why does dmd 
use static linking by default? Is shared version of phobos 
still experimental? Anyway we need some remarks in 
documentation about the lack of these functions in static 
version of phobos.


This seems like a weird change if intentional, since the function 
is publicly declared. I'd file a bug report.


Re: libphobos.so and loading libraries at runtime

2014-01-07 Thread Dicebot

On Sunday, 5 January 2014 at 20:47:44 UTC, FreeSlave wrote:
But why does dmd use static linking by default? Is shared 
version of phobos still experimental?


It is. It works pretty good in practice but Martin wanted to 
improve provided utilities for library/symbol loading before 
announcing it as released AFAIR.


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*...


dub and ddox

2014-01-07 Thread Kelet

Hello,

I'm working on a library, and I'm trying to write the 
documentation with Sönke's ddox software[1]. As I understand, it 
works with the Ddoc documentation format[2].


The first problem I came across is that documented unit tests 
weren't being converted into examples like in [2]. I came to 
realize that you have to specifically enable it in package.json, 
like so:

-ddoxFilterArgs: [ --unittest-examples ]

Now my problem is styling it. While it looks decent, it is just 
plain white. I noticed there were some questions about styling it 
before, but I mainly want it so that if I type

`dub build --build=ddox`
it will generate my styled documentation. Or at least some 
process similar to this.


I think bootDoc[3] looks pretty good out of the box, but I don't 
think it works with ddox.


I'd like to hear any other misc. comments about using ddox 
(particularly with dub). I was hoping there would be a few 
alternative styles already made under a nice license that I could 
tweak.


[1]: https://github.com/rejectedsoftware/ddox
[2]: http://dlang.org/ddoc.html
[3]: https://github.com/JakobOvrum/bootDoc


Re: dub and ddox

2014-01-07 Thread Kelet

Also, I cannot find any documentation on ddox arguments
(ddoxFilterArgs). Is this currently not available? I had to look
through the source code and vibe.d to figure them out.

Regards,
Kelet


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: Simplest way to create an array from an associative array which its contains keys and values?

2014-01-07 Thread Craig Dillabaugh

On Friday, 3 January 2014 at 17:38:16 UTC, Gary Willoughby wrote:
Simplest way to create an array from an associative array which 
its contains keys and values?


For example if i have an associative array like this:

[one:1, two:2]

What's the easiest way to create a dynamic array that looks 
like this:


[one, 1, two, 2]

I know it can be done via a loop, but is there a more idiomatic 
way to achieve this?


As someone with little experience with functional programming, I 
am just curious - having browsed through the thread - if the 
various solutions proposed here would really be considered more 
'idiomatic' D. Or if they were posted because the OP asked about 
avoiding the foreach() loop.


In other words while:

auto range = aa.byKey.map!(a = chain(a.only, aa[a].only));
string[] array = range.join;

Saves a few lines of code, and looks cooler, it seems that the 
trivial foreach loop version is very easy:


string[] array;

foreach (key, value; aa) {
array ~= key;
array ~= value;
}




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: Simplest way to create an array from an associative array which its contains keys and values?

2014-01-07 Thread H. S. Teoh
On Tue, Jan 07, 2014 at 08:38:10PM +, Craig Dillabaugh wrote:
[...]
 As someone with little experience with functional programming, I am
 just curious - having browsed through the thread - if the various
 solutions proposed here would really be considered more 'idiomatic'
 D. Or if they were posted because the OP asked about avoiding the
 foreach() loop.
 
 In other words while:
 
 auto range = aa.byKey.map!(a = chain(a.only, aa[a].only));
 string[] array = range.join;
 
 Saves a few lines of code, and looks cooler, it seems that the
 trivial foreach loop version is very easy:
 
 string[] array;
 
 foreach (key, value; aa) {
   array ~= key;
   array ~= value;
 }
[...]

Even better, encapsulate this in a function:

CommonType!(K,V)[] aaToArray(K,V)(V[K] aa)
if (is(CommonType!(V, K)))
{
typeof(return) result;
foreach (key, value; aa) {
result ~= key;
result ~= value;
}
return result;
}

Then you can use it in a single line next time:

string[] arr = aaToArray([a: aa, b : bb]);
int[] arr = aaToArray([1: 2, 3: 4]);
... // etc.


T

-- 
Real men don't take backups. They put their source on a public
FTP-server and let the world mirror it. -- Linus Torvalds


Re: Foreach loop behaviour and manipulation

2014-01-07 Thread Binarydepth

On Thursday, 28 November 2013 at 23:45:26 UTC, H. S. Teoh wrote:

On Fri, Nov 29, 2013 at 12:36:18AM +0100, Binarydepth wrote:
Hi guys I'm having some problems. Calculations are not working 
as
expected and I get segmentation fault. I used the 2.059 
version and

it runs after compilation on compileonline.com

[...]

foreach(t; 1..51)
{
temp=t;
t*=20;


Modifying the loop variable of a foreach is, in general, a 
risky move.
If you need to make loop indices jump around, you should use a 
plain for

loop instead:

for (t=1; t  51; t++)
{
// modify t at will, just make sure your loop
// condition(s) / loop increments still work correctly.
}

or, if the loop indices are truly wildly jumping around, use a 
while

loop:

t = 1;
while (t  51 /* or whatever condition you may have */)
{
... // Do stuff
t = ... // compute next index to jump to
}


T


This excersice is an example :

Escriba un programa que determine los números (de cantidad de 
cifras par) divisores de 11
aplicando el siguiente concepto: cuando la suma de los dígitos 
alternos del número son iguales,
ese número es exactamente divisible por once. Por ejemplo 5841: 5 
+ 4 = 8 + 1, por lo tanto

el número 5841 es divisible por once.

The important part is los números (de cantidad de cifras par) 
The number of pair digits 10 to 99,  1000 to , 10 to 
99, etc...


I immediately thought of this thread. Surely you can use a series 
of if inside the loop that will make it jump the undesired 
numbers.


or ... for(count=1;count0  count100 || count999  
count1 || etc...; count++ )


Re: Simplest way to create an array from an associative array which its contains keys and values?

2014-01-07 Thread Craig Dillabaugh

On Tuesday, 7 January 2014 at 20:52:40 UTC, H. S. Teoh wrote:
On Tue, Jan 07, 2014 at 08:38:10PM +, Craig Dillabaugh 
wrote:

[...]
As someone with little experience with functional programming, 
I am
just curious - having browsed through the thread - if the 
various
solutions proposed here would really be considered more 
'idiomatic'
D. Or if they were posted because the OP asked about avoiding 
the

foreach() loop.

In other words while:

auto range = aa.byKey.map!(a = chain(a.only, aa[a].only));
string[] array = range.join;

Saves a few lines of code, and looks cooler, it seems that the
trivial foreach loop version is very easy:

string[] array;

foreach (key, value; aa) {
array ~= key;
array ~= value;
}

[...]

Even better, encapsulate this in a function:

CommonType!(K,V)[] aaToArray(K,V)(V[K] aa)
if (is(CommonType!(V, K)))
{
typeof(return) result;
foreach (key, value; aa) {
result ~= key;
result ~= value;
}
return result;
}

Then you can use it in a single line next time:

string[] arr = aaToArray([a: aa, b : bb]);
int[] arr = aaToArray([1: 2, 3: 4]);
... // etc.


T


Yes, I would imagine if this was not a 'one off' operation, you 
would likely want to create a function. That one looks nice.


I posted my question mainly because D advertises itself as a 
'multi-paradigm' language. It seems that a number of the more 
experienced posters on here seem to like functional approaches 
using the algorithms in std.algorithm.


However, it seems to me sometimes the obvious/simple solution 
that avoids using std.algorithm results in more readable code. So 
I was curious to know if using std.algorithm functions are 
generally considered preferable for simple cases like this, or if 
it is simply a matter of taste.


As an aside, the trade-off is even more blatant in C++ where a 
simple hand-rolled solution often comes out looking so much nicer 
than the STL algorithm alternative.





Re: Foreach loop behaviour and manipulation

2014-01-07 Thread Binarydepth


or ... for(count=1;count0  count100 || count999  
count1 || etc...; count++ )


 That won't work. It's better separate foreach loops.


Re: Simplest way to create an array from an associative array which its contains keys and values?

2014-01-07 Thread Andrej Mitrovic
On 1/7/14, Craig Dillabaugh cdill...@cg.scs.carleton.ca wrote:
 In other words while:

  auto range = aa.byKey.map!(a = chain(a.only, aa[a].only));
  string[] array = range.join;

 Saves a few lines of code, and looks cooler, it seems that the
 trivial foreach loop version is very easy:

 string[] array;

 foreach (key, value; aa) {
   array ~= key;
   array ~= value;
 }

OP asked for an array, however the reason I showed the example is
because you can get a range that way, which is lazy and will not
allocate:

auto items = aa.byKey.map!(a = chain(a.only, aa[a].only)).joiner;  //
no allocations at all
writeln(items);

So there's a huge difference, as you're saving memory (and CPU time if
you don't want to walk through the entire list).


Re: Simplest way to create an array from an associative array which its contains keys and values?

2014-01-07 Thread Jakob Ovrum
On Tuesday, 7 January 2014 at 20:38:11 UTC, Craig Dillabaugh 
wrote:
Saves a few lines of code, and looks cooler, it seems that the 
trivial foreach loop version is very easy:


string[] array;

foreach (key, value; aa) {
array ~= key;
array ~= value;
}


Assuming the return value of `byKey` has a length property, using 
std.array.array has the benefit of automatically allocating just 
once for the result, while your proposed alternative will grow on 
demand, causing several allocations that depend on the number of 
pairs in `aa`.


Of course, Teoh's `aaToArray` can trivially do this too, but the 
naive loop straight in user code is just that - naive.


Re: Foreach loop behaviour and manipulation

2014-01-07 Thread H. S. Teoh
On Tue, Jan 07, 2014 at 09:38:34PM +, Binarydepth wrote:
 
 or ... for(count=1;count0  count100 || count999 
 count1 || etc...; count++ )
 
  That won't work. It's better separate foreach loops.

Y'know, this code snippet really reminds me of why Jackson Structured
Programming helped me so much. While there are many ways of writing
loops, most ways are wrong (some blatantly so, while others only subtly
so). Writing a correct loop requires that the structure of the code
matches the structure of the problem that it's trying to process.

If you're trying to loop over two distinct ranges, 0 to 100 and 999 to
1, then conceptually they are two different operations, and
therefore should be mapped to two different loops. Trying to combine
them into one usually creates a mess, and even when you get it right,
the resulting code is fragile, error-prone, and hard to maintain.

I often see code like this:

bool first_time = false;
for (i=0; i  n; i++) {
if (first_time) {
do_something();
first_time = true;
}

if (i+1 == n) { // last time
do_something_else();
}

do_other_things();
}

This kind of code shows a poor mapping of code structure to problem
structure, which means it's prone to boundary condition bugs, overlap
bugs, and other sorts of problems, not to mention long-range
interdependencies that makes the code basically impossible to reuse, and
hard to maintain.

Consider what the loop is trying to do, by unrolling it. It looks like
this:

do_something();
do_other_things();
do_other_things();
do_other_things();
...
do_something_else();
do_other_things();

If you refactor this, you see that it follows the structure:

A -- B (repeat k times) -- C -- B

where A = do_something(), B = do_other_things(), and C =
do_something_else().

So you see that the repeating part in the structure of the problem is
really only with the middle part; A and the final C -- B should be put
*outside* the loop body, like this:

do_something();
for (i=1; i+1  n; i++) {   // N.B.: loop bounds adjusted
do_other_things();
}
do_something_else();
do_other_things();

Many programmers, esp. those with C/C++ background, cringe when they see
the second call to do_other_things() after the loop body, and they try
various ways of putting it inside the loop body -- especially when
do_other_things() is a big code block. But actually, this way of writing
it is the correct way, because it reflects the structure of the problem
more accurately. Putting everything inside one big loop creates a
structure conflict with the problem, which has a different structure;
this invites people to introduce boolean flags and other such hacks to
make things work correctly. But actually, that's just stitching over the
symptoms of the deeper problem, which is that the structure of the code
fails to correspond with the structure of the problem.

By making the structure of the code match the structure of the problem,
we eliminate the proliferation of boolean flags and convoluted loop
conditions (which are very error-prone and basically impossible to
maintain), and the code begins to speak for itself, because just by
looking at the structure of the code, you know what's the structure of
the problem it's working on. Once the structure is properly sorted out,
then we can worry about other things, like do_other_things() being a big
copy-n-pasted code block -- which then basically suggests the obvious
solution: factor it into a function.

A classic example of poor mapping of code structure to problem structure
is join(): inserting (n-1) delimiters into a list of n items. I almost
always see code like this:

foreach (i, e; range) {
result.put(e);
if (i+1  range.length)
result.put(',');
}

But let's step back for a moment and look at what's the *real* structure
of the problem. Suppose range = [1,2,3,4,5]. Then the desired output is:

1 , 2 , 3 , 4 , 5

Or, more abstractly, if we use 'e' in a generic sense to refer to any
item:

e , e , e , e , e , e

which can be factored into the form:

(e ,){(n-1) times} e

Due to the nature of the range API, however, this does not lend itself
to a straightforward implementation (there is no primitive for looping
over (n-1) items in a range). So we consider an alternative
factorization:

e (, e){(n-1) times}

This, then, suggests that the first element of the range should be
treated specially, which leads to the following code:

if (range.empty) return; // boundary case

result.put(range.front);
range.popFront();

while (!range.empty) {
result.put(',');

Re: segfault when using std.parallelism and std.process.executeShell

2014-01-07 Thread Ali Çehreli

On 12/12/2013 08:33 PM, Nikhil Padmanabhan wrote:

Hi,

The following code dies with a segfault :

import std.stdio, std.parallelism, std.process;

void main() {
 auto a=[hello,world,goodbye];
 foreach(s; parallel(a,1)) {
 auto ls=executeShell(echo ~s);
 writeln(ls.output);
 }
}


I don't know the original problem but that program works without any 
problem with the current dmd on github.


Ali



both in ldc and dmd. Removing either the parallel or running something
other than executeShell (eg. just doing a writeln) works, which suggests
to me that it's something about the way executeShell is interacting with
parallel.

Pulling it up in lldb, I get :
* thread #2: tid = 0x16738e6, 0x000100039198
test`D3std7process7environFNbNdNeZxPPa + 20, stop reason =
EXC_BAD_ACCESS (code=1, address=0x0)
 frame #0: 0x000100039198 test`D3std7process7environFNbNdNeZxPPa
+ 20

Any thoughts on what might be going wrong? Is executeShell somehow not
threadsafe?

Thanks!
-- Nikhil




Re: segfault when using std.parallelism and std.process.executeShell

2014-01-07 Thread Kelet

On Tuesday, 7 January 2014 at 23:12:09 UTC, Ali Çehreli wrote:
don't know the original problem but that program works without 
any problem with the current dmd on github.


Works for me on dmd v2.064 (current stable) on Windows.


Re: dirEntries throws exception on broken symlinks

2014-01-07 Thread Timothee Cour
I reported this here some time ago:
http://d.puremagic.com/issues/show_bug.cgi?id=11501 (dup of
http://d.puremagic.com/issues/show_bug.cgi?id=8298)
and there's a pull request ready, not sure why it isn't being merged


On Sun, Jan 5, 2014 at 10:20 PM, dennis denn...@visi.com wrote:

 On Sunday, 5 January 2014 at 21:33:56 UTC, FreeSlave wrote:

 You must not cast base class to derived class, when you don't know actual
 type (and even if you know exact type it's still bad practice to cast
 instance of more generic type to more specific one). Use multiple catch
 statements instead:

 catch(FileException o)
 {
 //handle FileException
 }
 catch(Exception o)
 {
 //handle all other types of exceptions
 }

 About dirEntries, you need to move your try/catch statements into loop
 somehow. You probably should save result of dirEntries to variable and then
 make manual loop instead of foreach. Result of dirEntries is lazy, so it
 will not throw exception when you just get it.

 It may look like

 auto entries = dirEntries(your args);
 while(!entries.empty)
 {
 try
 {
 entry = entries.front;
 //do your stuff
 }
 //catch statements
 finally
 {
 entries.popFront();
 }
 }


 Thank you for the quick feedback.  Your explanation of the two problems
 works for me.



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