[Linux-aus] Moose, JSON Question

Daniel Pittman daniel at rimspace.net
Sun Jan 4 13:49:17 EST 2009


David Lloyd <lloy0076 at adam.com.au> writes:
> On 03/01/2009, at 7:49 PM, Daniel Pittman wrote:
>> David Lloyd <lloy0076 at adam.com.au> writes:
>>
>>> At the recent OSDC I heard about Moose so I thought I'd take the Moose
>>> out on the hunting range to see what I could come up with.
>>
>> Your question isn't actually Moose related, but a generic Perl question,
>> as far as I can tell.
>
> That's what I thought but seeing I'd put in a module I don't have that
> much experience with, and one that probably fiddles a bit to do what
> it does I'd mentin it.

It is good to add the extra detail, and I am glad I wasn't missing
something in there. :)

[...]

>>>    DB<3> $tj->to_json({a => 'b'});
>>>    Can't locate object method "a" via package "JSON" at /Library/
>>> Perl/5.8.8/JSON.pm
>>>    line 136.
>>
>> The JSON package to_json treats the hash keys in the second argument as
>> local method calls, resulting in this error.
>
> Ah, well spotted, I didn't quite see that.

I had to go as far as reading the module code to make sure that was what
was going on, and I am disappointed that the JSON code handles invalid
arguments in such an ... unclean fashion.  Oh, well.  Error handling is
never that great across the board.

[...]

>>>     1. But the caveat is that they don't do what you expect them to
>>>        do...
>>
>> They don't do what *you* expect them to do — your examples did
>> exactly what I expected. ;) More seriously, this is the standard Perl
>> behaviour, not anything to do with Moose or otherwise.
>
> Sometimes Perl gives me the willies, to use the vernacular.

Heh.  Fair enough.  I confess I never really understood that, myself,
since the behaviour is almost always pretty consistent, but the DWIM
features can sometimes be very confusing, even to experts. :)

>>> 2. Interestingly if I remove the perl2json or json2perl class, the
>>>    class methods "to_json" and "from_json" respectively (or both)
>>>    throw a "can't be found in namespace error", i.e. Moose/Perl
>>>    can't find them
>>>     1. Which implies they're being loaded because they're used in the
>>>        module...
>>>     2. I've looked into JSON's source code and it seems to be doing
>>>        some funky stuff to figure out which backend JSON:: one is
>>>        using but other than that it looks like a standard Exporter
>>>        to me, it just has rolled its own export and import functions
>>
>> They should show up in the namespace... and a quick test here shows that
>> they do:
>>
>>    perl -e 'package Test; use JSON; package main; \
>>        print UNIVERSAL::can("Test", "to_json") ? "imported\n" : "missing\n"'
>
> I must have missed that when I did:
>
> perl -Ilib -MTestJSOn -e -d 0
> ...
> DB<?> S
> [lots of methods]

Odd.  I don't know if there is anything special that might hide them
from the debugger 'S' output—I have never actually used the Perl
debugger, to be honest, so don't know what quirks it might hide.

[...]

>>> 3. As a matter of OO style, is it "nice" to expose "used" package's
>>>    imports in the class one is making even though the behaviour if
>>>    you use them as a class method appears to be strange
>>
>> Generally, no, you wouldn't expect to import a random class into your
>> object and have it add methods.
>
> Exactly - I think my trotting about in Java lately has kind of insulated me a
> little .
>
>> With Moose this is even less common: the 'Role' type is used for the
>> purpose of class extension, in a cleaner fashion than random exports
>> into your namespace.
>
> *hmm*  A "JSON" role?

Well, you should probably think of a Moose "role" as a Java "interface",
kind of, except that it comes with implementation as well.

So, yes, a JSON role would be reasonable, along the lines of adding a
'to_json' and 'from_json' method to any Moose class, which
implementation then generated or created an instance from JSON.

>>>     1. That is, in this case I did "use JSON;" and caused "from_json"
>>>        and "to_json" to materialise - if I have an actual object
>>>        (TestJSON->new()) I can call them but as shown the behaviour
>>>        is suboptimal
>>
>> Your calling convention is wrong: the JSON methods need to have their
>> data as the first argument, and calling them as methods means that they
>> don't.
>
> I understood that much - hopefully my commentary indicated that I'd
> detected that they were being called as class methods rather than
> POPMs (Plain Old Perl Methods).
>
>> The summary is, don't do that.  Use your wrapper methods. ;)
>
> I was kind of hoping that Moose or the Perl Object system would
> insulate me from this type of shenanigans.

Those "shenanigans" are the basic ingredients of method calling in Perl;
would you really want an OO system that completely and utterly changed
the calling convention of the language?


Imagine, in Java, the effect of adding a module that changed the calling
convention so that instead of this...

   RandomClass foo = new RandomClass;
   foo.bar(1, 2.3);

...calling the 'bar' method on the 'RandomClass' class, it did this:

1. Look up a global object named 'bar'
2. Call a method on it, passing it the strings 'RandomClass', 'integer'
   'float'
3. Got an anonymous function back from back from that method call.
4. Invoked that anonymous function with the values foo, 1 and 2.3

That would be more than a little surprising, right?

That, essentially, is what you were expecting Moose to do: to completely
change the method / function calling convention into something that
behaved completely differently.

Regards,
        Daniel

Not that multiple-dispatch is in any way a bad thing, and it would
significantly improve Java to have it. :)



More information about the linux-aus mailing list