# smart matching

am 06.10.2011 06:44:21 von Chris Stinemetz
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 @divisors = divisors( $ARGV[0] );

when( @divisors ~~ 2 ) { # 2 is in @divisors

say "$_ is even";

continue;

}

when( !( @divisors ~~ 2 ) ) { # 2 isn't in @divisors

say "$_ is odd!";

continue;

}

when( @divisors ~~ $favorite ) {

say "$_ is divisible by my favorite number";

continue;

}

when( $favorite ) { # $_ ~~ $favorite

say "$_ is my favorite number";

continue;

}

my @empty;

when( @divisors ~~ @empty ) { say "Number is prime" }

default { say "$_ is divisible by @divisors" }

}

sub divisors {

my $number = shift;

my @divisors = ();

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

push @divisors, $divisor unless $number % $divisor;

}

return @divisors;

--

To unsubscribe, e-mail: beginners-unsubscribe@perl.org

For additional commands, e-mail: beginners-help@perl.org

http://learn.perl.org/

## Re: smart matching

am 06.10.2011 09:10:30 von Shlomi Fish
On Wed, 5 Oct 2011 23:44:21 -0500

Chris Stinemetz wrote:

> trying to learn smart matching in an exercise.

>=20

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

>=20

A few comments on your code.

> Thank you,

>=20

> Chris

>=20

> #!/usr/bin/perl

>=20

> use warnings;

> use strict;

>=20

> use 5.010;

>=20

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

>=20

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(@ARGV);

> my $favorite =3D 62;

>=20

> given( $ARGV[0] ) {

> when( ! /^\d+$/ ) { say "Not a number!" }

>=20

> my @divisors =3D divisors( $ARGV[0] );

>=20

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( @divisors ~~ 2 ) { # 2 is in @divisors

> say "$_ is even";

> continue;

> }

>=20

> when( !( @divisors ~~ 2 ) ) { # 2 isn't in @divisors

> say "$_ is odd!";

> continue;

> }

>=20

> when( @divisors ~~ $favorite ) {

> say "$_ is divisible by my favorite number";

> continue;

> }

>=20

> when( $favorite ) { # $_ ~~ $favorite

> say "$_ is my favorite number";

> continue;

> }

>=20

> my @empty;

> when( @divisors ~~ @empty ) { say "Number is prime" }

>=20

> default { say "$_ is divisible by @divisors" }

> }

>=20

Your indentation is erratic.

> sub divisors {

> my $number =3D shift;

>=20

> my @divisors =3D ();

No need for the Â«=3D ()Â» 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 @divisors, $divisor unless $number % $divisor;

> }

>

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

if ($number % $divisor == 0)

{

push @divisors, $divisor;

}

Regards,

Shlomi Fish

=20

> return @divisors;

>=20

--=20

------------------------------------------------------------ -----

Shlomi Fish http://www.shlomifish.org/

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

I used to be arrogant. Now Iâ=99m simply Perfect.

â=94 one of Shlomi Fishâ=99s relatives.

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

--

To unsubscribe, e-mail: beginners-unsubscribe@perl.org

For additional commands, e-mail: beginners-help@perl.org

http://learn.perl.org/

## Re: smart matching

am 06.10.2011 10:18:38 von timothy adigun
--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.

#!/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 @divisors = divisors( $ARGV[0] );

my $val=2; #added test value

when( @divisors ~~ /$val/) { # 2 is in @divisors ,/$val/ check it

say "$_ is even";

continue;

}

when( !( @divisors ~~/$val/ ) ) { # 2 isn't in @divisors /$val/ check

it

say "$_ is odd!";

continue;

}

when( @divisors ~~ /$favorite/ ) { # /$favorite/ check it

say "$_ is divisible by my favorite number";

continue;

}

when( /$favorite/ ) { # $_ ~~ $favorite

say "$_ is my favorite number";

continue;

}

my @empty;

when( @divisors ~~ @empty ) { say "Number is prime" }

default { say "$_ is divisible by @divisors" }

}

sub divisors {

my $number = shift;

my @divisors = ();

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

push @divisors, $divisor unless $number % $divisor;

}

return @divisors;

}

Regards,

timothy

--f46d044269a8be47f704ae9cf84e--

## Re: smart matching

am 06.10.2011 17:48:10 von John SJ Anderson
On Thu, Oct 6, 2011 at 03:10, Shlomi Fish 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@perl.org

For additional commands, e-mail: beginners-help@perl.org

http://learn.perl.org/