Jump to page: 1 2 3
Thread overview
Is it possible to handle 'magic' property assignments a'la PHP?
Jan 04, 2014
Gary Willoughby
Jan 04, 2014
Gary Willoughby
Jan 04, 2014
Gary Willoughby
Jan 04, 2014
Gary Willoughby
Jan 04, 2014
Adam D. Ruppe
Jan 04, 2014
H. S. Teoh
Jan 05, 2014
Philippe Sigaud
Jan 05, 2014
TheFlyingFiddle
Jan 05, 2014
Artur Skawina
Jan 05, 2014
TheFlyingFiddle
Jan 05, 2014
Jacob Carlborg
Jan 05, 2014
Philippe Sigaud
Jan 06, 2014
Jacob Carlborg
Jan 06, 2014
Philippe Sigaud
Jan 07, 2014
Jacob Carlborg
Jan 07, 2014
Philippe Sigaud
Jan 07, 2014
Jacob Carlborg
Jan 07, 2014
H. S. Teoh
Jan 07, 2014
Jacob Carlborg
Jan 07, 2014
H. S. Teoh
Jan 08, 2014
Jacob Carlborg
Jan 08, 2014
H. S. Teoh
Jan 09, 2014
Jacob Carlborg
Jan 09, 2014
H. S. Teoh
Jan 09, 2014
Jacob Carlborg
January 04, 2014
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!"
    }
}
January 04, 2014
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!
January 04, 2014
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?
January 04, 2014
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";
	}
January 04, 2014
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.
January 04, 2014
On Sat, Jan 04, 2014 at 07:52:11PM +0000, 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:
January 05, 2014
On Sat, Jan 4, 2014 at 10:08 PM, H. S. Teoh <hsteoh@quickfur.ath.cx> 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 findByXXXXX and generate the related query. A bit like Activerecord for Ruby.
January 05, 2014
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!.
January 05, 2014
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
> findByXXXXX 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
January 05, 2014
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
« First   ‹ Prev
1 2 3