Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Type checker not checking out

by clemburg (Curate)
on Jul 31, 2001 at 18:22 UTC ( [id://101161]=note: print w/replies, xml ) Need Help??


in reply to Type checker not checking out

I would attack this problem differently, by use of higher-level functions (predicates).

Like this:

#!/usr/bin/perl -w use strict; sub map_recursive { my ($structure, $predicate) = @_; my @result; if (UNIVERSAL::isa($structure, 'ARRAY')) { for (@{$structure}) { push @result, map_recursive($_, $predicate); } } elsif (UNIVERSAL::isa($structure, 'HASH')) { for (keys %{$structure}) { push @result, map_recursive($structure->{$_}, $predicate); } } else { push @result, $predicate->($structure); } return @result; } my $scalar = 2; my @list = (1, 3, 8, 10); my %hash = (a => 1, b => 2, c => 3); my $oddp = sub { (((shift) % 2) == 1) ? 1 : 0 }; print "#1: ", join(",", map_recursive($scalar, $oddp)), "\n"; print "#1: ", join(",", map_recursive(\@list, $oddp)), "\n"; print "#1: ", join(",", map_recursive(\%hash, $oddp)), "\n";

Then you can hide the complexity of actually checking the type in the predicate.

Christian Lemburg
Brainbench MVP for Perl
http://www.brainbench.com

Replies are listed 'Best First'.
Re: Re: Type checker not checking out
by premchai21 (Curate) on Aug 05, 2001 at 07:31 UTC
    Hmm... but what if I need to check for, say, an array of objects of a certain type? Suppose I do this:
    package Foo; sub new { bless {}, shift } sub get { $_[0]->{$_[1]} } sub set { $_[0]->{$_[1]} = $_[2] } package main; my @list = (Foo->new, Foo->new, Foo->new); $list[0]->set('a', 'b'); $list[1]->set('b', 'a'); $list[2]->set('x', 'y'); my $isa_foo = sub { UNIVERSAL::isa(shift, 'Foo') }; print join ',', map_recursive(\@list, $isa_foo);
    This doesn't work, because map_recursive will descend an extra level into the Foo structure itself, and give me intermingled 1s and 0s which have no meaning to me or my program whatsoever.

    It descends into the Foo, finding it to be a hash, and declares 0 on 'a', 'b', and 'y', since they aren't Foos. Or:

    my @list2 = ( {a => 'm'}, { 1 => 55}, { Foo => 'Bar' }); my $h = sub { UNIVERSAL::isa(shift, 'HASH') }; print join ',', map_recursive (\@list2, $h);
    And here I'm looking to check for an array of hashes. But oh my, 55 isn't a hash, so this gets disqualified. You see now why map_recursive won't do; the format I'm using allows one to specify the whole structure.

    However, it doesn't quite work yet...

    Update: clemburg's solution below works better than the one above. I think I'll probably use that. Thanks you, clemburg.

      Easy. Change map_recursive() to not descend into recognized structures. That is probably the more sensible default behavior, agreed.

      #!/usr/bin/perl -w use strict; sub map_recursive { my ($structure, $predicate) = @_; # don't descend into recognized structures if ($predicate->($structure)) { return $predicate->($structure); } # not recognized - pick apart my @result; if (UNIVERSAL::isa($structure, 'ARRAY')) { for (@{$structure}) { push @result, map_recursive($_, $predicate); } } elsif (UNIVERSAL::isa($structure, 'HASH')) { for (keys %{$structure}) { push @result, map_recursive($structure->{$_}, $predicate); } } else { push @result, $predicate->($structure); } return @result; } package Foo; sub new { bless {}, shift } sub get { $_[0]->{$_[1]} } sub set { $_[0]->{$_[1]} = $_[2] } package main; my @list = (Foo->new, Foo->new, Foo->new); $list[0]->set('a', 'b'); $list[1]->set('b', 'a'); $list[2]->set('x', 'y'); my $isa_foo = sub { UNIVERSAL::isa(shift, 'Foo') }; print "#1: ", join(',', map_recursive(\@list, $isa_foo)), "\n"; my @list2 = ( {a => 'm'}, { 1 => 55}, { Foo => 'Bar' }); my $h = sub { UNIVERSAL::isa(shift, 'HASH') }; print "#2: ", join(',', map_recursive (\@list2, $h)), "\n";

      Christian Lemburg
      Brainbench MVP for Perl
      http://www.brainbench.com

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://101161]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-19 21:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found