in reply to Re: find a substring of unknow lenght if it is in a hash
in thread find a substring of unknow lenght if it is in a hash

G'day perlynewby,

"question 1 I don't understand why on INDEX, the warning says $string is undef? and I also had to declare it again as "my" when I did on pragma."

When you get a error (or warning), it's vitally important that you paste it verbatim, not just type in a vague facsimile of the message.

I strongly suspect that the error you got didn't mention $string at all; instead, it made reference to $tring! (Note the missing 's'.)

So, to fix, add the 's' and remove the my (which you added).

"question 2 whys is the '~~" operator method it's not working"

That's the smart-match operator. It's experimental and subject to change. I recommend you learn non-experimental Perl before delving into ~~.

-- Ken

Replies are listed 'Best First'.
Re^3: find a substring of unknow lenght if it is in a hash
by perlynewby (Scribe) on Jun 29, 2015 at 21:03 UTC

    thank you

    I will add the error message it returns next time....Idon't know how my eyes missed that "s"...I spent time so much time trying to understand the error before asking. but ,now that you've pointed it out , I can see it clearly on the error message

    Use of uninitialized value $tring in index at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 49 (#3

    yeap, message said it was experimental too but I didn't actually understood that it may nt work...WILL stick with your advice.

    grazie

      ... I didn't actually understood that it [~~] may nt work...

      It may not work, but the greater danger is that it may work, and the way it works may be changed without notice in some future version of Perl — indeed, depending on the version of Perl you're using, it may already have been changed!

      Yes, it's definitely best to keep to the safe, well-lit archives and study halls of the Monastery and avoid the dark, dank cellars where Wizards delve!


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

Re^3: find a substring of unknow lenght if it is in a hash
by perlynewby (Scribe) on Jun 29, 2015 at 22:44 UTC

    Now, I have a question on WHY index worked at all? yes, I got an error while typing $string variable(skipped the "s" in code). however, I got an output anyways?

    so i went back and replicated the error so you can see it..again

    my $string = 'abcdefghijk'; my %match = (bc => "Michelangelo", efg => "Raffaello",de => "Caravaggi +o",ijk => "Tintoretto",hij=>"Leonardo",); foreach $art (keys %match){ print "this is INDEX $art =>",join(',',$match{$art}),"\n", if inde +x my $tring,$art; }
    Parentheses missing around "my" list at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 48 (#1) (W parenthesis) You said something like my $foo, $bar = @_; when you meant my ($foo, $bar) = @_; Remember that "my", "our", "local" and "state" bind tighter than c +omma. Use of uninitialized value $tring in index at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 48 (#2) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl will try to tell y +ou the name of the variable (if any) that was undefined. In some cas +es it cannot do this, so it also tells you what operation you used th +e undefined value in. Note, however, that perl optimizes your progr +am and the operation displayed in the warning may not necessarily app +ear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer to the concatenation (.) operator, even though there is no . in your program. this is INDEX efg =>Raffaello this is INDEX de =>Caravaggio this is INDEX hij =>Leonardo this is INDEX bc =>Michelangelo this is INDEX ijk =>Tintoretto
      index my $tring,$art

      A variable declaration like my returns a value:

      c:\@Work\Perl\monks>perl -wMstrict -le "my $x = my $y = my $z = 42; print $x; " 42
      In the case of your index expression, the  my $tring sub-expression defines a scalar variable and default-initializes it with the (very well defined) undefined value undef. This value is passed to the index built-in and "promoted" to  '' (the empty string), but because you have wisely asked Perl to do so, Perl warns you about this rather suspicious transaction (update: and also the business with my). index then searches for an occurrence of the string in  $art within the empty string, and returns its success/failure. The string in  $art is never found, so index always returns -1, which is a true if-condition, and so everything gets printed.

      Update: Here's an experiment: Is it possible that  '' (the empty string) is a valid hash key? If so, if you add a new artist's name to your hash as the value of the key empty-string, will this artist's name be printed in the for-loop? In other words, can index identify the empty-string of the key within the empty-string of the promoted undef? If it can, what value will index return?


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

        hmm, well, I see what it printed but I'm not sure if I defined the empty-string key in the hash as you have asked me, did I do it correctly?.

        If I add a space in between the tick marks then the hash returns

        this is INDEX =>bernini

        If no space between the ticks then match hash returns nothing.

        can you explained why even when the empty string(space in it) ' ' returns the key when there's not space in the $string that's being checked against??

        ok, I am have to read more on the index.

        I appreciate the well detailed explanations

        thank you

        my $string = 'abcdefghijk'; my %match = (' '=>"bernini",bc => "Michelangelo", efg => "Raffaello",d +e => "Caravaggio",ijk => "Tintoretto",hij=>"Leonardo",);
        foreach $art (keys %match){ print "this is INDEX $art =>",join(',',$match{$art}),"\n", if inde +x $string,$art; }
      "Now, I have a question on WHY index worked at all? yes, I got an error ..." [my emphasis]

      No you didn't get an error, you got two warnings:

      (W parenthesis) ... (W uninitialized)

      So, that's the short answer as to why it "worked at all": there was no error.

      However, the bigger problem is that, instead of looking closely at the output, you're just posting another question. While that may get an answer to a specific instance of a single type of problem, you're not gaining any general understanding and, as such, not really learning anything.

      So, let me try to work through the issues you encountered and show how Perl already provided the answers you sought from us.

      Firstly, you're using the strict and warnings pragmata. That's a really good idea, so well done. I use them all the time myself: you'd be hard-pressed to find any complete working script that I've posted (and there's hundreds of them) that doesn't use them. However, using them without understanding why you're doing so is less good: follow the links I've provided and read their documentation.

      The diagnostic messages that Perl emits are, by default, short and sweet! When you encounter one you haven't previously seen, you can look up its full description in perldiag — take a quick look at that now. Note the table at the top with the classification letters and the short description just below that. If you've read the documentation that I've linked to so far, you've learnt (at least) three things about the information Perl had given you:

      • (W parenthesis): a warning in the parenthesis category
      • (W uninitialized): a warning in the uninitialized category
      • (F): an error [you've seen it; didn't post it; I'll get to that in a minute]

      When you start learning Perl, and are unfamiliar with any of the diagnostic messages, you can spend a lot of time looking them up. The diagnostics pragma will look them up for you and display them; it can't, however, read the introductory description of perldiag for you (which is why I asked you to do that yourself). Eventually, you'll become familiar with the more common messages; the output from diagnostics will become a lot of unwanted clutter; you should stop using this pragma when you get to that stage. It's also important to realise that diagnostics is a developer tool: do not use it in production code!

      Hopefully, you now have a much better understanding of what those three pragmata are doing, and the ways in which Perl is providing you with help. In other words, not just that you asked for help, but specifically what help you asked for. Let's move on to the actual help Perl provided for you current code.

      First up, the one you didn't post, would have looked like:

      Global symbol "$tring" requires explicit package name (did you forget +to declare "my $tring"?) at ... Execution of ... aborted due to compilation errors (#1) (F) You've said "use strict" or "use strict vars", which indicates + that all variables must either be lexically scoped (using "my" or +"state"), declared beforehand using "our", or explicitly qualified to say which package the global variable is in (using "::"). Uncaught exception from user code: Global symbol "$tring" requires explicit package name (did you for +get to declare "my $tring"?) at ... Execution of ... aborted due to compilation errors.

      My guess is that you dealt with that something like: I've seen that before; add my to fix; error gone; all good. Well, as you now know, that wasn't "all good" at all: you only masked the error and, in doing so, generated two warnings that previously didn't exist. Here's how I would have dealt with it:

      1. Oh dear, I've made a typo. Good thing I asked Perl to spell-check my variable names. What the hell's a tring - that should be a string. Fix typo - error gone - didn't generated new warnings - really all good! However, if that wasn't a typo ...
      2. Oh dear, I've got a scoping issue. Luckily, my consistent indentation scheme should make that easy to find. There it is: brace should be after $tring, not before. Move brace and indent $tring - error gone - didn't generated new warnings - really all good! However, if that wasn't a scoping issue ...
      3. Oh dear, I actually forgot to declare $tring. I don't do that very often - but it does happen accasionally. Declare $tring - often with my (but could need state or our or $::tring or $Some::Package::tring) - error gone - didn't generated new warnings - really all good!

      The "Global symbol "$whatever" requires explicit package name ..." is one of the most common errors. Blindly adding my to make it go away is a really bad move. Look closely at your code, and fully understand why you got that error, before even attempting to formulate a fix.

      Now let's address those two warnings which you introduced with index my $tring,$art.

      index my $tring,$art is valid syntax:

      $ perl -MO=Deparse -e 'index my $tring,$art' index my $tring, $art; -e syntax OK

      [See B::Deparse for information on that strange looking incantation and perlrun for more on the -M switch]

      But you asked for warnings, and my $tring,$art doesn't look right to Perl, so Perl warns you about it: (W parenthesis). It also provides you with additional help ("Remember that "my", ... bind tighter than comma."): so, my $tring will be evaluated before $art.

      Similarly, when my $tring is evaluated, $tring is declared but not initialized, so Perl warns you about that too: (W uninitialized). And again, Perl provides more additional help: "It was interpreted as a "" or a 0 ...". It just keeps giving! :-)

      So, index my $tring,$art is interpreted as index "", $art. What happens when you run that? Let's check the documentation for index: "If the substring is not found, index returns -1.".

      There are only five things that Perl considers to to be FALSE: 0, '0', "", () and undef. The value, -1, is not one of them, and so is TRUE. See "perlsyn: Truth and Falsehood".

      If $art evaluates to the empty string, index "", $art will be index "", "" and return 0 (FALSE). If $art evaluates to any non-zero-length string, index "", $art will return -1 (TRUE). Accordingly, 'if index my $tring,$art' will always be TRUE (unless you had a zero-length key in %match) and the conditional print statement will execute.

      Throughout, Perl warned you of potential problems, as requested, and also told you how it was going handle them.

      In conclusion, read the information that you've requested from Perl. Read it thoroughly and act on that information. If you don't understand something, read the documentation. By doing this, you will learn, and probably learn a lot. And, when you really do get stuck, feel free to ask but ensure you tell us all the things you did to resolve the issue on your own.

      -- Ken