Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

educated_foo (3106)

educated_foo
  (email not shown publicly)

Journal of educated_foo (3106)

Monday May 21, 2007
12:54 PM

Defining "DSL", or eternal recurrence in software

[ #33322 ]
(Inspired by chromatic's recent musings...)

I want a function to take the mean of some data:

$x = mean \@data;

Hm.... I want to ignore NaN and Inf sometimes; I'll add a flag for it:

$x = mean \@data, 1;

But I may also want to trim outliers; I'll use keyword arguments:

$x = mean \@data, skipinf => 1, trim => 0.1;

Whoa, this is getting complicated; I'll make it an Object:

$x = new Mean(@data);
$x->{skipinf}=1;
$x->{trim}=0.1;
$y = $x->value

OMG, no encapsulation, I'll make accessors:

$x = new Mean;
$x->setData(\@data);
$x->setSkipInf(1);
$x->setTrim(0.1);
$y = $x->value

But now I have to do this just to do a simple mean:

$x = new Mean;
$x->setData(\@data);
$y = $x->value

I know, I'll create a little language for means:

$x = mean \@data, trim => 0.1, skipinf => 1;

Then I can write in the domain terminology, and taking the mean is easy:

$x = mean \@data;

...and thus we see how "writing interfaces that don't suck" became "creating little languages."

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I mean, ok, I see some cases where it would be useful.

    But it seems to me that 90% of the time, you don't really NEED the ability to mutate the objects after creation time, especially with that sort of thing. You'd almost always set it at creation time.

    Mutators just adds more (potentially illogical) states (and thus potential bugs).

    $mean = Mean->new( skipinf => 1, trim => 1 )->on( @data );

    package Mean;

    use Object::Tiny qw{
            skipinf
            trim
    };

    sub o
    • My broader point was that the current fad of calling everything a "DSL"can exist only because people are thoughtless with interfaces and/or have been trained to create painful ones. I agree that setters are probably unnecessary in this case, but your cleaner code nicely demonstrates one of my own interface pet peeves: Blah->new(@stuff)->doit. There's always at least one in the CPAN queue -- see Sudo this morning. Doing this is almost always a mistake indicative of someone having been told that "obj
      • > Sometimes a function is just a function.

        Sometimes, yes. And it's true people get bitten by the object fad.

        But as you scale is can be very advantageous to have the option of encapsulating a function and moving it around.

        It's not really safe to do this with a raw code-ref, because a coderef could be anything at all and is tied to the Perl instance. A data structure is far more flexible.

        "Process Objects" (objects that describe a computational process) allow you to do things that functions can not do.

        For e
        • "Process Objects" (objects that describe a computational process) allow you to do things that functions can not do.

          IMHO they get the defaults wrong most of the time. If you amortize over all the people using a module, it's less trouble for those who need them to go through the full pain of either serializing functions through e.g. Storable or doing a custom solution, than for everyone to use a ghastly "OO" interface, or roll their own. Distributing a module on CPAN is a real win when it will save time

        • Many of those advantages you mention are also available via closures. Other languages don't have true closures - so they have to do that in OO - but we have choice. HOP shows that a more functional approach also works.