Senin, 05 Juli 2010

Spot the error

use Data::Rmap qw(:all);
use JSON;
use Data::Dump;
use Clone;
use boolean;

my $arg = from_json(q{{"1":true,"2":false}});
# convert JSON booleans to boolean's booleans
rmap_all { bless $_,"boolean" if ref($_) =~ /^JSON::(XS|PP)::Boolean$/ }, $arg;
dd $arg;


Hint: it's one character long.

In fact, this piece of code is full of Perl's traps (from Perl's lack of booleans obviously, to less obviously having to clone and rmap not working), it disgusts me.

9 komentar:

  1. Ah yes, I remember this. You were ranting on freenode #perl.

    I told you to use Data::Vistor.

    rmap_all in void context is incompetent just the same asmap in void context is.

    It disgusts me that you'd post such a failpile to Iron Man when the perl community spent hours trying to help you find an elegant solution and you chose not to listen.

    Yours, disappointed in your lack of desire to learn to write perl well

    -- mst

    BalasHapus
  2. Btw, to avoid some misunderstanding: I did not post about this problem on IRC (I don't hang out at IRC channels), I just found out about Data::Rmap today, and I am not complaining about Perl (instead, of my own piece of code).

    BalasHapus
  3. if rmap_all has singature of map built-in, it should be 'rmap_all { code } list', not 'rmap_all { code }, list' (with comma after code block). Did I guess correctly?

    BalasHapus
  4. @Jacob: yep. Unfortunately the addition of comma doesn't result in a warning/error, while in map() it does.

    BalasHapus
  5. The only problem I see is that you are using the wrong module. The rmap functions, like map itself, should be used for their output and you are trying to use rmap_all for its side effects. Use a module designed to do what you want like Data::Walk:

    #!/usr/bin/perl

    use strict;
    use warnings;
    use boolean;

    use JSON;
    use Data::Walk;
    use Data::Dump;

    my $arg = from_json(q{{"1":true,"2":false}});
    # convert JSON booleans to boolean's booleans

    walk sub {
        (ref $_) =~ /^JSON::(?:XS|PP)::Boolean$/ and bless $_, "boolean"
    }, $arg;

    dd $arg;

    BalasHapus
  6. The obvious error is the comma before the param list for rmap_all

    I think I would do it like this btw:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Data::Rmap qw(:all);
    use JSON;
    use Data::Dump;
    use boolean;

    my $arg = from_json( q{ {"1":true,"2":false} } );
    dd $arg;
    # convert JSON booleans to boolean's booleans
    rmap_all {
    if ( UNIVERSAL::isa($_, 'JSON::Boolean') ) {
    $_ = $_ ? true : false;
    }
    } $arg;
    dd $arg;

    and btw. perldoc boolean talks about JSON and YAML:

    Data interchange modules like YAML and JSON can now "use boolean" to encode/decode/roundtrip Boolean values.

    BalasHapus
  7. Oh and btw. there is a warning:

    nicolasm@akiko:~$ perl -wle 'use strict; use Data::Rmap; my $arg = {}; rmap_all { }, $arg;'
    Useless use of private variable in void context at -e line 1.
    nicolasm@akiko:~$ perl -wle 'use strict; use Data::Rmap; my $arg = {}; rmap_all { } $arg;'

    BalasHapus
  8. Oh even cleaner re: perldoc JSON:

    rmap_all { ($_ = $_ ? true : false) if JSON::is_bool($_); } ($arg);

    BalasHapus
  9. @Chas. Owens: the problem is, in Data::Rmap's POD, almost all the examples for rmap/rmap_all are in void context. So that might suggest that using it in void context is the recommended way.

    I did use Data::Walk in the previous version, but since it does not modify in place, I was looking for another module that does (since aside from reblessing I modify other stuffs too).

    BalasHapus