Work on Tie::Constrained has had me slinging around a lot of small anonymous subroutines. Many of those are composed of similar parts, joined by && or ||. I began wanting an easy way to crank out new subs from a small set of old.

In mathematics, operators like addition are defined on functions by their action on the values the functions return. For example, (sin + exp)(x) is sin(x) + exp(x). I got the notion of overloading the && and || ops for a class of blessed subroutines, so that $foo && $bar would return a blessed sub { &$foo && &$bar }.

You may have already noticed what's wrong with that idea. The && and || operators are not overloadable! I think I can understand why, too. The logical operators are used to test for success of a constructor. How could that work if $baz = FunkOpera->new(...) or die $! returned sub { $baz or die $!}?

Well, every idea has its ups and downs. The bitwise operators, & and | are conceptually similar to the logical ones, and they are overloadable. They can stand in for their logical counterparts. That is not ideal. The overloaded operators will be parsed by perl as the bitwise ops. There is no ultra-low precedence form of the bitwise ops. Those shortcomings may force heavier use of grouping parentheses than we're accustomed to. It's not perfect, but it will do.

So here it is, called for the moment FunkOpera.

#!/usr/bin/perl package FunkOpera; use overload '&' => sub { my ($l, $r, $f) = @_; bless $f ? sub {&{$r} && &{$l}} : sub {&{$l} && &{$r}} , __PACKAGE__ }, '|' => sub { my ($l, $r, $f) = @_; bless $f ? sub {&{$r} || &{$l}} : sub {&{$l} || &{$r}} , __PACKAGE__ }, '!' => sub { my ($fn) = @_; bless sub { ! &{$fn}}, __PACKAGE__ }; 1;
package main; my $foo = bless sub { $_[0] =~ /foo/ }, FunkOpera; my $bar = sub {"bar"}; my %funk; @funk{qw/foonbar foorbar barnfoo barrfoo/} = ($foo & $bar, $foo | $bar, $bar & $foo, $bar | $foo); for (keys %funk) { print qq($_("food") returns ), $funk{$_}->('food'}, $/; print qq($_("ford") returns ), $funk{$_}->('ford'}, $/; } __END__ foorbar("food") returns 1 foorbar("ford") returns bar barnfoo("food") returns 1 barnfoo("ford") returns foonbar("food") returns bar foonbar("ford") returns barrfoo("food") returns bar barrfoo("ford") returns bar
The old-timey calling convention with "&" sigil and no parens is intended. Both subs are to be called with the same arguments, so it is convenient to not alter @_ in the base functions and have the arguments brought in automatically.

It is only necessary that one sub in a simple expression is a FunkOpera. The rest is taken care of by overload.pm magic. The odd trinary construction in the overload subs for binary operators helps with that, as well as keeping argument order straight.

This works very well for arithmetic operators, too.

So, it's not perfect, but it does what I wanted.

After Compline,
Zaxo


In reply to FunkOpera: Abstracting Perl Operators by Zaxo

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.