Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

formatting a number of elsif statements

0 views
Skip to first unread message

ccc31807

unread,
Jul 5, 2009, 3:07:41 PM7/5/09
to
Using 5.8 in a web app, I have about 18 elsif statements which look
similar to this:

elsif ($action eq 'AddAttorney')
{
print qq(<h4>Add Attorney</h4>);
HTML::add_professional($oprid, $role, 'Attorney');
HTML::print_button('setup.cgi','Return To Setup',$oprid, $role);
}
elsif($action eq 'AddInsurer')
...

I now fact the prospect of adding some more, hopefully not many, but
I'm getting tired of looking at all of this.

Is there any way to mimic the case/switch statement? Ideally, I'd like
to have just the matching term for each block, like this:

'AddAttorney'
print qq(<h4>Add Attorney</h4>);
HTML::add_professional($oprid, $role, 'Attorney');
HTML::print_button('setup.cgi','Return To Setup',$oprid, $role);
'AddInsurer'
...

It's not critical, but I'm just getting tired of looking at all the
repetition.

CC.

Tony Curtis

unread,
Jul 5, 2009, 3:14:40 PM7/5/09
to
>> On Sun, 5 Jul 2009 12:07:41 -0700 (PDT),
>> ccc31807 <cart...@gmail.com> said:

> Using 5.8 in a web app, I have about 18 elsif statements
> which look similar to this:

> elsif ($action eq 'AddAttorney') { print qq(<h4>Add
> Attorney</h4>); HTML::add_professional($oprid, $role,
> 'Attorney'); HTML::print_button('setup.cgi','Return To
> Setup',$oprid, $role);
> }
> elsif($action eq 'AddInsurer') ...

> I now fact the prospect of adding some more, hopefully
> not many, but I'm getting tired of looking at all of
> this.

> Is there any way to mimic the case/switch statement?
> Ideally, I'd like to have just the matching term for
> each block, like this:

If each block of code is the same, you could use a hash
table to map all of the labels you want to match to the
replacement text in the HTML. If the key's defined,
output the text with the replaced label (e.g. AddAttorney
-> "Attorney").

If it's more heterogeneous hie thee to
http://search.cpan.org/ and see what "switch" gets you...

hth
t

Ben Morrow

unread,
Jul 5, 2009, 4:00:57 PM7/5/09
to

Quoth Tony Curtis <tony_c...@yahoo.com>:

> >> On Sun, 5 Jul 2009 12:07:41 -0700 (PDT),
> >> ccc31807 <cart...@gmail.com> said:
>
> > Using 5.8 in a web app, I have about 18 elsif statements
> > which look similar to this:
>
> > elsif ($action eq 'AddAttorney') { print qq(<h4>Add
> > Attorney</h4>); HTML::add_professional($oprid, $role,
> > 'Attorney'); HTML::print_button('setup.cgi','Return To
> > Setup',$oprid, $role);
> > }
> > elsif($action eq 'AddInsurer') ...
>
> > I now fact the prospect of adding some more, hopefully
> > not many, but I'm getting tired of looking at all of
> > this.
>
> > Is there any way to mimic the case/switch statement?
> > Ideally, I'd like to have just the matching term for
> > each block, like this:
>
> If each block of code is the same, you could use a hash
> table to map all of the labels you want to match to the
> replacement text in the HTML. If the key's defined,
> output the text with the replaced label (e.g. AddAttorney
> -> "Attorney").

That's a good suggestion. Another might be to use a hash table of
subrefs, like

my %dispatch = (
AddAttorney => sub {

print qq(<h4>Add Attorney</h4>);
HTML::add_professional($oprid, $role, 'Attorney');
HTML::print_button('setup.cgi','Return To Setup',
$oprid, $role);

},
AddInsurer => sub { ... },
);

$dispatch{$action}();

or even a class with a method for each action.

> If it's more heterogeneous hie thee to
> http://search.cpan.org/ and see what "switch" gets you...

Nonono, don't do that! Switch.pm was Not A Good Idea. It uses a source
filter built on Text::Balanced to do its work, and there are more than a
few constructions that cause it to parse your source incorrectly. The
resulting errors are very hard to track down.

If you can afford to require 5.10, you can use given/when.

Ben

Tony Curtis

unread,
Jul 5, 2009, 4:25:04 PM7/5/09
to
>> On Sun, 5 Jul 2009 21:00:57 +0100,
>> Ben Morrow <b...@morrow.me.uk> said:

> Nonono, don't do that! Switch.pm was Not A Good Idea. It
> uses a source filter built on Text::Balanced to do its
> work, and there are more than a few constructions that
> cause it to parse your source incorrectly. The resulting
> errors are very hard to track down.

Oh. Didn't know that. Actually I've never used it myself
so I wasn't aware of any shortcomings.

The data->dispatch approach is more aesthetically pleasing
anyway.

t

J�rgen Exner

unread,
Jul 5, 2009, 4:25:26 PM7/5/09
to
ccc31807 <cart...@gmail.com> wrote:
>Using 5.8 in a web app, I have about 18 elsif statements which look
>similar to this:
>
>elsif ($action eq 'AddAttorney')
>{
> print qq(<h4>Add Attorney</h4>);
> HTML::add_professional($oprid, $role, 'Attorney');
> HTML::print_button('setup.cgi','Return To Setup',$oprid, $role);
>}
>elsif($action eq 'AddInsurer')
>...
>
>I now fact the prospect of adding some more, hopefully not many, but
>I'm getting tired of looking at all of this.
[...]

>It's not critical, but I'm just getting tired of looking at all the
>repetition.

Yeah, repetition is what computers are good at.

Step 1: identify which pieces of your repetitions are constant and which
pieces change. I can only guess but it appears like

print qq(<h4>Add #####</h4>);
HTML::add_professional($oprid, $role, '#####');


HTML::print_button('setup.cgi','Return To Setup',$oprid, $role);

is the constant part with the variable/changing part blocked out by
#####.

Step 2: Find a way to compute the variable parts from a suitable
parameter. In this case you got $action as the parameter and you want to
map it into a simple string. A hash is an ideal and very simple
datastructure for that.

my %param= {'AddAttorney' -> 'Attorney',
'AddInsurer' -> 'Insurer',
.....
}

Step 3: Replace the placeholder for the variable part ##### with actual
parameterized code that retrieves the variable part at runtime:

print qq(<h4>Add $param{$action}</h4>);
HTML::add_professional($oprid, $role, $param{$action});


HTML::print_button('setup.cgi','Return To Setup',$oprid, $role);

That should do it.

jue


ccc31807

unread,
Jul 5, 2009, 6:27:37 PM7/5/09
to
Thanks, Ben.

I went ahead and bit the bullet.

I wrote a function that takes, among other arguments, an entity type
and an action type, so now I just call one procedure. It did require a
translation table as you suggested (which I hard coded for now but
will probably put into a database), but that's a lot easier on the
eyes than a couple hundred lines of elsif statements.

As a bonus, I am able to abstract my SQL as well. In my code, I have
procedures to:
- add
- insert
- view all
- view one
- edit
- update
- delete

for a dozen different categories, Insurers, Employers, Attorneys,
Agents, etc. It started out pretty small, but man, scaling becomes an
issue when different people start adding their wants to the list!
Saying, 'Yes, I can do a little app to track the players,' turns into
a Sunday at the keyboard when the office gets a crack at it.

On Jul 5, 4:00 pm, Ben Morrow <b...@morrow.me.uk> wrote:
> That's a good suggestion. Another might be to use a hash table of
> subrefs, like
>
>     my %dispatch = (
>         AddAttorney => sub {
>             print qq(<h4>Add Attorney</h4>);
>             HTML::add_professional($oprid, $role, 'Attorney');
>             HTML::print_button('setup.cgi','Return To Setup',
>                 $oprid, $role);
>         },
>         AddInsurer => sub { ... },
>     );
>
>     $dispatch{$action}();
>
> or even a class with a method for each action.

One of these days, I'm going to learn OO Perl. I've got two books on
my reading list, 'Object Oriented Perl' and 'Higher Order Perl', but
I've never been able timewise to do more than just browse through
them.

Thanks for your suggestion.

CC

s...@netherlands.com

unread,
Jul 6, 2009, 3:55:43 PM7/6/09
to

I haven't read any other reply's but I would bet there is that
switch/case mimic in Perl 5.10

Since you bring up the C switch/case construct, lets talk about
what that really is and how much you should really worry about it.

Forgetting languages except assembly for the moment. How many branch
instructions do you think there are, and how many language intrinsics
do you think you can make with them?

Lets get at least a little bit real. Case/Switch was added to C for only one
reason, as a pass through when conditions overlapp. It still uses the basic
assembly branches but it is still a compound.

Looks are in the eye of the beholder. You obviously never programmed in assembly.

-sln

Martijn Lievaart

unread,
Jul 6, 2009, 4:27:27 PM7/6/09
to
On Mon, 06 Jul 2009 12:55:43 -0700, sln wrote:

> Lets get at least a little bit real. Case/Switch was added to C for only
> one reason, as a pass through when conditions overlapp. It still uses
> the basic assembly branches but it is still a compound.

Another reason is that it can often be implemented using a branch table.

>
> Looks are in the eye of the beholder. You obviously never programmed in
> assembly.
>

And obviously, you didn't look enough at disassembled C. :-)

M4

s...@netherlands.com

unread,
Jul 6, 2009, 4:32:51 PM7/6/09
to
On Mon, 6 Jul 2009 22:27:27 +0200, Martijn Lievaart <m...@rtij.nl.invlalid> wrote:

>On Mon, 06 Jul 2009 12:55:43 -0700, sln wrote:
>
>> Lets get at least a little bit real. Case/Switch was added to C for only
>> one reason, as a pass through when conditions overlapp. It still uses
>> the basic assembly branches but it is still a compound.
>
>Another reason is that it can often be implemented using a branch table.
>

[snip]
>
>M4

I'm sorry, I missed that branch table instruction in the op code list (rst?).
Perhaps you should dissasemble your assembler.

-sln

ccc31807

unread,
Jul 6, 2009, 5:03:06 PM7/6/09
to
On Jul 6, 3:55 pm, s...@netherlands.com wrote:
> I haven't read any other reply's but I would bet there is that
> switch/case mimic in Perl 5.10

Yes.

> Forgetting languages except assembly for the moment. How many branch
> instructions do you think there are, and how many language intrinsics
> do you think you can make with them?

As you say, looks are in the eye of the beholder. In this case, you
can see the logic in two ways. The first way is how I started out, by
switching based on the type (Agent, Attorney, Employer, etc) and task
(insert, update, delete, select). The second way is how I ended up, in
a more OO style, trashing all the branches and replacing them with a
generic function, like this:
$hashref = do_it($type, $task);

> Lets get at least a little bit real. Case/Switch was added to C for only one
> reason, as a pass through when conditions overlapp. It still uses the basic
> assembly branches but it is still a compound.

I don't know about that. I had six months of assembly years ago and
can't remember much about it.

> Looks are in the eye of the beholder. You obviously never programmed in assembly.

Yes, and yes.

CC

s...@netherlands.com

unread,
Jul 6, 2009, 5:27:17 PM7/6/09
to
On Mon, 6 Jul 2009 14:03:06 -0700 (PDT), ccc31807 <cart...@gmail.com> wrote:

>On Jul 6, 3:55�pm, s...@netherlands.com wrote:

<snip>


>> Lets get at least a little bit real. Case/Switch was added to C for only one
>> reason, as a pass through when conditions overlapp. It still uses the basic
>> assembly branches but it is still a compound.
>
>I don't know about that. I had six months of assembly years ago and
>can't remember much about it.
>
>> Looks are in the eye of the beholder. You obviously never programmed in assembly.
>
>Yes, and yes.
>
>CC

I started out doing assembly on the z80a actually, before assemblers. Did alot of
hand written code (to be machine input later), later looked at all the 8080/286/386/486,
and assemblers (Intel mostly), then reviewed the Motorolla, then some other cpu's, which
were almost identical in basic functionality.

There is only jump relative and its conditional flavors, or jump absolute, and restart (rst)
which is a table absolute jump commonly used to boot (absolute code) systems or in response
to intterrupts (hardware reset), not used by languages.

So there you have it, jump relative (with conditional) or jump absolute.

Remember any of that?

-sln

s...@netherlands.com

unread,
Jul 6, 2009, 6:52:50 PM7/6/09
to

Iiether can be conditional (relative or absolute).
I just never found the TABLE op code, u know. Assemblers have indirection
with locations, but the raw code is jumps, assemblers just embelish and translate
to simple op jumps. There is no construct more complex to the cpu no matter what
you think.

This is a prime example of learning before leaping.

-sln

Martijn Lievaart

unread,
Jul 9, 2009, 1:18:09 AM7/9/09
to
On Mon, 06 Jul 2009 13:32:51 -0700, sln wrote:

>>Another reason is that it can often be implemented using a branch table.
>>
> [snip]
>>
>>M4
>
> I'm sorry, I missed that branch table instruction in the op code list
> (rst?). Perhaps you should dissasemble your assembler.

It's called an indirect jump. Sorry, but you really should take some
education here, these are rather basic concepts.

M4

s...@netherlands.com

unread,
Jul 9, 2009, 5:39:54 PM7/9/09
to

I don't know if there is an indirect jump op code. The accumulator may contain
an address, and there may be a jump to where it points. Any kind of indirection
involves a 2-step loading of a fixed address into a register, getting its contents
then loading it into another register (with a possible addition).

Jumping to a fixed location is more than four times quicker, as is the case of
if/then/else.

I'm sorry, machine cycles (if there is a relative jump op) don't change. The math
is still the same.

Back in the days of 'resident' dos programs it made a difference, today it still
makes a difference.

Surely, real-time.

-sln

s...@netherlands.com

unread,
Jul 9, 2009, 6:18:50 PM7/9/09
to
On Thu, 09 Jul 2009 14:39:54 -0700, s...@netherlands.com wrote:

>On Thu, 9 Jul 2009 07:18:09 +0200, Martijn Lievaart <m...@rtij.nl.invlalid> wrote:
>
>>On Mon, 06 Jul 2009 13:32:51 -0700, sln wrote:
>>
>>>>Another reason is that it can often be implemented using a branch table.
<snip>

It cannot be! Comparisons on each case must be made, there is no single leaf.

-sln

Martijn Lievaart

unread,
Jul 10, 2009, 4:32:35 PM7/10/09
to

It's rather simple, something like:

switch (x) {
case 1:
f1();
break;
case 2:
f2();
break;
.
.
.
case <n>:
f<n>;
break;
}

might be implemented (in pseudo assembler)

.data
label branchtable
Lcont
L1
L2
.
.
.
L<n>

.code

; value is in accumulator X

CMP X,<n>
JGT Lcont
JMP branchtable[x]
L1:
call f1
JMP Lcont
L2:
call f2
JMP Lcont
.
.
.
L<n>:
CALL f<n>
Lcont:

Again, this is pretty basic stuff, consult a good book on compilers.

M4

s...@netherlands.com

unread,
Jul 11, 2009, 7:29:59 PM7/11/09
to

Looks pretty basic. A single comparison of a value in a range (seemingly continuous)
that is the offset into a table (data) that hold the absolute jump addresses.

Its the going from here:
CMP X,<n>
to here:
JMP branchtable[x]

thats got me. I haven't done assembly in a long time, if I were paid to do it I would.
I do remember doing thousands and thousands of hand written machine code lines before assemblers.
Mostly 8-bit. Then some stuff with Masm 5.1 and eproms for a while. Mostly frogotten.

Thats why I look at your pseudo assembler and wonder if there is a hidden meaning in CMP X,<n>
the '<n>' especially. It might be benificial to view dissasembly (preferably after c2 pass)
to see if they actually invented some new 'op' code or something that would be a miracle and
shorten your assembly down to what appears to be really only a very few machine cycles.

So that this:

if (x == 1)
f1();
else
CMP X,1
JRNE 16
call f1
JMP Lcont
if (x == 2)
f2();
else
CMP X,2
JRNE 16
call f2
JMP Lcont
...
Lcont:

will forever be looked on as bad code as will this:

switch (x) {
case 1:
f1();

case 2:
case 109827:
fall();
break;
}

-sln

0 new messages