[Linux-aus] Moose, JSON Question

David Lloyd lloy0076 at adam.com.au
Sun Jan 4 11:13:59 EST 2009


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.

>> Now, I also wanted to fiddle a bit with JSON so I thought, well,  
>> let's
>> do some TDD as practice and see what happens. Here's a cut down
>> version of TestJSON.pm:
> [...]
>>    sub json2perl {
>>        my ($self, $perl) = @_;
>>        return from_json($perl);
>>    }
> This will call from_json with only one argument, the '$perl' value.

And by the way, it works.

>> It appears that "from_json" is being interpreted as an object  
>> method and then
>> dispatched to JSON::from_json like this:
>>    JSON::from_jason($object_hash, $json);
> Yes, it is — because you explicitly called it that way.  The '->'
> operator passes the object on the left to the function on the right as
> the first argument.
> This has nothing to do with Moose, and would work the same way in any
> object / package you created.


>> Take careful note that the object hash is now in the array. The
>> function then reads the very first argument passed to it and then
>> balks.
>> In another session I managed this:
>>    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.

>> So, a few questions:
>> 1. If one uses a module in Perl 5.8.10 inside an object, but more
>>    specifically a Moose based object, and it imports functions into
>>    the module's namespace, it appears that the functions really are
>>    in the namespace and can be called
> Correct.
>>     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.

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

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


A "JSON" role?

>>     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. For example:

package myclass;

import some.random.letus.ExplodeTheWorld;

public class myclass {
   public myclass ();

...that I couldn't do:

public myclass;

    public class evil {
      public static void main(int arg, string argv[]) {

...whereas it seems that in Perl I could.


More information about the linux-aus mailing list