http://qs321.pair.com?node_id=11118540

catfish1116 has asked for the wisdom of the Perl Monks concerning the following question:

I'm not getting any errors but program doesn't pick up the first character if it is a '@'. code below

#* Progrmm prompts user fpr input and determines # ## which data type it is (scalar array or hash) # ## # ##################################################### print "Enter a string and I will determine the data type: "; chomp(my $_ = <STDIN>); if ($_ = (m/^[\$]\w/)) { print "\nThat is a scalar data type\n"; } elsif ($_ = (m/^[\@]\w/)) { print "\nThat is an array data type\n"; } else { print "\nData type not found\n"; }

it will recognize the '$' leading character but not the '@'. In my code I have the match set up the same. TIA The Catfish

Replies are listed 'Best First'.
Re: If statement not working
by choroba (Archbishop) on Jun 25, 2020 at 17:21 UTC
    Short answer: Use =~ instead of = to bind a regex against a variable.

    Long answer: The $_ is the default topic. You don't need to mention it in many contexts, matching a regex being one of them. So, you can shorten the code to

    if (/^[\$]\w/) { print "\nThat is a scalar data type\n"; } elsif (m/^[\@]\w/) { print "\nThat is an array data type\n"; } else { print "\nData type not found\n"; }

    When you use =, it changes the contents of $_, so after the first condition, it contains the result of the regex match, not the original user input.

    Also, remove the my from $_. Lexical $_ was deprecated and is not supported in modern Perl versions. Use local if you want to incorporate the code into a larger codebase.

    Update:

    Moreover, you can also use a hash from sigils to data types, no regex and if/else needed:

    print "Enter a string and I will determine the data type: "; chomp(local $_ = <STDIN>); my %sigil2type = ('$' => 'scalar', '@' => 'array', '%' => 'hash', '*' => 'GLOB'); my $sigil = substr $_, 0, 1; my $type = $sigil2type{$sigil} || 'unknown'; say "\nThat is a $type data type.";

    Update2: The $_ will be populated with the match result, not with the regex. Thanks AnomalousMonk.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: If statement not working
by perlfan (Vicar) on Jun 25, 2020 at 17:39 UTC
    if ($_ = (m/^[\$]\w/)) {

    Solution pointed out below. This is an assignment (using =) clobbering $_ with an empty array the true/false result. An assignment of an undefined thing evaluates to false every time. Similar to if ($_ = ()) or if ($_ = undef).

    Update - because I was curious:

    perl -MO=Deparse,-P -e 'if($_ = (m/foo/)) { print 'hi' }' if ($_ = /foo/) { print hi $_; } -e syntax OK

    A little more insight.

    update 2- corrected ty

      This is an assignment (using =) clobbering $_ with an empty array. An assignment of an undefined ... Similar to if ($_ = ()) or if ($_ = undef).

      $_ is clobbered with the true/false result of evaluating the match of the regex against $_:

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -e "print 'Enter a string and I will determine the data type: '; chomp($_ = <STDIN>); dd 'A:', $_; ;; if ($_ = (m/^[\$]\w/)) { print qq{\n'$_' is a scalar data type\n}; } dd 'B:', $_; ;; if ($_ = (m/^[\@]\w/)) { print qq{\n'$_' is an array data type\n}; } dd 'C:', $_; " Enter a string and I will determine the data type: $scalar ("A:", "\$scalar") '1' is a scalar data type ("B:", 1) ("C:", "") c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -e "print 'Enter a string and I will determine the data type: '; chomp($_ = <STDIN>); dd 'A:', $_; ;; if ($_ = (m/^[\$]\w/)) { print qq{\n'$_' is a scalar data type\n}; } dd 'B:', $_; ;; if ($_ = (m/^[\@]\w/)) { print qq{\n'$_' is an array data type\n}; } dd 'C:', $_; " Enter a string and I will determine the data type: @ra ("A:", "\@ra") ("B:", "") ("C:", "")


      Give a man a fish:  <%-{-{-{-<

        ty fixed