MJD HOP influence

M

Matija Papec

It seems that functional approach is better suited for smaller "classes"
compared to classical OOP. Thinking in such way is challenging and pretty
new to me so I would be interested to hear suggestions; eg. is there some
flaw which can show in threading environment or how to optimize this very
basic OO example below.


===========================
use strict;
use warnings;

my $obj = Child(foo => 1, bar =>2);
$obj->(addcond => [id => 7]);
$obj->(addcond => [name => "lucas"]);

print $obj->(dumper => 1) if $obj->(can => "dumper");


sub Child {
#
# child class
#
our ($AUTOLOAD, $SUPER);
# child object data
my @foobar;

my $m = {
AUTOLOAD => sub {
my $self = shift;
print "There is no $AUTOLOAD!\n";
return;
},
dumper => sub {
my $self = shift;
$SUPER->(dumper => @_);
},
addcond => sub {
my $self = shift;
# get $SUPER via $self
# $AUTOLOAD contains current method name
$self->("SUPER")->($AUTOLOAD => @_);
},
};
return newclosure(usebase => \&Parent, $m, @_);
}

sub Parent {
#
# parent class
#
use Data::Dumper;
# object data
my %arg = @_;
my @cmdcond;

my $m = {
dumper => sub {
my $self = shift;
Dumper \@cmdcond, \%arg;
},
addcond => sub {
my $self = shift;
push @cmdcond, shift;
},
};
return newclosure($m, @_);
}


#########################################
sub newclosure {
#
our ($AUTOLOAD, $SUPER);
my $m = shift;

my $usebase;
my $super;
# inheritance?
if ($m eq "usebase") {
$usebase = shift;
$m = shift;
$super = &$usebase;
}

# core methods
$m->{SUPER} = sub { $super };
$m->{can} = sub {
my $self = shift;
my $sub = shift;
$m->{$sub} || $super->(can => $sub) || $m->{AUTOLOAD};
};

my $self;
return $self = sub {
my $sub = shift;
local $AUTOLOAD = $sub;
local $SUPER = $super;

# who you gonna call?
return
$m->{$sub} ? $m->{$sub}->($self, @_) :
$super->(can => $sub) ? $super->($sub, @_) :
$m->{AUTOLOAD}->($self, @_);
};
}
 
A

Anno Siegel

Matija Papec said:
It seems that functional approach is better suited for smaller "classes"
compared to classical OOP.

With "functional approach", do you mean a class whose objects are
coderefs? What is the "classical" approach and what are the advantages
you see?
Thinking in such way is challenging and pretty
new to me so I would be interested to hear suggestions; eg. is there some
flaw which can show in threading environment or how to optimize this very
basic OO example below.

There is no OO in your example. The hallmark of Perl OO is that objects
are blessed into their class. This never happens here. Neither are the
calls

$obj->(addcond => [id => 7]);

etc. method calls, this is just the syntax to call a coderef. So whatever
you have built, it isn't an alternative to a classical OO approach.

Otherwise, classes whose objects are coderefs offer better protection
(and harder access to) the the object variables, assuming that the
object variables are implemented as private lexicals. They are usually
harder to deal with than more conventional implementations. The size
of the class (in terms of number and complexity of methods) has little
to do with the advantages and drawbacks of this approach.

Anno
===========================
use strict;
use warnings;

my $obj = Child(foo => 1, bar =>2);
$obj->(addcond => [id => 7]);
$obj->(addcond => [name => "lucas"]);

print $obj->(dumper => 1) if $obj->(can => "dumper");


sub Child {
#
# child class
#
our ($AUTOLOAD, $SUPER);
# child object data
my @foobar;

my $m = {
AUTOLOAD => sub {
my $self = shift;
print "There is no $AUTOLOAD!\n";
return;
},
dumper => sub {
my $self = shift;
$SUPER->(dumper => @_);
},
addcond => sub {
my $self = shift;
# get $SUPER via $self
# $AUTOLOAD contains current method name
$self->("SUPER")->($AUTOLOAD => @_);
},
};
return newclosure(usebase => \&Parent, $m, @_);
}

sub Parent {
#
# parent class
#
use Data::Dumper;
# object data
my %arg = @_;
my @cmdcond;

my $m = {
dumper => sub {
my $self = shift;
Dumper \@cmdcond, \%arg;
},
addcond => sub {
my $self = shift;
push @cmdcond, shift;
},
};
return newclosure($m, @_);
}


#########################################
sub newclosure {
#
our ($AUTOLOAD, $SUPER);
my $m = shift;

my $usebase;
my $super;
# inheritance?
if ($m eq "usebase") {
$usebase = shift;
$m = shift;
$super = &$usebase;
}

# core methods
$m->{SUPER} = sub { $super };
$m->{can} = sub {
my $self = shift;
my $sub = shift;
$m->{$sub} || $super->(can => $sub) || $m->{AUTOLOAD};
};

my $self;
return $self = sub {
my $sub = shift;
local $AUTOLOAD = $sub;
local $SUPER = $super;

# who you gonna call?
return
$m->{$sub} ? $m->{$sub}->($self, @_) :
$super->(can => $sub) ? $super->($sub, @_) :
$m->{AUTOLOAD}->($self, @_);
};
}
 
M

Matija Papec

X-Ftn-To: Anno Siegel

With "functional approach", do you mean a class whose objects are
coderefs? What is the "classical" approach and what are the advantages
you see?

By classic OO perl I mean using package and blessing hash/array/etc into it.
Potential advantage is avoiding separate file/package when you only need a
few methods for your objects.
The hallmark of Perl OO is that objects
are blessed into their class. This never happens here. Neither are the

True, but nobody claimed otherwise..
$obj->(addcond => [id => 7]);

etc. method calls, this is just the syntax to call a coderef. So whatever
you have built, it isn't an alternative to a classical OO approach.

That depends on what do you mean it should provide to be an alternative.
This example has *some* OO qualities like object methods and inheritance; in
that way it follows OO paradigm (OO paradigm in general, not that of perl).
Otherwise, classes whose objects are coderefs offer better protection
(and harder access to) the the object variables, assuming that the
object variables are implemented as private lexicals. They are usually
harder to deal with than more conventional implementations. The size

Yes; unfortunately I'm not sure if you can inherit from such class; perhaps
building parent so it can provide data container for it's children?
of the class (in terms of number and complexity of methods) has little
to do with the advantages and drawbacks of this approach.

Now that you mention this, I can only say that my OO coderefs doesn't suffer
completely like blessed ones. :)
 
A

Anno Siegel

Matija Papec said:
X-Ftn-To: Anno Siegel



By classic OO perl I mean using package and blessing hash/array/etc into it.

That's what I mean too.
Potential advantage is avoiding separate file/package when you only need a
few methods for your objects.

Avoiding a separate *file* is usually just a matter of source organization,
it can be done with any implementation. Avoiding a *package* goes to
the root of Perl OO since classes are normally packages. So the question
is, what takes the role of classes in this implementation? I sincerely
don't see what does.
True, but nobody claimed otherwise..

Then please explain the terms: What are objects in this implementation,
what are methods and what are classes. I can't think of an OO system
that doesn't define these.

I haven't read HOP cover to cover yet. Perhaps you could point out
what part of the book stimulated your code so others can read up on
the background.
$obj->(addcond => [id => 7]);

etc. method calls, this is just the syntax to call a coderef. So whatever
you have built, it isn't an alternative to a classical OO approach.

That depends on what do you mean it should provide to be an alternative.
This example has *some* OO qualities like object methods and inheritance; in
that way it follows OO paradigm (OO paradigm in general, not that of perl).

What are the object methods, and what are objects, and how does
inheritance happen? Normally inheritance goes from one class to another.
Without defining what classes are, it is impossible to even talk about
inheritance.
Yes; unfortunately I'm not sure if you can inherit from such class; perhaps
building parent so it can provide data container for it's children?

With a standard implementation of a Perl class with objects that happen
to be coderefs, inheritance happens like with any other Perl class.
As usual in Perl OO, it depends on the implementation of the base
class whether inheritance is easy, hard or impossible. There is
nothing fundamentally different from classes whose objects are (say)
hashrefs.
Now that you mention this, I can only say that my OO coderefs doesn't suffer
completely like blessed ones. :)

Sorry, I don't understand this sentence.

Anno
 
M

Matija Papec

X-Ftn-To: Anno Siegel
Then please explain the terms: What are objects in this implementation,
what are methods and what are classes. I can't think of an OO system
that doesn't define these.

See below.
I haven't read HOP cover to cover yet. Perhaps you could point out
what part of the book stimulated your code so others can read up on
the background.

At the beginning Mark wrote that functional and OO approach are solving the
same problems so I've tried if functional could simulate OO.
What are the object methods, and what are objects, and how does
inheritance happen? Normally inheritance goes from one class to another.
Without defining what classes are, it is impossible to even talk about
inheritance.

Sorry, I thought this is obvious; "classes" are sub Parent and sub Child,
object is what you get after calling either of these two ($obj), and class
methods are defined in %$m. If $obj comes from Child, it can call all Child
methods in addition to those defined in Parent as Child is inheriting from
Parent (usebase => \&Parent defines this relationship).
Beside, Child can override Parent methods but it can also call them via
$SUPER.
With a standard implementation of a Perl class with objects that happen
to be coderefs, inheritance happens like with any other Perl class.
As usual in Perl OO, it depends on the implementation of the base
class whether inheritance is easy, hard or impossible. There is
nothing fundamentally different from classes whose objects are (say)
hashrefs.

Perhaps, but possibility to inherit from class which uses scalar/coderef
goes more often toward impossible then it would go in case when base class
uses hashref. If it isn't much trouble, can you point to good example of
class using coderefs and it's easily inheritable?
Sorry, I don't understand this sentence.

In my example coderefs are some kind of objects and my base class doesn't
have to worry how it could be inherited by other class, as opposed to
blessed coderef, where their class *has to think* about possible
inheritance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top