Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Trying to avoid passing params to subs through globals

Reply
Thread Tools

Trying to avoid passing params to subs through globals

 
 
Justin C
Guest
Posts: n/a
 
      12-10-2009

Further to me recent problem of unblessed references, I'm re-writing my
code, putting more of it into subroutines so that the main thread is
more obvious. I'm finding that where I was using global variables there
appear to be a lot of variables that need passing to some sub-routines.

I'm thinking of creating a few hashes of references to these variables,
and then passing the whole hash (or a reference to it) to the
subroutine.

my %excel = (
"worksheet" => \$ws,
"workboot" => \$wb,
"format_1" => \$format_1,
"format_2" => \$format_2,
);

my %document = (
"pdf" => \$pdf,
"table" => \$table,
);

Firstly, if these are defined near the begining of the program they look
just like globals to me! What's the difference? OK, so I can just
declare "my %excel =();" and then have a subroutine(s) populate it on an
ad-hoc basis, that, I suppose, looks less global.

To avoid a whole bunch of vars being global I can see that I'm going to
have to nest a lot of sub-routines so that I can keep scope minimal.

The other thing is, if $ws, for example, was returned as a reference (I
think I really need to see where I should return references, and where I
should return the actual thing... if it's an object return the thing, if
it's scalar, array or hash return a ref? maybe that's too crude) I
surely shouldn't be creating a reference to it (in the hash
assignement), so it should be "worksheet" => $ws" instead of "\$ws",
shouldn't it?

Sorry if the above sounds a bit random, it's hitting the keyboard as
it's coming to mind, and I shouldn't really be doing this now, I'm
supposed to be working... though the work I'm supposed to be doing is
getting this program to do what we want - it's a little chicken and egg
here at the moment.

Justin.

--
Justin C, by the sea.
 
Reply With Quote
 
 
 
 
Randal L. Schwartz
Guest
Posts: n/a
 
      12-10-2009
>>>>> "Justin" == Justin C <(E-Mail Removed)> writes:

Justin> Further to me recent problem of unblessed references, I'm re-writing my
Justin> code, putting more of it into subroutines so that the main thread is
Justin> more obvious. I'm finding that where I was using global variables there
Justin> appear to be a lot of variables that need passing to some sub-routines.

Sounds like related state correlated with related behavior.

That's called an "object".

Might wanna look into that.

If you need, I can recommend a good book (or two .

print "Just another Perl hacker,"; # the original

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<(E-Mail Removed)> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
 
Reply With Quote
 
 
 
 
Uri Guttman
Guest
Posts: n/a
 
      12-14-2009
>>>>> "SRB" == Sir Robert Burbridge <(E-Mail Removed)> writes:

SRB> Although, I've actually found this a very helpful paradigm:

actually that is a poor paradigm.

SRB> sub do_something {
SRB> ...
SRB> my $handler = sub {
SRB> ...
SRB> };

SRB> if ($cond_a) {
SRB> return $handler->(do_a());
SRB> } elsif ($cond_b) {

why the else (of the if) when you just returned? make it cleaner by just
falling through to a plain if.

SRB> return $handler->(do_b());
SRB> } else {
SRB> return $handler->(do_c());
SRB> }
SRB> }

better yet, use a dispatch table. i hate elsif's and try to never use
them. they are a marker for poor logic. hell, i eschew else as well. in
over 10k lines in one project i had about 3 elsif's and 11 else's. and
the code is very readable. it is just done with very clean logic and
code flow.

uri

--
Uri Guttman ------ http://www.velocityreviews.com/forums/(E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      12-14-2009
>>>>> "SRB" == Sir Robert Burbridge <(E-Mail Removed)> writes:

SRB> On 12/14/2009 01:46 PM, Uri Guttman wrote:
SRB> if ($cond_a) {
SRB> return $handler->(do_a());
SRB> } elsif ($cond_b) {
>>
>> why the else (of the if) when you just returned? make it cleaner by just
>> falling through to a plain if.
>>

SRB> return $handler->(do_b());
SRB> } else {
SRB> return $handler->(do_c());
SRB> }
SRB> }
>>
>> better yet, use a dispatch table. i hate elsif's and try to never use
>> them. they are a marker for poor logic. hell, i eschew else as well. in
>> over 10k lines in one project i had about 3 elsif's and 11 else's. and
>> the code is very readable. it is just done with very clean logic and
>> code flow.


SRB> Definitely =) Conditionals were mostly just fodder for the sake of
SRB> the anonymous sub (which was the major point). Mostly I use this kind
SRB> of thing for failure routines:
SRB> if (my $result = try_something()) {
SRB> handle_success($result);
SRB> } elsif (my $result = try_fallback()) {
SRB> handle_succesS($result);
SRB> }
SRB> and so on ... I don't really have a good paradigm for that kind of
SRB> thing that would involve a dispatch table though (is there one?).

you can still drop the elsif and make them if's if the handlers are done
and you need to exit. that alone makes for a better coding style.

as for that try/handle stuff, if it is as regular as you show, then a
simple table/loop will do it better:

my @try_subs = ( \&try_foo, \&try_bar, ... ) ;

foreach my $try ( @try_subs ) {

my $result = $try->() ;
next unless $result ;

handle_success( $result ) ;
last ;
}

nary an else or elsif in the code!

thanx,

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Jochen Lehmeier
Guest
Posts: n/a
 
      12-14-2009
On Mon, 14 Dec 2009 19:46:14 +0100, Uri Guttman <(E-Mail Removed)>
wrote:

> in over 10k lines in one project i had about 3 elsif's and 11 else's.


I understand your trouble with elsif (well, at least I can think of cases
where elsif may not be optimal).

But "else"? How could "else" possibly be a sign of bad logic?
 
Reply With Quote
 
Jochen Lehmeier
Guest
Posts: n/a
 
      12-14-2009
On Mon, 14 Dec 2009 22:04:27 +0100, Uri Guttman <(E-Mail Removed)>
wrote:

> SRB> if (my $result = try_something()) {
> SRB> handle_success($result);
> SRB> } elsif (my $result = try_fallback()) {
> SRB> handle_succesS($result);
> SRB> }


> my @try_subs = ( \&try_foo, \&try_bar, ... ) ;
>
> foreach my $try ( @try_subs ) {
>
> my $result = $try->() ;
> next unless $result ;
>
> handle_success( $result ) ;
> last ;
> }
>
> nary an else or elsif in the code!


I guess if we would work in a team, we would regularly have heated
discussions on things like this. Replacing a standard, efficient, easy to
parse (mentally), absolutely normal coding style with a rather convoluted
one, just for the abstract goal of avoiding "else" and "elsif" (*)...
well, I have no useful, public-compatible comment really.

Besids, your pattern breaks down as soon as your functions take different
arguments, or your handle_success() differ from each other, though I guess
you could work around that with closures too, if you wanted.

Note, I do not recall that the OP mentioned lots and lots of elsif's -
only 2 or maybe 3. For larger numbers of cases, and especially when
re-used, this pattern might be kind of useful, but not for simple cases
like this, and not just for getting rid of els(e|if).

Aside from that,

my $result = try_something() || try_fallback();
handle_success($result) if $result;

would be the Perl-like variant I'd use (or straigtforward "elsif", just
like SRB), which scales perfectly to large numbers of try_()'s if you
insert line breaks in strategical places.
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      12-14-2009
>>>>> "JL" == Jochen Lehmeier <(E-Mail Removed)> writes:

JL> On Mon, 14 Dec 2009 19:46:14 +0100, Uri Guttman <(E-Mail Removed)>
JL> wrote:

>> in over 10k lines in one project i had about 3 elsif's and 11 else's.


JL> I understand your trouble with elsif (well, at least I can think of
JL> cases where elsif may not be optimal).

JL> But "else"? How could "else" possibly be a sign of bad logic?

not a sign of bad logic but of inefficient logic in perl.

my favorite counter example is this style which is all too common:

you enter a sub and have a validity check for something and then you do
the work if the data is ok:

if ( valid() ) {

do lots of code here
}
else {
return -1 ;
}

return $result ;

vs my style:

return -1 unless valid() ;

lots of code
return $result ;


look ma, no else!! no else is needed!! it is shorter, no extra block
entries, no extra indent, no wasted pixels for the {} chars!

you do your checking and get out immediately if bad. then the main good
work is done inline and not in an indented block. perl allows and
encourages this style with statement modifiers and good flow control
ops.

there are many variations on that style but they all eschew else
statements. you just don't need them that often in good perl. most of
the time elses are used for error cases. other times a conditional
expression is better (that is another commonly abused thing, else's
assigning to the same var as the then clause). if you show me code with
lots of else's i can usually rewrite it better without them.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Jochen Lehmeier
Guest
Posts: n/a
 
      12-14-2009
On Mon, 14 Dec 2009 22:51:18 +0100, Uri Guttman <(E-Mail Removed)>
wrote:

> not a sign of bad logic but of inefficient logic in perl.


Define "bad", define "inefficient". Try to avoid the term "logic" please,
it is much too big in this context, c/f http://en.wikipedia.org/wiki/Logic.

> you enter a sub and have a validity check for something and then you do
> the work if the data is ok:
>
> if ( valid() ) {
>
> do lots of code here
> }
> else {
> return -1 ;
> }
>
> return $result ;
>
> vs my style:
>
> return -1 unless valid() ;
>
> lots of code
> return $result ;


> look ma, no else!! no else is needed!!


Well, this is completely different code from what we talked about before,
and you didn't mention my remarks on the original topic at all (Logical
Fallacy: Irrelevant Conclusion). Of course your second code is shorter
than the longer code up there (and I've written enough fragements closer
to your second than your first), but I still fail to see how this is so
specifically *because* there is no "else" (Logical Fallacies: Affirming
the Consequent, Denying the Antecedent, and maybe Non Sequitur). And while
I am with you in that your second code is better than the first, you still
have to convince me that your second code is "better" than (just to name
an example)

my $result=-1;
if (valid())
{
lots of code
}
return $result;

You seem to be very focused on "else". I still fail to see why. There are
many ways to write code with or without "else", all with different
lengths, your measurement of code simply seems to consist of the number of
bytes and number of "else"s.

> you do your checking and get out immediately if bad. then the main good
> work is done inline and not in an indented block. perl allows and
> encourages this style with statement modifiers and good flow control
> ops.


Yes, yes, but go back to the original topic please - very different stuff
back there (Logical Fallacy: Fallacy of Many Questions or Loaded Question)

> there are many variations on that style but they all eschew else
> statements. you just don't need them that often in good perl.[...]
> if you show me code with
> lots of else's i can usually rewrite it better without them.


For your definition of "better".

The reason I reply here and try to argue with you is that you make "else"
out to be totally bad and evil, like someone saying "goto is evil" (the
latter being true ). I would hate for some Perl newcomer to grow up
with FUD or hearsay like this. Saying "a rather short than long coding
style, getting out of subs ASAP" is perfectly fine with me. But saying
"avoid else at all costs" is not.

You are correct in saying that there is the long-winded coding style of
people who are not familiar with the usual Perl idioms which can be used
to make Perl code short. But there is nothing at all specifically pointing
to "else" in that reasoning. And it is absolutely not true that in all
circumstances the shorter code is "better".

Besides, consider: you suggest to work a lot with "return" or "last"
mingled in between other statements. This is one thing which surely leads
to shorter code, but also leads very quickly to code which is much harder
to maintain, since it gets harder to see the flow of execution at a
glance. I.e., if I have a sub that does *not* contain any "return" or
"last", then I can be absolutely sure that the flow of execution will, at
some point, arrive at the end of the method; and I can be absolutely sure
that I can add code there that will be executed after everything else in
that sub (for example, something which modifies, logs or validates the
return code). With frequent "return" and "last", this gets harder. (Yes, I
am purposefully ignoring "die" here).

There are is also the Theory of Computation, which, for example, concerns
itself with proofs of correctness. In those areas, if/else is often *much*
easier to work with than return/last.

Check out LISP, just to broaden the horizon. The language does not even
have the concept of "return" or "last" at all, and heavily uses "else".
But it's still *very* logical, indeed.

PS: Sorry for the OT Logic stuff, folks.
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      12-14-2009
>>>>> "JL" == Jochen Lehmeier <(E-Mail Removed)> writes:

JL> On Mon, 14 Dec 2009 22:51:18 +0100, Uri Guttman <(E-Mail Removed)>
JL> wrote:

>> not a sign of bad logic but of inefficient logic in perl.


JL> Define "bad", define "inefficient". Try to avoid the term "logic"
JL> please, it is much too big in this context, c/f
JL> http://en.wikipedia.org/wiki/Logic.

i use logic as in the decisions made in flow control. those are all
logical choices. it is a fine term for this.

>> you enter a sub and have a validity check for something and then you do
>> the work if the data is ok:
>>
>> if ( valid() ) {
>>
>> do lots of code here
>> }
>> else {
>> return -1 ;
>> }
>>
>> return $result ;
>>
>> vs my style:
>>
>> return -1 unless valid() ;
>>
>> lots of code
>> return $result ;


>> look ma, no else!! no else is needed!!


JL> Well, this is completely different code from what we talked about
JL> before, and you didn't mention my remarks on the original topic at
JL> all (Logical Fallacy: Irrelevant Conclusion). Of course your second
JL> code is shorter than the longer code up there (and I've written
JL> enough fragements closer to your second than your first), but I still
JL> fail to see how this is so specifically *because* there is no "else"
JL> (Logical Fallacies: Affirming the Consequent, Denying the Antecedent,
JL> and maybe Non Sequitur). And while I am with you in that your second
JL> code is better than the first, you still have to convince me that
JL> your second code is "better" than (just to name an example)

it is faster as in no block entry which costs you in perl.

it is shorter so it is easier to read on a screen

it is simpler as you don't need to check inside blocks for what is
happening and where.

easier to follow the MAIN logic which doing the work as you already
handled the easy error exit case. no worries about what ELSE should be
done as there is no else clause.

one less indent makes it easier to read and you can use longer lines
with fewer wrapped lines. that also makes the code shorter and easier to read.

is that enough to qualify it as BETTER code? 5 good reasons with others
i can scrounge up if needed.

JL> my $result=-1;
JL> if (valid())
JL> {
JL> lots of code
JL> }
JL> return $result;

JL> You seem to be very focused on "else". I still fail to see why. There
JL> are many ways to write code with or without "else", all with
JL> different lengths, your measurement of code simply seems to consist
JL> of the number of bytes and number of "else"s.

i don't focus on else. i just easily code away from it. it takes zero
effort for me to do it and it generates better code by the above
reasons. it is the coding style i teach for perl and it usually wins
over most who learn it.


>> you do your checking and get out immediately if bad. then the main good
>> work is done inline and not in an indented block. perl allows and
>> encourages this style with statement modifiers and good flow control
>> ops.


JL> Yes, yes, but go back to the original topic please - very different
JL> stuff back there (Logical Fallacy: Fallacy of Many Questions or
JL> Loaded Question)

huh?? we are talking a minimal change in style to lower the else count
and make better code. there is no loaded question nor fallacy here. it
is a proven style improvement. simple and effective.

>> there are many variations on that style but they all eschew else
>> statements. you just don't need them that often in good perl.[...]
>> if you show me code with
>> lots of else's i can usually rewrite it better without them.


JL> For your definition of "better".

and i get paid to judge code so my word has backing on this. i rate code
for recruitment and for code review projects. too many elses can always
be improved. it is just one of the many things i see which can be
improved. hell, my code can be improved. please do so. my cpan id is
URI. go for it and publish it here. if you show me better code, i will
use it gladly. but you have to also prove it to be better. i know i can
back up my code against weak attacks.

JL> The reason I reply here and try to argue with you is that you make
JL> "else" out to be totally bad and evil, like someone saying "goto
JL> is evil" (the latter being true ). I would hate for some Perl
JL> newcomer to grow up with FUD or hearsay like this. Saying "a
JL> rather short than long coding style, getting out of subs ASAP" is
JL> perfectly fine with me. But saying "avoid else at all costs" is
JL> not.

not evil, just not needed as often as it is commonly used. it is needed
but just rarely. i don't go out of my way to force no elses. i just can
do it naturally in perl. in other langs it wouldn't be as easy. this is
a perl style point, not a general thing against elses like with no gotos.

JL> You are correct in saying that there is the long-winded coding style
JL> of people who are not familiar with the usual Perl idioms which can
JL> be used to make Perl code short. But there is nothing at all
JL> specifically pointing to "else" in that reasoning. And it is
JL> absolutely not true that in all circumstances the shorter code is
JL> "better".

shorter code is generally better code given that it isn't forced into
obsfucation. there is a limit but so much code is long winded and can be
easily improved by shortening it.

JL> Besides, consider: you suggest to work a lot with "return" or "last"
JL> mingled in between other statements. This is one thing which surely
JL> leads to shorter code, but also leads very quickly to code which is
JL> much harder to maintain, since it gets harder to see the flow of
JL> execution at a glance. I.e., if I have a sub that does *not* contain
JL> any "return" or "last", then I can be absolutely sure that the flow
JL> of execution will, at some point, arrive at the end of the method;
JL> and I can be absolutely sure that I can add code there that will be
JL> executed after everything else in that sub (for example, something
JL> which modifies, logs or validates the return code). With frequent
JL> "return" and "last", this gets harder. (Yes, I am purposefully
JL> ignoring "die" here).

then your code is too complex. i keep things short and sweet and flow
control is everything in doing that.

JL> There are is also the Theory of Computation, which, for example,
JL> concerns itself with proofs of correctness. In those areas, if/else
JL> is often *much* easier to work with than return/last.

who cares about that when working in the real world?

JL> Check out LISP, just to broaden the horizon. The language does not
JL> even have the concept of "return" or "last" at all, and heavily uses
JL> "else". But it's still *very* logical, indeed.

lisp sucks donkey balls. and i know from plenty of experience in
it. lisp is for computers. perl is for people. your choice!

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      12-15-2009
>>>>> "DH" == David Harmon <(E-Mail Removed)> writes:

DH> On Mon, 14 Dec 2009 16:04:27 -0500 in comp.lang.perl.misc, "Uri Guttman"
DH> <(E-Mail Removed)> wrote,
>> my @try_subs = ( \&try_foo, \&try_bar, ... ) ;
>>
>> foreach my $try ( @try_subs ) {
>>
>> my $result = $try->() ;
>> next unless $result ;
>>
>> handle_success( $result ) ;
>> last ;
>> }
>>
>> nary an else or elsif in the code!


DH> my $result = try_foo()
DH> || try_bar()
DH> || ... ;

DH> handle_success( $result ) if $result;

and how would you handle undef values? or a list return there? undef can
be checked with // in 5.10 but lists can't be handled with ||. the loop
version can easily be modified to handle list returns.

also if you need to pass args to those subs it gets redundant to see
them in each call and noisy as well. the loop version keeps the calling
code simple and extendable while keeping the list of calls separate
where you can easily see and edit it.

this assumes a decent sized list of calls, not just 2 or 3 of them.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
passing filename path with spaces to subs news2003@wanadoo.es Perl Misc 6 03-24-2008 10:24 AM
params v.s. @params in rails? Barry Ruby 9 09-15-2005 03:12 AM
passing globals to imported module James Tauber Python 5 08-16-2004 08:57 PM
Globals vs passing in by reference hello smith C Programming 4 02-12-2004 01:49 AM
Re: circular dependencies & globals - avoid w/ precompiler directives?betterdesign suggestions? Suzanne Vogel C++ 2 06-26-2003 12:25 AM



Advertisments