pattern matching and abstract functions

C

ccc31807

Let's suppose you have a web app, and your HTML user interface
contains menu items like this:
<a href="site?menu=home">HOME</a>
<a href="site?menu=faq">FAQ</a>
<a href="site?menu=links">LINKS</a>
<a href="site?menu=contact">CONTACT US</a>

On the server side, you have code that looks like this (as STYLE A):
use CGI;
my $menu = param('menu');
if ($menu eq 'home') { do_this(); }
elsif ($menu eq 'faq') { do_that(); }
elsif ($menu eq 'links') { do_something_else(); }
elsif ($menu eq 'contact') { do_another_thing(); }
else { print "CGI ERROR, unknown $menu\n"; }

Some languages (Lisp and Erlang, for instance) have functions that are
conceptually overloaded and specialized according to their parameters.
For example, using a Perlish hypothetical language, you might do this
(as STYLE B):
do_this('home');
do_this('faq');
do_this('links');
do_this('contact');
do_this(_); # underscore represents an unknown value

Is there any way to specialize functions in Perl based on the value of
their parameters? The app is written in a procedural style, not OO,
and I'd like a way to introduce polymorphism without rewriting it as
an OO app.

The motivation for this question is an application that started with a
small number of elsif branches, and now has dozens of branches and has
become a nightmare to maintain. I have written a little script that
can change the source code from STYLE A to STYLE B but I haven't been
able to figure out a way to use Perl for Lisp-like specialization or
Erlang-like pattern matching.

Thanks, CC.
 
I

Ikram Kurdi

Let's suppose you have a web app, and your HTML user interface
contains menu items like this:
 <a href="site?menu=home">HOME</a>
 <a href="site?menu=faq">FAQ</a>
 <a href="site?menu=links">LINKS</a>
 <a href="site?menu=contact">CONTACT US</a>

On the server side, you have code that looks like this (as STYLE A):
use CGI;
my $menu = param('menu');
if ($menu eq 'home') { do_this(); }
elsif ($menu eq 'faq') { do_that(); }
elsif ($menu eq 'links') { do_something_else(); }
elsif ($menu eq 'contact') { do_another_thing(); }
else { print "CGI ERROR, unknown $menu\n"; }

Some languages (Lisp and Erlang, for instance) have functions that are
conceptually overloaded and specialized according to their parameters.
For example, using a Perlish hypothetical language, you might do this
(as STYLE B):
do_this('home');
do_this('faq');
do_this('links');
do_this('contact');
do_this(_); # underscore represents an unknown value

Is there any way to specialize functions in Perl based on the value of
their parameters? The app is written in a procedural style, not OO,
and I'd like a way to introduce polymorphism without rewriting it as
an OO app.

The motivation for this question is an application that started with a
small number of elsif branches, and now has dozens of branches and has
become a nightmare to maintain. I have written a little script that
can change the source code from STYLE A to STYLE B but I haven't been
able to figure out a way to use Perl for Lisp-like specialization or
Erlang-like pattern matching.

Thanks, CC.

Not sure if this is exactly what you want: You can do 'named
arguments' this way:
callSubroutine(arg1=>val,arg2=>val,arg3=>val);

Inside the subroutine you can put them inside a hash:
%h = @_;

Then check for the existence of keys:
if(exists($h{arg1})) { do this; }

or check the value of the keys:
if($h{arg1} = val) { do this; }

If you don't want to pass any values with the arguments, you can just
do this:
callSubroutine(arg1=>undef,arg2=>undef);

Again put @_ into a hash and check for the existence of keys with
'exists'.
 
U

Uri Guttman

c> On the server side, you have code that looks like this (as STYLE A):
c> use CGI;
c> my $menu = param('menu');
c> if ($menu eq 'home') { do_this(); }
c> elsif ($menu eq 'faq') { do_that(); }
c> elsif ($menu eq 'links') { do_something_else(); }
c> elsif ($menu eq 'contact') { do_another_thing(); }
c> else { print "CGI ERROR, unknown $menu\n"; }

c> Some languages (Lisp and Erlang, for instance) have functions that are
c> conceptually overloaded and specialized according to their parameters.
c> For example, using a Perlish hypothetical language, you might do this
c> (as STYLE B):
c> do_this('home');
c> do_this('faq');
c> do_this('links');
c> do_this('contact');
c> do_this(_); # underscore represents an unknown value

you are thinking about multiple dispatch and the key is the TYPE of the
variable is different, not the value. value is only a runtime thing and
so all langs would need some other way to determine how to handle each
value. in perl this is done via a dispatch table which is simply a hash
of values (e.g. 'home') to code refs (e.g. \&do_this_home). this has
been discussed many times here so google for more about them.

uri
 
C

ccc31807

my %action = (
    home    => \&do_this,
    faq     => \&do_that,
    links   => \&do_something_else,
    contact => \&do_another_thing,
);

I haven't tried this yet, so this may be off, but it looks like you
have constructed a hash with keys matching the value of the parameter
containing the user selected value (e.g., home, faq, etc.), and a
reference to the function to be triggered according to the value of
the key.

I can deal with this, but it will require me to think of a name for
each function ... not too difficult since I can use the value of the
parameter (like menu, faq, etc.). However, I was really looking for
something that triggered on the value of the parameter itself.

The only other thing, that I didn't mention, is that this is an
interface for a database, and we potentially have 20 or 30 variables
coming in (to insert a person into PERSON, for example). I'm using
lexical variables for these values, and this has never been a problem.
The functions call DBI functions and pass in the action (select,
insert, update, delete) and the relevant data, and I don't see any
need whatsoever to make any change in that code.

Thanks, CC.
 
U

Uri Guttman

c> I haven't tried this yet, so this may be off, but it looks like you
c> have constructed a hash with keys matching the value of the parameter
c> containing the user selected value (e.g., home, faq, etc.), and a
c> reference to the function to be triggered according to the value of
c> the key.

c> I can deal with this, but it will require me to think of a name for
c> each function ... not too difficult since I can use the value of the
c> parameter (like menu, faq, etc.). However, I was really looking for
c> something that triggered on the value of the parameter itself.

that *IS* triggered on the value itself. even if you could do what you
imagine you want you would still need a way to distinguish what code
handles what input. your way delays the handling until later but without
such a dispatch table you still need an if/else tree or a switch
statement. this is true even for languages with multiple dispatch, you
have to declare a sub for each type (again TYPE not value) of input. you
can't hide the decision tree under the carpet. somewhere you need to
look at the different input values and do different things. doing it
early in a dispatch table is the easiest, cleanest, fastest and most
idiomatic way in perl. it is done all over the place and you need to
learn how to use them.

c> The only other thing, that I didn't mention, is that this is an
c> interface for a database, and we potentially have 20 or 30 variables
c> coming in (to insert a person into PERSON, for example). I'm using
c> lexical variables for these values, and this has never been a problem.
c> The functions call DBI functions and pass in the action (select,
c> insert, update, delete) and the relevant data, and I don't see any
c> need whatsoever to make any change in that code.

so? you can call any sub via a dispatch table. you can even pass in
extra args or whatever in the calling call. the main idea is just using
a key (your input value NOT TYPE) to decide which sub to call. i said
google for many discussion on dispatch tables over many years.

uri
 
W

Willem

ccc31807 wrote:
) Let's suppose you have a web app, and your HTML user interface
) contains menu items like this:
) <a href="site?menu=home">HOME</a>
) <a href="site?menu=faq">FAQ</a>
) <a href="site?menu=links">LINKS</a>
) <a href="site?menu=contact">CONTACT US</a>
)
) On the server side, you have code that looks like this (as STYLE A):
) use CGI;
) my $menu = param('menu');
) if ($menu eq 'home') { do_this(); }
) elsif ($menu eq 'faq') { do_that(); }
) elsif ($menu eq 'links') { do_something_else(); }
) elsif ($menu eq 'contact') { do_another_thing(); }
) else { print "CGI ERROR, unknown $menu\n"; }
)
) Some languages (Lisp and Erlang, for instance) have functions that are
) conceptually overloaded and specialized according to their parameters.
) For example, using a Perlish hypothetical language, you might do this
) (as STYLE B):
) do_this('home');
) do_this('faq');
) do_this('links');
) do_this('contact');
) do_this(_); # underscore represents an unknown value

Could you give a *complete* example of how the function declaration
of do_this would look in Lisp or Erlang ?

) Is there any way to specialize functions in Perl based on the value of
) their parameters? The app is written in a procedural style, not OO,
) and I'd like a way to introduce polymorphism without rewriting it as
) an OO app.

You can do this:

use do_this;
my $menu = param('menu');
do_this->$menu();

And then have functions in the do_this package named for each menu.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
C

ccc31807

so? you can call any sub via a dispatch table. you can even pass in
extra args or whatever in the calling call. the main idea is just using
a key (your input value NOT TYPE) to decide which sub to call. i said
google for many discussion on dispatch tables over many years.

I was really, really looking for something like Erlang type multi
functions, where you can do the following:

cost(orange) -> 4;
cost(apple) -> 5;
cost(banana) -> 6;
cost(apple) -> 7;
cost(_) -> unknown.

If you call cost(X), you get the cost of X -- simple, straight
forward pattern matching, and it doesn't matter whether X is an apple,
orange, or anything else.

Yes, I know that different languages are optimized for different
things. They say about Erlang that it makes hard things easy and easy
things hard, and I can vouch for the truth of that from hard won
personal experience.

Unfortunately, I don't know enough about language construction in
general, or Perl in particular, to understand how something like this
could work in Perl, but I'm happy with the dispatch table syntax. Now,
I'm going to play with it so I'll probably be tied up for most of the
rest of the day ... and besides ... I've also got to do some few
little things for my employer so he won't have an excuse to fire
me. ;-)

CC.
 
W

Willem

ccc31807 wrote:
)> so? you can call any sub via a dispatch table. you can even pass in
)> extra args or whatever in the calling call. the main idea is just using
)> a key (your input value NOT TYPE) to decide which sub to call. i said
)> google for many discussion on dispatch tables over many years.
)
) I was really, really looking for something like Erlang type multi
) functions, where you can do the following:
)
) cost(orange) -> 4;
) cost(apple) -> 5;
) cost(banana) -> 6;
) cost(apple) -> 7;
) cost(_) -> unknown.

Why are you trying to shoehorn Erlang-specific language constructs into
other languages ? The above is not in any way better than any of the ways
it can be done in Perl or any other language.

) Yes, I know that different languages are optimized for different
) things. They say about Erlang that it makes hard things easy and easy
) things hard, and I can vouch for the truth of that from hard won
) personal experience.

Except that it is *not easier* to do this the Erlang way, except
for you because you happen to be used to doing it like that.


But, if you really really want to, I'm sure that Perl can be taught to
do it almost exactly like the above.

There are ways to hook into the language parser so that you
can add extra constructs, and basides that, you could probably
come quite close by tie-ing a hash or something.

This should work:

tie %cost, tiefunction;

my $x = 1;
$cost{orange} = sub { 4 };
$cost{apple} = sub { 5 };
$cost{banana} = sub { $x++ };
$cost{apple} = sub { 7 };

say $cost{banana}; # 1
say $cost{apple}; # 7
say $cost{banana}; # 2
say $cost{pear}; # undef

package tiefunction; # Left as an exercise to the reader.
# In other words: I'm too lazy.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
U

Uri Guttman

c> I was really, really looking for something like Erlang type multi
c> functions, where you can do the following:

c> cost(orange) -> 4;
c> cost(apple) -> 5;
c> cost(banana) -> 6;
c> cost(apple) -> 7;
c> cost(_) -> unknown.

and that is a dispatch table with a different syntax. also it seems your
code example is really a hash as the values are just constants.

c> If you call cost(X), you get the cost of X -- simple, straight
c> forward pattern matching, and it doesn't matter whether X is an apple,
c> orange, or anything else.

it isn't calling different code based upon the input, it is just looking
up values. in perl that is just a hash.

c> Unfortunately, I don't know enough about language construction in
c> general, or Perl in particular, to understand how something like this
c> could work in Perl, but I'm happy with the dispatch table syntax. Now,
c> I'm going to play with it so I'll probably be tied up for most of the
c> rest of the day ... and besides ... I've also got to do some few
c> little things for my employer so he won't have an excuse to fire
c> me. ;-)

a dispatch table is easy, fast and very flexible. it is what you want.

uri
 
C

ccc31807

  c> cost(orange) -> 4;
  c> cost(apple) -> 5;
  c> cost(banana) -> 6;
  c> cost(apple) -> 7;
  c> cost(_) -> unknown.

and that is a dispatch table with a different syntax. also it seems your
code example is really a hash as the values are just constants.

Uri, the integers above (4, 5, 6, an 7) are just the return values
from the function. Erlang is a functional language, and it doesn't
matter if the return values are symbols, primitives, constants,
variable values, return values from named functions, or return values
from lambda functions.

I'm not complaining, or touting one language as opposed to another,
just pointing out differences. There's a reason I use Perl for 95% of
my programming tasks, and it's because it's suited to the tasks I need
to do.

Yes, I like Erlang style multi functions, but Erlang doesn't have a
string data type, and it's really hard to do Perl style string
manipulation if you don't have a string data type. It's not a crime to
like a nifty feature of some language and wish your own workhorse
language had that feature.

Besides, the Perl style dispatch table will do what I want, so take my
word for it that I'm not complaining or dissing Perl in any way.

CC.
 
U

Uri Guttman

c> Uri, the integers above (4, 5, 6, an 7) are just the return values
c> from the function. Erlang is a functional language, and it doesn't
c> matter if the return values are symbols, primitives, constants,
c> variable values, return values from named functions, or return values
c> from lambda functions.

and your example reduces to a hash. that is all that matters here. a
hash that has code references is the same as erlang returning named or
lambda functions. it is the SAME CONCEPT in about the same amount of
code. no lang has a magic way to do dispatch tables as you always need a
map of keys to subs. the syntax varies but the required data is the
same.


c> Besides, the Perl style dispatch table will do what I want, so take my
c> word for it that I'm not complaining or dissing Perl in any way.

then just learn perl dispatch tables already and stop this thread.

uri
 
C

Charlton Wilbur

cc> If you call cost(X), you get the cost of X -- simple, straight
cc> forward pattern matching, and it doesn't matter whether X is an
cc> apple, orange, or anything else.

Congratulations, you've just reinvented parametric polymorphism.

The syntactic sugar for that in Perl is $x->cost;

Its implementation is left as an exercise for the reader.

Charlton
 
C

ccc31807

Congratulations, you've just reinvented parametric polymorphism.

I may be dead wrong, but I've always understood polymorphism to depend
on the TYPE of the parameter, rather than the value of the parameter.

In Prolog, the function parameters are pattern matched as to the
value, yet I've never heard anyone say that Prolog functions are
polymorphic. Same is true in Erlang, which is a direct descendant of
Prolog.

Lisp has generic functions which are specialized on the parameter
TYPE, rather than value, but in my case, all the parameters are of the
same TYPE -- it's the value that differs and it's the value that I
want to key on.

Dispatch tables work fine. Looking back in HOP, MJD discusses them
early on, but I had never used them and had forgotten about them.

CC.
 

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,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top