http://www.perlmonks.org?node_id=1207981


in reply to Prototype like sort()?

Thanks for all the answers, and sorry for not explaining myself more clearly. Basically I want to provide a sort-like function that users can use like sort(). The actual code I'm talking about is List::Rank.

sort SUBNAME LIST
sort BLOCK LIST
sort LIST

If users don't specify BLOCK or SUBNAME then sorting will be done the default way (lexically). If BLOCK or SUBNAME is specified, then sorting will be done using that custom sorter.

Seeing that this is not possible, I settled with separate subroutines.

Replies are listed 'Best First'.
Re^2: Prototype like sort()?
by haukex (Archbishop) on Feb 01, 2018 at 14:38 UTC

    I'm a bit late to the party, I just wanted to point out that it's not impossible to have one sub do it all, just ugly (and with the limitation that in the third form, the first thing in the list can't be a coderef):

    sub mysort (&@) { my $sub = ref $_[0] eq 'CODE' ? shift : sub {...}; ... } sub subname {...}; mysort {...} 'x', 'y', 'z'; mysort \&subname, 'x', 'y', 'z'; &mysort( 'x', 'y', 'z');

    On the other hand, I like your solution of rank @list vs. rankby {...} @list!

      Unfortunately there is an ugly and hard to debug edge case when using an &call with an empty list.

      From perlsub

      &foo;        # foo() get current args, like foo(@_) !!

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      Nice!

      to elaborate further, the trick you are using is that prepending & to a sub let's the parser ignore the prototype.

      > perlsub: Not only does the & form make the argument list optional, it also disables any prototype checking on arguments you do provide. This is partly for historical reasons, and partly for having a convenient way to cheat if you know what you're doing. 

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      Yup, all the time I write subs that behave differently depending on the type of arguments. The most common is: foo([ \%opts ], $arg, ...) and then trying to detect the optional hashref in the first argument.

      What I'm looking for here is the syntax bonus :)

Re^2: Prototype like sort()?
by LanX (Saint) on Feb 01, 2018 at 17:23 UTC
    Others explained that not all builtins' APIs can be copied by using prototypes.

    But if you are willing to combine your rank with another modifier sub like by with prototype, you could form compound statements like

    rank LIST; rank by BLOCK LIST; rank by {SUBNAME} LIST;

    I find this more readable than your original approach.

    If acceptable, I could elaborate further on a clean implementation.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Wikisyntax for the Monastery

      That's nice, I got reminded of TOBYINK's PerlX::Maybe when reading that code. But it's too "magical" for my taste. Thanks for the offer though.
        Actually, as long as we are only talking about two variants, it's more sensical to just define a second rankby .

        IMHO a module with many sort like functions would profit from a specialized by .

        > But it's too "magical" for my taste.

        In context of my DSL mediators I've already put some efforts into investigating possible pitfalls and found very good solutions.

        Please note that most other solutions come with ugly edge cases which are excluded here.

        There is a performance penalty though ...

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Wikisyntax for the Monastery