I'm interested in opinions on the use of FP (functional-Perl, ie: non-OO) routines exposed to consumers of an otherwise OO-module. Given that this is almost completely a style preference, I've chosen to Meditate on it. See the concept code below for an idea what's involved. While the examples are terse, the idea is to expose package-configs, possibly defaults to constructor use, or any package-wide tuning a module may support.

As I see it, there are 3 potential options:

  1. Use FP routines, and document public API use as Ex::Mod::conf(key=>'value')
  2. Use OO-style syntax, and document public API use as Ex::Mod->conf(key=>'value')
  3. Avoid such use all-together, making the caller always list every option desired.

#1 above is what my code samples use, and seems to best represent what the routine does. On the other hand, callers now need to remember if they're invoking an FP routine verses a method/constructor.

#2 is basically the same, but lets consumers be lazy and use the infix operator in all cases. This might be written in the module as:

sub conf { shift; # throw away unused class. # .. do real work here }

#3 would make callers always provide every default option (or not have any say in configuring other package-level adjustments.) Perhaps the callers re-use lengthy/common constructor arguments like so:

my %re_use = (name => 'Alice'); Ex::Mod->new( override=>'whatever', %re_use );
I'm not really fond of making callers do extra work if it's considered likely that use of a particular library might wish to set sensible defaults throughout use of the module. Further, this means package-config (not used by constructors) could only be adjusted by reaching into something like $Ex::Mod::DefaultTimeout to enact changes, which also feels messy.

Below is the example consumer, and the example Ex::Mod class:

consumer.pl

use strict; use warnings; use lib '.'; require Ex::Mod; Ex::mod::conf( user => 'Alice' ); my $a = Ex::mod->new(); # Presumably more constructor use wanting user=>'Alice' goes here.. my $b = Ex::mod->new( user=>'Bob'); printf "User a is: %s\n", $a->whoami(); printf "User b is: %s\n", $b->whoami();

Ex/Mod.pm

package Ex::mod; use strict; use warnings; # package-scoped config. my %conf = ( user => undef, ); # config routine. NB: FP! # <class>::conf( 'key' => 'value' ); sub conf { my %c = ( @_ ); for (keys %c) { $conf{$_} = $c{$_} if exists $conf{$_}; } } # new(), the constructor. sub new { my $class = shift; $class = ref($class) || $class; # subclass boilerplate. my %opts = ( @_ ); my $self = { user => $opts{user} // $conf{user} // '', }; return bless $self, $class; } # whoami() - method to say who this object's user is: sub whoami { my $self = shift; return $self->{user} // undef; }

In reply to OO APIs and FP interfaces by Apero

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.