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

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Jan 7 12:44:12 PST 2014


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


More information about the Digitalmars-d-learn mailing list