# #1: smart matching

## Posted on 2011-10-06 06:44:21 by 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
http://learn.perl.org/

Report this message

# #2: Re: smart matching

## Posted on 2011-10-06 09:10:30 by Shlomi Fish

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

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

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

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

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

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

Report this message

# #3: Re: smart matching

## Posted on 2011-10-06 10:18:38 by 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.

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

Regards,
timothy

--f46d044269a8be47f704ae9cf84e--

Report this message

# #4: Re: smart matching

## Posted on 2011-10-06 17:48:10 by John SJ Anderson

On Thu, Oct 6, 2011 at 03:10, Shlomi Fish <shlomif@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@perl.org