Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re^5: tk option+value in variable?

by cniggeler (Sexton)
on Jan 26, 2019 at 16:04 UTC ( [id://1229005] : note . print w/replies, xml ) Need Help??

in reply to Re^4: tk option+value in variable?
in thread tk option+value in variable?

Thank you for the detailed answer! I see you added a couple other ways to pass arguments to subroutines; in response to your questions,
What's the difference between feeding the strings "$x, $y" and '$x, $y' to eval?
The first "flattens" $x and $y to their integer literal values (2, 3) and passes that to add, while the 2nd passes the variable names ($x, $y), which are then resolved to their values in add.
What's @ra[ 2, 1 ] all about?
Selects elements 2 and 1 - integer literals (3, 2) - from @ra and passes those to add

If I am missing something please let me know, otherwise no need to reply. Thanks again!

Replies are listed 'Best First'.
Re^6: tk option+value in variable?
by AnomalousMonk (Archbishop) on Jan 26, 2019 at 22:23 UTC
    The first "flattens" $x and $y to their integer literal values (2, 3) and passes that to add ...

    I would express this somewhat differently. The word "flattens" brings to my mind the idea of "list flattening," which is not, as I see it, at work here. Instead, I would say that in the expression
        eval("$x, $y")
    the double-quote operator first interpolates the in-scope  $x $y variables into a string, and then passes the string, in this example "2, 3", a very simple source code string literal list expression, to eval to process, and indeed, eval returns just that list.

    ... the 2nd passes the variable names ($x, $y), which are then resolved to their values in add.

    Again, I would express this differently. I would say that eval is passed the "raw" string  '$x, $y' (single-quotes don't interpolate) and it is eval that resolves these variables to their values in the course of evaluating this string of Perl code, then returning the result of the evaluation. Nothing is resolved in add.

    In both cases, eval returns and add is passed exactly the same  (2, 3) list. In the second case, eval has a bit more work to do to achieve the same final result.

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

      Thanks again! By reducing to a simpler example, I now see that eval("$x + $y") and eval('$x + $y') are both evaluated by, er, eval. I had played with eval originally because I thought eval($mw->Label(-text => "Col. 1", $opt, -padx => 10)->grid( ...) would substitute $opt with its contents, and in turn evaluate the entire string. I still don't understand the steps the interpreter takes when processing an eval, but it's probably not a fruitful path to pursue further at this time. Better that I understand now that since subroutines take lists as their argument, @opt is an appropriate means to convey list items.
        I still don't understand the steps the interpreter takes when processing an eval

        eval with a string argument basically does the same thing as perl when it parses and executes Perl code. The thing that can get confusing is exactly what the contents of that string are. Consider this: when you write $x=3; $y=2; print "$x + $y";, then you know that double quotes interpolate, in this case meaning that the current values of those variables are substituted into the string. What gets passed to the print function is the string "3 + 2". On the other hand, in print '$x + $y';, the single quotes don't interpolate, and the string that gets passed to the function is exactly '$x + $y'. Now substitute eval for print, and I hope it's clear what strings are being passed to the function: In the first case, eval is parsing and executing the Perl code 3 + 2, and in the second case, it's parsing and executing the Perl code $x + $y, with the current values of those variables. Although in this simple example the result may be the same, it can get very tricky very quickly, for example if the code and especially the contents of the variables get more complex, if the string to be evaled gets stored for later execution, and so on.

        Further to haukex's post++, here's an untested way your original approach might have been made to work. Please understand that I only suggest this for the purpose of experimenting to gain a better understanding of eval when you meet it again.

        The basic idea here is to completely build and possibly check the eval string before passing it to eval.

        my $newfont = ...; my ($fg, $bg) = (..., ...); my $opt = "-fg => $fg, -bg => $bg"; $opt .= ", -font => $newfont" if length $newfont; my $eval_string = # note \$rw is escaped, $opt is NOT qq{\$rw->Label(-text => "Col. 1", $opt, -padx => 10)->grid( \$rw->Label(-text => "Col. 2", $opt, -padx => 11), \$rw->Label(-text => "Col. 3", $opt, -padx => 11)) }; print "eval string '$eval_string' \n" if $DEBUG; my $rw = ...; # tk object must exist before string is eval-ed eval $eval_string;
        Again, Don't Do This! in your Tk app: you'll give yourself a terrible headache. eval is powerful and can be very useful, but there's a time and place for everything.

        Just to pound this completely into the ground, if $opt had been something that made sense to Label (so you didn't get the "Odd number of args ..." or any other error), why couldn't
            eval($mw->Label(-text => "Col. 1", $opt, -padx => 10)->grid( ...));
        work? It might, or at least it might appear to.

        In the  eval EXPR invocation above, the expression is
            $mw->Label(-text => "Col. 1", $opt, -padx => 10)->grid( ...)
        and the value passed to eval depends on whatever the call to  grid() returns, which, IIRC, is nothing, the empty list (but I haven't checked this). In this case, the call to Label might work as expected when it was invoked during construction of the eval argument list, but when the (I think) empty argument list was then passed to eval, a perhaps puzzling Use of uninitialized value in eval "string" ... warning would be printed (if you had warnings enabled, which, as a righteous Monk, you always have :).

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