variable interpolation of refs to anonymous subroutines

C

cartercc

Reading from a database, I read the data into a hash of hashes.
Actually the last hash is the key to an anonymous array, which is what
I really want to get at, but one step at a time.)

I have a subroutine that prints these values out very nicely, like this
$hash1key->$hash2key->value1 value2 value3 etc. The values are what I
really want.

All this goes into a here document (which will be either XML or XHTML).
Is there a way to variable interpolate the return value from the
subrouting into the here document? Or perhaps to print directly from
the subroutine?

I've set my routine up as an anonymous subroutine with a reference to a
scalar, but all I get when I read the reference in my output is a
CODEREF and a hex dump. I've tried every permutation I can think of,
disambiguating with braces, etc., but I haven't found any way to make
this work, yet. I guess I could turn my here doc into a series of print
statements, but I really don't want to do that.

Thanks for all suggestions, CC.
 
J

J. Gleixner

Reading from a database, I read the data into a hash of hashes.
Actually the last hash is the key to an anonymous array, which is what
I really want to get at, but one step at a time.)

I have a subroutine that prints these values out very nicely, like this
$hash1key->$hash2key->value1 value2 value3 etc. The values are what I
really want.

All this goes into a here document (which will be either XML or XHTML).
Is there a way to variable interpolate the return value from the
subrouting into the here document? Or perhaps to print directly from
the subroutine?

I've set my routine up as an anonymous subroutine with a reference to a
scalar, but all I get when I read the reference in my output is a
CODEREF and a hex dump. I've tried every permutation I can think of,
disambiguating with braces, etc., but I haven't found any way to make
this work, yet. I guess I could turn my here doc into a series of print
statements, but I really don't want to do that.

Thanks for all suggestions, CC.

Suggenstion #1: Next time, post a small example of the issue.

Suggestion #2: perldoc Data::Dumper
 
C

cartercc

J. Gleixner said:
Suggenstion #1: Next time, post a small example of the issue.

Okay, code:

database schema like this:
table TASKS
tasks_id int primary key
day int
name varchar
description varchar
done_date date
done_by varchar
term varchar

code like this:
my %tasks # declare hash

#open connection to database and run query
while (my $rec = $sth->fetchrow_hashref())
{
$tasks{$rec->{day}}{$rec->{name}} =
[$rec->{description},$rec->{done_date},$rec->{done_by}];
}
#close connection to database

#print test to look at values
foreach my $line (keys(%tasks))
{
print "$line => $tasks{$line}<br />";
foreach my $line2 (keys %{$tasks{$line}})
{
print "$line2 => @{$tasks{$line}{$line2}}<br />";
}
}

#print here document, an HTML table that loops for appox 180 days
#I KNOW THIS IS WRONG, PLEASE, DON'T THROW ROCKS!!
<td><b>WEEK $i</b></td>
<td><span class=\"day_no\">$mo_month / $mo_date / $mo_year
($mo)</span>${print_tasks}->$mo</td>
<td><span class=\"day_no\">$tu_month / $tu_date / $tu_year
($tu)</span>$tasks{$tu}</td>
<td><span class=\"day_no\">$we_month / $we_date / $we_year
($we)</span>$tasks{$we}</td>
<td><span class=\"day_no\">$th_month / $th_date / $th_year
($th)</span>$tasks{$th}</td>
<td><span class=\"day_no\">$fr_month / $fr_date / $fr_year
($fr)</span>$tasks{$fr}</td>

cc
 
T

Tad McClellan

J. Gleixner said:
(e-mail address removed) wrote:


Suggenstion #1: Next time, post a small example of the issue.


Suggestion #0: Check the Perl FAQ *before* posting to the
Perl newsgroup.


perldoc -q function

How do I expand function calls in a string?
 
C

cartercc

Tad said:
Suggestion #0: Check the Perl FAQ *before* posting to the
Perl newsgroup.

I did. I tried the code samples, but none worked. Don't forget that I'm
working in a double quoted string.

I've read the perlref and FAQ4 on expanding both functions calls and
variables, but none worked. I can expand the nested hashes fine, but
I'd rather use the return result of a function which is passed the key
of the hash (the top level), and all this in a here doc.

I've also almost read the ink off the pages on Schwartz's book PORM,
particularly chapter 6, to no avail I've also consulted the Deitel and
Deitel How to Program Perl. I've done my due diligence, and I'm at a
dead end.

If it's not possible to variable interpolate functions in double quoted
strings (which I believe to be the case), I'll do it another way. But
if you (or anyone else) knows now to do this, I'd appreciate some
guidance.

Thanks much, CC.
 
D

David Squire

If it's not possible to variable interpolate functions in double quoted
strings (which I believe to be the case)

Not so.
I'll do it another way. But
if you (or anyone else) knows now to do this, I'd appreciate some
guidance.

This very issue was discussed in another thread here yesterday. See
perldoc -q expand, which in turn points to perldoc perlref.

DS
 
T

Tad McClellan

I did. I tried the code samples, but none worked.


If you post the broken code, we have a good chance at helping
you fix it.

If you don't, we don't.

Don't forget that I'm
working in a double quoted string.


What makes you think that I forgot that?

The FAQ answer that I pointed you to is in a double quoted string too.

I've read the perlref and FAQ4 on expanding both functions calls and
variables, but none worked.


If you post the broken code, we have a good chance at helping
you fix it.

If you don't, we don't.

I'd rather use the return result of a function which is passed the key
of the hash (the top level), and all this in a here doc.

I've also almost read the ink off the pages on Schwartz's book PORM,


I am familiar with that tome. :)

I've done my due diligence, and I'm at a
dead end.



If you post the broken code, we have a good chance at helping
you fix it.

If you don't, we don't.

Have you seen the Posting Guidelines that are posted here frequently?

If it's not possible to variable interpolate functions in double quoted
strings (which I believe to be the case),


It is possible, as shown in the FAQ answer!

if you (or anyone else) knows now to do this, I'd appreciate some
guidance.


It works for me:

---------------------------
#!/usr/bin/perl
use warnings;
use strict;

my %days = qw(
Sun Sunday
Mon Monday
Tues Tuesday
);

print <<ENDDOC;
the long version of 'Mon' is @{[ day('Mon') ]}.
ENDDOC

sub day {
my($key) = @_;
return $days{$key};
}
 
C

cartercc

Thanks, Tad,
Tad said:
If you post the broken code, we have a good chance at helping
you fix it.

If you don't, we don't.

You already have helped, so accept my thanks. My error was that I
attempted to use an ANONYMOUS subroutine, rather than a named routine.
So here's what I did --

I very carefully retyped your code, line by line, and it worked! (I'll
admit that I was mildly surprised, not because I doubted your ability,
but because I doubted mine.)

I then modified my script to name the subroutine, and it worked again!
(This time I will confess that I was moderately surprised.)

Now, I've corrected the entire table for all the days, and as soon as I
figure out which subscripts to use where, I'll be done.

I am curious about one thing. In essence the code is like this:

sub func { my $var = shift; return "Today is $var";}
print "What is today? @{[func('Wednesday')]}";

I understand the func('Wednesday') part of it. That's just a normal
function call. But what's with the @{[ ]}? I take it that the braces
are just a block, so I understand that. What I don't understand is the
@ symbol and the square brackets. Is this a real array, or some kind of
side effect? If it's a real array, where did it come from?
I am familiar with that tome. :)

And mine's almost worn out. Almost time to buy a new one.
Have you seen the Posting Guidelines that are posted here frequently?

Yes, and not only seen them but read them and have tried to comply with
them. However, to the extent that they require one to become an expert
before asking a question, I think they fall a bit short. I never ask
for help unless I'm at a dead end despite diligence, and I don't need
to be told to read the manual. I'm 56 years old, a full time IT staffer
with two advanced degrees and moderatly proficient in Perl, and while I
make stupid mistakes from time to time, I usually avoid them. I'm not
being ugly and don't want you to read these words with a bad tone, but
I want you to understand that I am a mature adult that knows how to
read for himself.
It is possible, as shown in the FAQ answer!

And as I just demonstrated to myself, with your help.

Thanks, Charles Carter.
 
D

David Squire

I am curious about one thing. In essence the code is like this:

sub func { my $var = shift; return "Today is $var";}
print "What is today? @{[func('Wednesday')]}";

I understand the func('Wednesday') part of it. That's just a normal
function call. But what's with the @{[ ]}? I take it that the braces
are just a block, so I understand that. What I don't understand is the
@ symbol and the square brackets. Is this a real array, or some kind of
side effect? If it's a real array, where did it come from?

This is explained in the FAQ entry to which you were directed. See
section "Using references" in perldoc perlref. @{...} is an array
dereference, and [] create a reference to an anonymous array.

DS
 
P

Paul Lalli

I am curious about one thing. In essence the code is like this:

sub func { my $var = shift; return "Today is $var";}
print "What is today? @{[func('Wednesday')]}";

I understand the func('Wednesday') part of it. That's just a normal
function call. But what's with the @{[ ]}? I take it that the braces
are just a block,

Incorrect assumption
so I understand that.

so no you don't.
What I don't understand is the
@ symbol and the square brackets. Is this a real array, or some kind of
side effect? If it's a real array, where did it come from?

You need to read:
perldoc perlreftut
perldoc perlref

[ ] is an operator that constructs a reference to an anonymous array.
For example:

my $ref = [ 5, 4, 2 ];

$ref is now a reference to an array that contains (5, 4, 2);

You dereference a reference by surrounding that reference in { } and
prepending the appropriate sigil ($ for a scalar reference, @ for an
array reference, and % for a hash reference):

my @array = @{$ref};

@array is now an array that contains the same values as does the array
referenced by $ref.

Putting it together:

func('Wednesday') is a function call that returns some value(s)
[ func('Wednesday') ] is a reference to an anonymous array that
contains the return values of the func subroutine
@{[ func('Wednesday') ]} is the actual array referenced by this
reference

Arrays can interpolate in double-quotish strings. Neither function
calls nor references can. That's why this process is necessary.
Yes, and not only seen them but read them and have tried to comply with
them. However, to the extent that they require one to become an expert
before asking a question, I think they fall a bit short.

I completely disagree with this assertion. They simply provide you
with tips on how to get the most help out of this group, by asking the
best possible questions.
I never ask
for help unless I'm at a dead end despite diligence, and I don't need
to be told to read the manual.

I'm sorry, but that's exceedingly arrogant. EVERYONE needs to be told
to read the manual. Unless you have it memorized (which you clearly
haven't), you should be reading it before asking questions.
I'm 56 years old, a full time IT staffer
with two advanced degrees and moderatly proficient in Perl,

None of which excuses you from having to write well thought out
questions. Forgive me, but someone of your age, who has presumably
been doing this for a while, should know better.
and while I
make stupid mistakes from time to time, I usually avoid them. I'm not
being ugly and don't want you to read these words with a bad tone, but
I want you to understand that I am a mature adult that knows how to
read for himself.

And yet for a mature adult who knows how to read, none of your prior
posts showed what code you tried, or how it "didn't work". That is, I
believe, what Tad was complaining about. You tried something, told us
it failed, and asked for help doing it the right way. But never once
showed us exactly what you tried so we could help you to fix it.

Paul Lalli
 
D

David Squire

Thanks, Tad,


You already have helped, so accept my thanks. My error was that I
attempted to use an ANONYMOUS subroutine, rather than a named routine.

It works fine with anonymous subroutines too, e.g.

prompt> perl -e '$anonsub = sub {$w = shift; return length($w)}; $word =
"frog"; print "$word has @{[ &$anonsub($word)]} characters"'
frog has 4 characters

Silly example, but you get the idea.

DS
 
D

David Squire

David said:
Thanks, Tad,


You already have helped, so accept my thanks. My error was that I
attempted to use an ANONYMOUS subroutine, rather than a named routine.

It works fine with anonymous subroutines too, e.g.

prompt> perl -e '$anonsub = sub {$w = shift; return length($w)}; $word =
"frog"; print "$word has @{[ &$anonsub($word)]} characters"'
frog has 4 characters

Or indeed, for even more anonymity, try:

prompt> perl -e ' $word = "frog"; print "$word has @{[&{sub{return
length($word)}}]} characters"'
frog has 4 characters

DS
 
T

Tad McClellan

You already have helped,
so accept my thanks.


You're welcome.

My error was that I
attempted to use an ANONYMOUS subroutine, rather than a named routine.


You can use an anonymous subroutine rather than a named one just fine.

If we had the code with said anonymous subroutine in it, then we
could show you how to use it...

So here's what I did --


Just post a short and complete program that we can run, and we
can almost for sure answer the question directly.

I am curious about one thing.


Did you follow the reference to perlref given in the FAQ answer?

In essence the code is like this:

sub func { my $var = shift; return "Today is $var";}
print "What is today? @{[func('Wednesday')]}";


Let's do the same thing with an anonymous subroutine:

my $sub = sub { my $var = shift; return "Today is $var"};
print "What is today? @{[ $sub->('Wednesday') ]}";

But what's with the @{[ ]}?


Let me read the docs to you:

The way it works is that when the C<@{...}> is seen in the double-quoted
string, it's evaluated as a block. The block creates a reference to an
anonymous array containing the results of the call to C<mysub(1,2,3)>. So
the whole block returns a reference to an array, which is then
And mine's almost worn out. Almost time to buy a new one.


There is a new edition (2nd) out now...

Yes, and not only seen them but read them and have tried to comply with
them.


I put that in there because you did not post a short and complete
program that we can run.

If you had, then we could have solved your problem with one followup
instead of this round-and-round that we now have.

I don't need
to be told to read the manual.


That seems at odds with what I can observe...
 
J

jgraber

Paul Lalli said:
(e-mail address removed) wrote:

snipped misc good explanations by Paul Lalli
I completely disagree with this assertion. They simply provide you
with tips on how to get the most help out of this group, by asking the
best possible questions.
Paul Lalli

I agree with the assertion, that the posting guidelines v 1.5
fall a bit short for non-experts.
They are insufficiently clearly written to be useful,
or at least,
I think they could be more clearly written and otherwise
improved to be more useful to non-expert.

As I have commented elsewhere, they include too few examples.
 
P

Paul Lalli

I agree with the assertion, that the posting guidelines v 1.5
fall a bit short for non-experts.
They are insufficiently clearly written to be useful,
or at least,
I think they could be more clearly written and otherwise
improved to be more useful to non-expert.

As I have commented elsewhere, they include too few examples.

Write up your improvements, and post them here for discussion. They're
not set in stone (that's why they have a version number, after all...)

Paul Lalli
 
J

jgraber

Paul Lalli said:
Write up your improvements, and post them here for discussion. They're
not set in stone (that's why they have a version number, after all...)

Paul Lalli

Been there, done that, but no discussion occurred,
Date: 21 Apr 2006 13:50:47 -0500
Message-ID: <[email protected]>

Perhaps I'm so clear and obvious that no one sees the need to comment.
 
A

A. Sinan Unur

....

Been there, done that, but no discussion occurred,
Date: 21 Apr 2006 13:50:47 -0500
Message-ID: <[email protected]>

Perhaps I'm so clear and obvious that no one sees the need to comment.

Interesting that you choose to disregard my response:

http://groups.google.com/group/comp.lang.perl.misc/msg/06f6873a852e8fe4

Besides, you did not write up your improvements: You attempted to assign
work by telling us what should be done.

Come up with the examples you want included if you want further
discussion.

Sinan


--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
 
C

cartercc

Tad said:
I put that in there because you did not post a short and complete
program that we can run.
If you had, then we could have solved your problem with one followup
instead of this round-and-round that we now have.

I should have kept my first effort, but that was two or three days ago,
and about two dozens versions back. I think the proper term is
'thrashing' and that's what I was doing. Next time, I promise, I'll
post the program.
That seems at odds with what I can observe...

Just because I'm ignorant doesn't mean that I'm stupid. I'm not a
programmer, but I use a lot of Perl in my job (database and system
administrator). I own and have studied most of the O'Reilly Perl books,
with some others (Deitel and Dubois, e.g.) but sometimes still get
stuck. I don't ask for sympathy, just a little slack.

My question may have seemed dumb to you, and I'm sorry I offended by
seeming to be obtuse, but I honestly did make a good attempt to solve
this particular problem with the documentation before posting.

Anyway, I appreciate the help -- I solved my problem and am feeling
pretty good now, and learned something to boot.

CC
 
C

cartercc

Paul said:
I'm sorry, but that's exceedingly arrogant. EVERYONE needs to be told
to read the manual. Unless you have it memorized (which you clearly
haven't), you should be reading it before asking questions.

Miscommunication. What I ^meant^ was that I KNOW that I should read the
manual, not that I can be lazy and ask for help rather than digging it
out myself. I totally agree with you that EVERYONE should read the
manual, and that I would have been exceedingly arrogant if I had meant
it the way you apparantly took it.
None of which excuses you from having to write well thought out
questions. Forgive me, but someone of your age, who has presumably
been doing this for a while, should know better.

I didn't offer this as an excuse. Just reading cookbooks doesn't make
you a cook, and reading documentation doesn't make you a programmer.
Sometimes we, you and me and everyone else, needs some guidance. I
offered something about my background to indicate something of
aptitude, not accomplishment. Maybe I should expressed myself a little
more elegantly.
And yet for a mature adult who knows how to read, none of your prior
posts showed what code you tried, or how it "didn't work". That is, I
believe, what Tad was complaining about. You tried something, told us
it failed, and asked for help doing it the right way. But never once
showed us exactly what you tried so we could help you to fix it.

Okay, I'll try to do better.

And if you still feel like continuing this discussion, let me ask this.
Dereferencing an anonymous array that contains the return values from a
function seems an awfully weird way to get at the behavior. I guess I
was thinking more along the lines of Java, where I would access an
object's method to do what I wanted. I see now that I was entirely on
the wrong track with Perl, but I feel a little like Alice must have
felt. Do you know of any particular reason for this, other than perhaps
only scalars and arrays can be variable interpolated? Might we be able
in the future to interpolate hashes and functions?

Thanks, CC.
 
J

jgraber

A. Sinan Unur said:

Thanks for that response to my question about ==cut==.
but I wouldn't call it a discussion of the merits of adding
"cargo-cult programming" examples to the posting guidelines.
Besides, you did not write up your improvements: You attempted to assign
work by telling us what should be done.

What form should "write up your improvements" take,
should I just edit the whole thing and post it as 1.6 (proposed) ?
Come up with the examples you want included if you want further
discussion. > Sinan

OK, I have included them here.

### Example Subject headers, add two lines above "Part of the beauty"
Example BAD Subject: Newbie, urgently need help with simple PERL question
Example GOOD Subject: How do I change all 'a' to 'b' with a regexp?


### Replacement first paragraph of "Ask perl to help you"
You can ask perl itself to help you find
common programming mistakes by doing three things:
use strict; # see perldoc strict
use warnings; # see perldoc warnings
use diagnostics; # see perldoc diag


### append this example to the end of "Provide enough information" section
Here is an example of a good post:

Subject: How do I change all 'a' to 'b' with a regexp?

I want to change all 'a' to 'b' with a regexp.
but only the first 'a' is getting changed.
This is the incorrect output of my program:
First line of text dbta
What I wanted is this, note dbtb, not dbta.
First line of text dbtb

#!/usr/local/bin/perl
use warnings; use strict; use diagnostics;
while (<DATA>) {
$_ =~ s/a/b/;
print $_; }
__DATA__
First line of text data

While this post demonstrates the guidelines for
incorrect output show, desired output shown,
short/complete pasteable, good subject line,
input __DATA__ included, use warnings/strict
it may fail the Social faux pas "..cursory doc search", since
the answer should be clear from line 1158 of the 2008 lines from
perldoc perlop, in the section labeled 's/PATTERN/REPLACEMENT/egimosx'
and tr/a/b/ would be a better choice than s///;

### end example
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top