Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

RFC: Junction.pm

by fireartist (Chaplain)
on May 02, 2005 at 13:34 UTC ( #453220=perlmeditation: print w/replies, xml ) Need Help??

Copied below is the docs from a module I've written: Junction.pm

It's inspired by the Junctions described in Perl6.

I'd appreciate any comments, including suitability of the module name, and whether it's lacking any features you think necessary, for the module to be useful.

NAME

Junction - Perl6 style Junction operators in Perl5.


SYNOPSIS

  my $j = Junction->new;
  
  if ($j->any(@grant) eq 'su') {
    ...
  }
  
  if ($j->all($foo, $bar) >= 10) {
    ...
  }
  
  if ($j->none(@pass) eq 'password') {
    ...
  }
  
  if ($j->one(@answer) == 42) {
    ...
  }
  
  # All methods can also be called on the Class Name
  
  if (Junction->one(@answer) == 42) {
    ...
  }


DESCRIPTION

Inspired by the Perl6 design docs, SEE ALSO.


METHODS

new()

Returns a stateless Junction object, on which you can call any of the methods listed below.

  my $j = Junction->new;
  
  $j->any;
  $j->all;

... which is provided as a short cut to typing:

  Junction->any;
  Junction->all;

all()

Returns an object which overloads the following operators:

  "<",  "<=", ">",  ">=", "==", "!=", 
  "lt", "le", "gt", "ge", "eq", "ne",

Returns true only if all arguments test true according to the operator used.

any()

Returns an object which overloads the following operators:

  "<",  "<=", ">",  ">=", "==", "!=", 
  "lt", "le", "gt", "ge", "eq", "ne",

Returns true if any argument tests true according to the operator used.

none()

Returns an object which overloads the following operators:

  "<",  "<=", ">",  ">=", "==", "!=", 
  "lt", "le", "gt", "ge", "eq", "ne",

Returns true only if no argument tests true according to the operator used.

one()

Returns an object which overloads the following operators:

  "<",  "<=", ">",  ">=", "==", "!=", 
  "lt", "le", "gt", "ge", "eq", "ne",

Returns true only if one and only one argument tests true according to the operator used.


EXPORT

None.


TO DO

Maybe allow the first argument to be a regex object, such that:

  $j->all( qr/\d+/, @input )

... matches all following arguments against the regex. Would need to figure out what to return and how/whether to handle captured values. (Suggestions welcome).


SUPPORT / BUGS

Submit to the CPAN bugtracker http://rt.cpan.org


SEE ALSO

http://dev.perl.org/perl6/doc/design/exe/E06.html - ``The Wonderful World of Junctions''.


AUTHOR

Carl Franks


COPYRIGHT AND LICENSE

Copyright 2005, Carl Franks. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself (perlgpl, perlartistic).

Replies are listed 'Best First'.
Re: RFC: Junction.pm
by dragonchild (Archbishop) on May 02, 2005 at 13:37 UTC
    What does this do that Quantum::Superpositions doesn't? (I know it's a lot of good syntactic sugar, but you need to elaborate on that in the POD.)

    The Perfect is the Enemy of the Good.

      I would imagine a simple operator overloading class would be far less of a beast than Q::S.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      What does this do that Quantum::Superpositions doesn't?

      Have a reasonable name (sorry, Damian).

      Thanks, I'll have to spend a while longer looking through the docs to figure out if it does what I want.

      I had searched cpan for 'junction', and got no results. Silly me, I should have known to search for Quantum Superpositions!

Re: RFC: Junction.pm
by Tanktalus (Canon) on May 02, 2005 at 14:40 UTC

    Just out of curiosity...

    if (all(5, 10, 15) > any (3, 8, 12, 20)) { print "Success!\n" }
    Does that work? :-) Also, I'm not sure if you can override =~, but that makes much more sense in perl5 land than allowing a regex or something as a parameter, as long as you're going about all this syntactical sugar anyway:
    if (all(@input) =~ /^\d+$/) { print "Got all whole numbers!\n" }
    looks much better than:
    if (all(qr/^\d+$/, @input)) { ... }
    Also, these don't make a lot of sense (to me, anyway) in OO format (and I'm an OO freak!). I'd expect more like:
    use Junction qw(any all); if (any(@list) > 0) { print "we have at least one postive number!\n"; +} if (all(@list) > 0) { print "even better - they're all positive number +s!\n"; }
    I'm not sure why you need that object anyway.

      Agreed, exporting the subs makes a lot more sense. I originally had only the object interface, because of the way it was built - it should have occured to me to use Exporter once that was no longer needed.

      if (all(5, 10, 15) > any (3, 8, 12, 20)) { print "Success!\n" }

      No, that doesn't work. I could make it work, but then it's starting to get into the complexity of Quantum::Superpositions (which I've still to fully read the docs of).

      Unfortunately, =~ can't be over-riden: that would be very nice. (And why Damian hasn't released Perl6::SmartMatch, I don't know ;)

      if (all(5, 10, 15) > any (3, 8, 12, 20)) { print "Success!\n" }

      Yes, it does work!
      I should have tested before I answered: I realised that of course it would work, as the operators the module used are still overloaded, even when being used inside the module.

      if (qr/^\d+$/ == all(@input)) { ... }

      The above now works. Note that you need to use a regex object qr// rather than just //, and you also need to use '==' or '!=', not '=~' or '!~'. It isn't ideal, but then you only need to use it if you want to!

      btw, I've uploaded this to CPAN as Perl6::Junction.

      update: changed the above link, as the cpan indexer hasn't picked it up yet, when you search by module name.

Re: RFC: Junction.pm
by fireartist (Chaplain) on May 02, 2005 at 20:44 UTC

    Hmm, I'm undecided about this. I've had a look over Quantum::Superpositions now, and it's got a lot of cool stuff in it. However, I see my approach as mostly syntactic sugar to replace things like:

    if ($param eq 'this' || $param eq 'that' || $param eq 'the other') { ... }
    with
    if ($param eq any('this', 'that', 'the other') { ... }
    which Quantum::Superpositions seems a bit overkill for.

    Taking a hint from hardburn above, I did some benchmarks (below) and there is a significant runtime difference, between using my code and Quantum::Superpositions'.

    One feature from Quantum::Superpositions that I think would be worth adding, is

    $result = any(1,2,3) * 2; if ($result == 4) {...}
    which would be trivial to add.

    Tanktalus asked above about if (all(@x) eq any(@y) {...}. I can see how useful that would be, but would have to experiment to find a way to implement it without getting as big as Q::S, while not making the code too ugly.

    Would Junction::Simple be a more fitting name? (I'm very hesitant to claim a top-name space)

    Benchmark timings...

    $ /usr/bin/perl ./benchmark.pl all: numeric (few) Rate Quantum-Superpositions Ju +nction Quantum-Superpositions 1842/s -- + -94% Junction 30303/s 1545% + -- all: numeric (lots) Rate Quantum-Superpositions Jun +ction Quantum-Superpositions 1364/s -- + -44% Junction 2433/s 78% + -- all: string Rate Quantum-Superpositions Jun +ction Quantum-Superpositions 1689/s -- + -79% Junction 8000/s 374% + -- any: numeric (few) Rate Quantum-Superpositions Ju +nction Quantum-Superpositions 747/s -- + -97% Junction 28571/s 3725% + -- any: numeric (lots) Rate Quantum-Superpositions Jun +ction Quantum-Superpositions 37.9/s -- + -97% Junction 1429/s 3672% + -- any: string Rate Quantum-Superpositions Jun +ction Quantum-Superpositions 317/s -- + -95% Junction 6422/s 1928% + --

      Tanktalus asked above about if (all(@x) eq any(@y) {...}. I can see how useful that would be, but would have to experiment to find a way to implement it without getting as big as Q::S, while not making the code too ugly.

      Actualy it is not all the difficult. Realy once you have overloaded the operators perl manages most of the extra magic to make that work without bloating your code. The code i linked to before is under 60 lines and handles that as well as embeding different any() and all() objects inside each other. For instance it handles print "YEA" if all( any(1..5), any(1..10), any(1..20)) > all(2..4); as expected.

      /me is still dieing to see how you approached the problem.


      ___________
      Eric Hodges

        I've uploaded it to cpan as Perl6::Junction.

        It's implemented more simply than yours (plain subs / no eval), which means that it's more lines of code, but in my benchmarks ran around 500% faster.

        See my reply to Tanktalus above, for more details on what it supports.

Re: RFC: Junction.pm
by eric256 (Parson) on May 02, 2005 at 15:54 UTC

    It would be interesting to see your code to compare. I built the same thing a while ago.


    ___________
    Eric Hodges

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://453220]
Approved by ghenry
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2021-01-22 04:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?