Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re^7: Preparing data for Template

by Corion (Patriarch)
on Dec 31, 2020 at 12:48 UTC ( [id://11126041]=note: print w/replies, xml ) Need Help??


in reply to Re^6: Preparing data for Template
in thread Preparing data for Template

You are passing a hash reference:

display('test', $vars);
... but you are expecting a "hash" (well, list of pairs):

sub display { # my $self = shift; my $file = shift; my %vars = @_;

Most likely in display, you want instead:

sub display { my( $file, $vars ) = @_; $template->process("$file.tt", $vars); }

Replies are listed 'Best First'.
Re^8: Preparing data for Template
by Bod (Parson) on Dec 31, 2020 at 12:57 UTC
    You are passing a hash reference ... but you are expecting a "hash" (well, list of pairs)

    Yes - of course you are totally correct...
    My inability to properly conceptualise references strikes again :(

    I seem incapable of truly internalising references, especially when they are being passed between distinct lumps of code. Despite reading, understanding and implementing, when I come to create new code that passes references I always seem to run into trouble. I don't think it's a lack of knowledge, it is a lack of understanding that repeatedly causes problems similar to this one.

    Any thoughts on how to get over this mental block would be appreciated.

      Any thoughts on how to get over this mental block would be appreciated.

      Do you have more experience in other languages? For example, has the concept of pointers in C / C++, or the concept of variables holding references to objects in Java "clicked" for you? If so, it's probably possible to transfer that idea to references in Perl. A simplified view is: there's the variable that represents the "raw memory" that actually stores the data, e.g. $scalar, @array, or %hash, and then there are the references that basically store the memory address to another piece of data in a $scalar variable.

      When you say my %origvars = ( frames => \&get_frames );, you've got a fresh piece of memory and you're actually storing the key frames with its value there. When you say my $vars = \%origvars;, you're asking Perl to store the address of that piece of memory into the variable $vars, so you're not copying the hash, just saving a reference to it. my $vars = { frames => \&get_frames }; simply combines these two things into one step: it allocates a fresh piece of memory somewhere, stores the hash there (it's called an anonymous hash because you're not giving it a name like %origvars in the previous example), and then gives you a reference to that piece of memory.

      Dereferencing basically allows you to work with a reference as if it were the original data structure. So for example, $vars->{frames} doescan be used the same as $origvars{frames}, my %foo = %$vars; makes a shallow copy of the hash into %foo the same way that my %foo = %origvars; does, and so on.

      An important concept to remember is that Perl (almost) never implicitly references or dereferences anything, you have to do that through the corresponding operators. So in your example above, my suspicion would be that you've mixed up my %hash = (...); and my $hashref = {...};, or you're expecting a the hashref $vars to be automatically dereferenced where it won't be.

      Again, all of this is very much simplified in hopes that it might help make things click. A thorough read of perlref will hopefully help.

      What are references

      Every variable needs a memory address.

      C has pointers to handle that type of data. It has also pointer arithmetic.

      A reference is a safer abstraction of pointers, no dangerous arithmetics, no change after memory reorganization.

      What's different in Perl

      In contrast to most languages does Perl have explicit reference operators and reference data type (sub type of scalars)

      @a is the list form of an array. (That's also important for list context.)

      $a=\@a is the reference type of that array. But both variables "refer" to the identical array! \ is just an operator to expose the embedded reference.

      Semantic/syntactic differences

      @b=@a does a list copy of the content , hence $b[0]=42 won't affect $a[0] . Both variables (used to) have the same content, but at different memory locations.

      $b=$a=\@b copies the array "object" itself, i.e. $b "points" to the same "address" Hence $b->[0]=42 means $a->[0]==42

      Comparison to other languages

      Arrays, Hashes etc in JS, Python and Ruby are effectively glorified references.

      And array[0] there is implicitly de-referencing, where you need an explicit -> in Perl for $array_ref->[0]

      And when passing an array to a sub func(array) there you risk a modification at a distance there, while func(scalar) is only copying the content.

      That JS code is equivalent to func($array_ref) in Perl, in contrast to calling func(@array) which is passing a flattened LIST of elements.

      All of this applies equally to %hashes as well, just that flattening happens to a list of (key, value) pairs.

      Conclusion

      Perl is explicit and consistent here, whenever you don't copy references you are copying the content.

      With the added cost of more operators and syntax needed.

      But try to do achieve something simple like a copy of content @a = @b in JS!

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      UPDATES

      expanded with headlines

      Maybe a good approach would be to pass everything as references?

      Alternatively, check what the function wants to receive, and pass in that. If the function wants a list, pass in a list. If the function wants a reference, pass in a reference.

      The main reason functions get written to take references as parameters is that you can only pass one list to a function. myfunc( @foo, @bar ) will be received by sub myfunc { as one list in @_, without a way to discern the previous boundary between @foo and @bar.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11126041]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-23 09:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found