(Inspired by chromatic's recent musings...)
I want a function to take the mean of some data:
Hm.... I want to ignore NaN and Inf sometimes; I'll add a flag for it:
$x = mean \@data;
But I may also want to trim outliers; I'll use keyword arguments:
$x = mean \@data, 1;
Whoa, this is getting complicated; I'll make it an Object:
$x = mean \@data, skipinf => 1, trim => 0.1;
OMG, no encapsulation, I'll make accessors:
$x = new Mean(@data);
$x->{skipinf}=1;
$x->{trim}=0.1;
$y = $x->value
But now I have to do this just to do a simple mean:
$x = new Mean;
$x->setData(\@data);
$x->setSkipInf(1);
$x->setTrim(0.1);
$y = $x->value
I know, I'll create a little language for means:
$x = new Mean;
$x->setData(\@data);
$y = $x->value
Then I can write in the domain terminology, and taking the mean is easy:
$x = mean \@data, trim => 0.1, skipinf => 1;
$x = mean \@data;
...and thus we see how "writing interfaces that don't suck" became "creating little languages."
$mean = Mean->new( skipinf => 1, trim => 1 )->on( @data );
package Mean;
use Object::Tiny qw{
skipinf
trim
};
sub on { ...
}
1;
$mean = Mean->new->on( @data );
$mean = Mean->on( \@data );
Re:I don't get the set_method things
educated_foo on 2007-05-22T13:31:22
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 "objects are good" until they no longer think about naturalness and convenience of interfaces. Sometimes a function is just a function.Re:I don't get the set_method things
Alias on 2007-05-23T04:05:37
> 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 example, File::Find::Rule objects essentially describe computational filters. Sure you could have it as a function, but because it's an object, it can be easily passed as a filter to other functions that operate on file sets.
And those functions can VALIDATE that they are recieving a filter object.
Even more abstracted from that, look at the Process.pm family.
Objects that a built as Process.pm subclasses are capable of some very very cool things, such as being backgroundable, are able to run in a seperate Perl instance, are able to run in a different Perl VERSION, or in my favourite case, can be serialized into files, and be distributed across multiple processing nodes.
That said, Process.pm objects describe BOTH the process and the data in a single object... (or at least have a pointer to the data).
Most of the time a verb (function) should just be a verb, but sometimes having a verb as a noun (object) can be very very handy.
But yes, many people and languages (Java) like to go a bit over the top by making everything a noun...
There's a time and a place for both.Re:I don't get the set_method things
educated_foo on 2007-07-08T06:29:22
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 for people who would otherwise have written their own code for the simple case."Process Objects" (objects that describe a computational process) allow you to do things that functions can not do.Re:I don't get the set_method things
zby on 2009-02-22T15:41:07
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.