smart matching

trying to learn smart matching in an exercise.

Why does this program output "odd" when I input an even number?

Thank you,

Chris

#!/usr/bin/perl

use warnings;
use strict;

use 5.010;

say "Checking the number <$ARGV[0]>";

my $favorite = 62;

given( $ARGV[0] ) {
when( ! /^\d+$/ ) { say "Not a number!" }

my [at] divisors = divisors( $ARGV[0] );

when( [at] divisors ~~ 2 ) { # 2 is in [at] divisors
say "$_ is even";
continue;
}

when( !( [at] divisors ~~ 2 ) ) { # 2 isn't in [at] divisors
say "$_ is odd!";
continue;
}

when( [at] divisors ~~ $favorite ) {
say "$_ is divisible by my favorite number";
continue;
}

when( $favorite ) { # $_ ~~ $favorite
say "$_ is my favorite number";
continue;
}

my [at] empty;
when( [at] divisors ~~ [at] empty ) { say "Number is prime" }

default { say "$_ is divisible by [at] divisors" }
}

sub divisors {
my $number = shift;

my [at] divisors = ();
foreach my $divisor ( 2 .. ($ARGV[0]/2 + 1) ) {
push [at] divisors, $divisor unless $number % $divisor;
}

return [at] divisors;

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
Chris Stinemetz [ Do, 06 Oktober 2011 06:44 ] [ ID #2065328 ]

Re: smart matching

On Wed, 5 Oct 2011 23:44:21 -0500
Chris Stinemetz <chrisstinemetz [at] gmail.com> wrote:

> trying to learn smart matching in an exercise.
>
> Why does this program output "odd" when I input an even number?
>

A few comments on your code.

> Thank you,
>
> Chris
>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use 5.010;
>
> say "Checking the number <$ARGV[0]>";
>

You're using $ARGV[0] several times (duplicate code) and it's a positional
argument:

http://perl-begin.org/tutorials/bad-elements/#subroutine-arg uments

Better unpack it as:

my $number =3D shift( [at] ARGV);

> my $favorite =3D 62;
>
> given( $ARGV[0] ) {
> when( ! /^\d+$/ ) { say "Not a number!" }
>
> my [at] divisors =3D divisors( $ARGV[0] );
>

Returns arrays as references is preferable.

Furthermore, I think you can only put when inside given and not arbitrary c=
ode,
and that "when()" operates on the datum that was given to given().

> when( [at] divisors ~~ 2 ) { # 2 is in [at] divisors
> say "$_ is even";
> continue;
> }
>
> when( !( [at] divisors ~~ 2 ) ) { # 2 isn't in [at] divisors
> say "$_ is odd!";
> continue;
> }
>
> when( [at] divisors ~~ $favorite ) {
> say "$_ is divisible by my favorite number";
> continue;
> }
>
> when( $favorite ) { # $_ ~~ $favorite
> say "$_ is my favorite number";
> continue;
> }
>
> my [at] empty;
> when( [at] divisors ~~ [at] empty ) { say "Number is prime" }
>
> default { say "$_ is divisible by [at] divisors" }
> }
>

Your indentation is erratic.

> sub divisors {
> my $number =3D shift;
>
> my [at] divisors =3D ();

No need for the =C2=AB=3D ()=C2=BB here. An array is initialised as empty b=
y default.

> foreach my $divisor ( 2 .. ($ARGV[0]/2 + 1) ) {

Do you want to operate on "$number" or on "$ARGV[0]"?

> push [at] divisors, $divisor unless $number % $divisor;
> }
>

I got a "WTF?" moment when I saw this unless construct. I'd write it as:

if ($number % $divisor =3D=3D 0)
{
push [at] divisors, $divisor;
}

Regards,

Shlomi Fish

> return [at] divisors;
>



--
------------------------------------------------------------ -----
Shlomi Fish http://www.shlomifish.org/
Stop Using MSIE - http://www.shlomifish.org/no-ie/

I used to be arrogant. Now I=E2=80=99m simply Perfect.
=E2=80=94 one of Shlomi Fish=E2=80=99s relatives.

Please reply to list if it's a mailing list post - http://shlom.in/reply .

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
Shlomi Fish [ Do, 06 Oktober 2011 09:10 ] [ ID #2065329 ]

Re: smart matching

--f46d044269a8be47f704ae9cf84e
Content-Type: text/plain; charset=ISO-8859-1

Hi Chris,
I think you will need to work on your code to make it better or maybe this
is just a dirty codes for practice. If not, there are some stuff you may
have to weed out...some of which Shlomi Fish mentioned.

However, to make your code work as you suppose, please check this little
addition and you can take it up from there.

<code>
#!/usr/bin/perl

use warnings;
use strict;
use 5.010;

say "Checking the number <$ARGV[0]>";

my $favorite = 62;

given( $ARGV[0] ) {
when( ! /^\d+$/ ) { say "Not a number!" }

my [at] divisors = divisors( $ARGV[0] );
my $val=2; #added test value
when( [at] divisors ~~ /$val/) { # 2 is in [at] divisors ,/$val/ check it
say "$_ is even";
continue;
}

when( !( [at] divisors ~~/$val/ ) ) { # 2 isn't in [at] divisors /$val/ check
it
say "$_ is odd!";
continue;
}

when( [at] divisors ~~ /$favorite/ ) { # /$favorite/ check it
say "$_ is divisible by my favorite number";
continue;
}

when( /$favorite/ ) { # $_ ~~ $favorite
say "$_ is my favorite number";
continue;
}

my [at] empty;
when( [at] divisors ~~ [at] empty ) { say "Number is prime" }

default { say "$_ is divisible by [at] divisors" }
}

sub divisors {
my $number = shift;

my [at] divisors = ();
foreach my $divisor ( 2 .. ($ARGV[0]/2 + 1) ) {
push [at] divisors, $divisor unless $number % $divisor;
}

return [at] divisors;
}
</code>

Regards,
timothy

--f46d044269a8be47f704ae9cf84e--
timothy adigun [ Do, 06 Oktober 2011 10:18 ] [ ID #2065330 ]

Re: smart matching

On Thu, Oct 6, 2011 at 03:10, Shlomi Fish <shlomif [at] shlomifish.org> wrote:
> Furthermore, I think you can only put when inside given and not arbitrary code,
> and that "when()" operates on the datum that was given to given().

I don't think there's any restriction on what code can be inside the
'given' block -- at least, there's nothing in 'perlsyn' saying you
can't have other code in there.

You are correct that 'given()' sets up a (lexically scoped, I guess?)
$_ equal to the argument that it is given -- which is a copy, not an
alias -- and the smart matches in when() will then use that $_ -- but
if you have a 'when()' that doesn't check $_, then you're fine. See
sample code below.

Note: that is not say that any of this is *advisable* -- it's not,
unless you really really need to. (You don't really really need to, in
case you're wondering.) You're probably better off only having
'when()' blocks inside a 'given()' block, and you're probably better
off keeping the conditions in your 'when()' tests nice and simple.
You'll thank yourself down the road.

Sample code:

#! /usr/bin/env perl

use strict;
use warnings;
use feature 'switch';

$_ = 'outside';

my $foo = 'foo';

given( $foo ) {
when( 1 == 1 ) { print "INIT\n" ; continue }

when( 'bar' ) { print "BAR: $foo $_\n" }

$foo = 'bar';

when( 'foo' ) { print "FOO: $foo $_\n" }

$foo = 'baz';

when( 'outside' ) { print "OUT: $foo $_\n" }

default { print "DEF: $foo $_\n" }
}

print;

--
To unsubscribe, e-mail: beginners-unsubscribe [at] perl.org
For additional commands, e-mail: beginners-help [at] perl.org
http://learn.perl.org/
John SJ Anderson [ Do, 06 Oktober 2011 17:48 ] [ ID #2065338 ]
Perl » gmane.comp.lang.perl.beginners » smart matching

Vorheriges Thema: John SJ Anderson is Perl Beginners list moderator
Nächstes Thema: Regarding help in Threading