formatting a number of elsif statements

C

ccc31807

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.
 
J

Jürgen Exner

ccc31807 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. [...]
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
 
C

ccc31807

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.

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

sln

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.

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
 
M

Martijn Lievaart

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

sln

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
 
C

ccc31807

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

sln

On Jul 6, 3:55 pm, (e-mail address removed) wrote:

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


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

sln

So there you have it, jump relative (with conditional) or jump absolute.
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
 
M

Martijn Lievaart

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

sln

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

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

sln

<snip>

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

-sln
 
M

Martijn Lievaart

<snip>

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

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

sln

<snip>

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

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

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
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top