NAME

Class::Holon - An experiment in redefining class declarations / object instantiation in perl.

SYNOPSIS

package Atom;
use Class::Holon 
( 
	To => DescribeLevel, 
	Type => Hash,
	Data => { protons=>0, neutrons=>0, electrons=>0 },
);


package main;
use Atom;
my $atom = Class::Holon::New('Atom');

DESCRIPTION

This module is an experiment in redefining class declarations and object instantiation in perl. The intent is to eventually encapsulate many of the common things that classes and objects find useful so that people do not have to reinvent the wheel to use them. I would also like for it to make certain capabilities available to programmers that are not available in native perl.

VOCABULARY

The term Holon was blatantly stolen from Authur Koestler (1905-1983). I believe he coined the term in 1967, but I'm not certain. I was actually introduced to the term via a book written by Ken Wilber, but I digress.

First, some definitions:

HOLON DEFINITION

Holon

A holon is a node in a tree structure. Holon comes from the Greek holos meaning "whole" and on meaning "part" or particle. The key characteristics of a holon include that it asserts its individuality in order to maintain the set order in the tree structure, but it also submits to the demands of the whole tree structure (the system) in order to make the system viable. Holons are self-contained, autonomous pieces which follow a prescribed set of rules. The holon has a "self-assertiveness tendency" (wholeness) as well as an "integrative tendency" (part).This duality is similar to the particle/wave duality of light. (Koestler)

Once you have some Holons, you can put them in a structure called a holarchy.

HOLARCHY DEFINITION

Holarchy

A holarchy is a hierarchy of holons. Entire organs such as the kidneys, heart, and brain are capable of continuing their functions, as quasi-independent wholes, when isolated from the organism and suplied with the proper nutrients.

Characteristics of Holarchies:

Bi-directionality: Each holon can receive signals as well as send signals. The "flow" in a holarchy is both up and down.

Level behaviour: The holon at one level is not necessarily the "sum" of its subordinates. The characteristics of holons at one level are not representative of the characteristics of the level above or below them. The further down the holarchy, the more mechanized, stereotyped, and predictable the behavior. Higher level holons have more flexibility and function a more abstract state.

Flexibility: Holarchies are not rigid structures; they allow modification and adaptability. A holon can be part of multiple holarchies.

Open-ended: The top and the bottom of holarchies are not absolute. A holarchy can be augmented or interwoven with another holarchy.

HOLONS IN PERL

You can Describe a holon level.

use Class::Holon ( To => DescribeLevel, ... );

You can Specify a specific type of holon level.

use Class::Holon ( To => SpecifyLevel, ... );

You can Instantiate new holons based on their description / specification.

my $instance = Class::Holon::New( ... );

Describe and Specify defines what a holon looks like. Once a holon is defined, you can Instantiate them.

DESCRIBING A LEVEL

A perl package namespace is used to give a holon level its Name. Each package can call use Class::Holon (...) once and only once to describe or specify a level.

If you find you have defined a holon that has a Name attribute, then you should rethink your entire approach.

The perl package that calls use Class::Holon determines the holon name.

So, say you want to define an "Atom" holon. First, get into package Atom. Then call use Class::Holon (); with the appropriate attributes.

package Atom;
use Class::Holon 
( 
	To => DescribeLevel, 
	Type => Hash,	
	Data => { protons=>0, neutrons=>0, electrons=>0 },
);
1; # thats it!

Or say you want to define a "Movable" holon, which keeps track of x,y,z coordinates of something.

package Movable;
use Class::Holon  
( 
	To => DescribeLevel, 
	Type => Hash,
	Data => { posx=>0, posy=>0, posz=>0 },	
);

Or, say you want to define a "Dogtag" holon.

package Dogtag;
use Class::Holon 
( 
	To => DescribeLevel, 
	Type => Hash,	
	Data => { Name=>'', Rank=>'', SerialNumber=>0 },
);

Or, say you want to define a "Bucket" holon that stores an array of scalars.

package Bucket;
use Class::Holon
(
	To => DescribeLevel,
	Type => Array,
	Data => [],
);

Last, but not least, say you want to define a "Helicopter" holon. And like a helicopter, it's fast and small, but somewhat difficult to control.

package Helicopter;
use Class::Holon
(
	To => DescribeLevel,
	Type => GetSet,
	Data => { Speed=>0, Altitude=>0 },
);

I'll go into more detail about the "GetSet" type later.

To has two possible valid values, DescribeLevel and SpecifyLevel.

Type has three possible valid values, Hash, Array, and GetSet.

Data will define the attributes, and possibly, their initial value.

Data is where the attributes for the holon are defined. Note that Dogtag has a Name attribute. This is OK in this case, since the Name of the holon is Dogtag. The Name attribute in this case refers the name of the person associated with each Dogtag instance.

If your Data has defined a Name attribute, just make sure you're defining your holons properly.

VARIATIONS ON DATA

The Data entry has a number of different flavors.

If Type is a Hash or GetSet, then Data can indicate the attribute names using an array reference.

Type => Hash,
Type => GetSet,
Data => [ attribute1, attribute2, attribute3, ... ],

If Type is a Hash or GetSet, then Data can use a reference a hash, where the keys indicate the attribute names, and the Data indicates its initial value.

Type => Hash,
Type => GetSet,
Data => {
	attribute1 => initial_value1,
	attribute2 => initial_value2,
	...
	},

Note, that if ANY attribute has an initial value, then they ALL must have an initial value. If you care about some initial values, but dont care about others, just use undef for the ones you don't care about.

If Type is an Array, then Data can ONLY be a reference to an array. The contents of the array indicate the initial values of an array instance, rather than the attribute names.

Type => Array,
Data => [ init_value_index_0, init_value_index_1, ... ],

Holons of type Array and Hash do not need to indicate Data. The instances are references to normal arrays/hashes, therefore, they can autovivify as usual.

Holons of type GetSet must define its Data attributes so that use Class::Holon can create the necessary methods in the proper package.

Note, if the initial value is a subroutine reference, the subroutine will be executed upon an object's instantiation.

package Frankenstein;
use Class::Holon ( To => DescribeLevel, Type => Hash,
	Data => { Yell => sub { print "It's ALIVE!!"; } },
);

package main;
use Frankenstein;	# no output here.

my $monster = Class::Holon::New('Frankenstein'); # It's ALIVE!!

&{$monster->{Yell}}();	# It's ALIVE!!

CREATING AN INSTANCE OF A HOLON

Once you've described a holon level, you can create instances of that level. The description of the level does NOT need to define a constructor. You have already defined everything perl needs to know in the use Class::Holon(...) call.

package main;
use Atom;
my $atom_instance = Class::Holon::New('Atom');

Note that package main did not have to say use Class::Holon. This is because when main calls use Atom, package Atom will call use Class::Holon, and use Class::Holon will pull the Class::Holon.pm perl package into the mix. You only have to use whatever holons you are using directly. Everything else is handled under the hood by the Holon module.

Class::Holon::New takes one parameter, the name of the level to create. This coincides with the name of the perl package that called use Class::Holon (...); In this case, Class::Holon::New('Atom') will return an instance of whatever holon was described in package Atom;.

The instance is in the form of a reference to what ever Type was defined for that holon. In this case, it is a reference to a hash.

The instance is a reference, and whatever it is pointing to (the referent) will be blessed into the package of the holon level. In this case, it is blessed into the Atom package.

The instance will be initialized to any values given in Data. In this case, $instance will refer to a hash containing the keys Name, Rank, and SerialNumber.

If an initial value is given to use Class::Holon in the form of a code reference, then that code reference will be executed at instantiation. See above for more info on

use Class::Holon ( Data => ... )

GETTING MORE SPECIFIC DESCRIPTIONS

Let's assume we've been tasked with writing some perl code that will allow us to model chemical experiments. (I'm not a chemist, but I play on TV.)

The Atom holon seems to be a good start. However, since we're talking about chemical experiments and not physics, its probably safe to assume that our application will not need to split atoms. Therefore, we could describe specific atoms.

When you Specify a holon level, you are taking a description and making it more specific.

The names of the attributes remain the same. But the values can be different.

In perl, the keys of the Data hash are the same, but the values can be different.

In the Atom example, it might look like this:

package Atom::Hydrogen;
use Class::Holon (
	To => SpecifyLevel, 
	Data => { protons=>1, neutrons=>0, electrons=>1 },	
);

package Atom::Oxygen;
use Class::Holon (
	To => SpecifyLevel, 
	Data => { protons=>8, neutrons=>8, electrons=>8 },	
);

Note, we are no longer defining Type. Instead, we use the same Type that was given in Atom.

Also note that we are defining different Values for Data. The Attributes MUST match the attributes used to define Atom.

This may or may not have a use in your application. If a subroutine is called on Atom, and a large case statement is needed to determine how to handle the Atom based on which atom it is, then it may be advantageous to give the Atom a qualifying name so that the proper subroutine can be called more directly. (this would be the approach for using multimethods, but we're getting ahead of ourselves.)

THE GETSET TYPE

The holon type GetSet is a little different than the others. The data in the holon is stored in an inaccessible array. The only means to access the data is via method calls. The names of the methods are the names of the Data attributes, but with a suffix to indicate what action to perform. These methods are imported in the package when you call use Class::Holon.

For instance:

package Helicopter;
use Class::Holon (
	To => SpecifyLevel,
	Type => GetSet,
	Data => { Speed=>0, Altitude=>0 },
);

package main;
my $jetranger = Class::Holon::New('Helicopter');

$jetranger->SpeedSet(110);
my $altitude = $jetrange->AltitudeGet;

The type GetSet hides the attribute implementation from the user. The array data contained in each object is not accessible except through the methods.

The method names are based off of the attribute name. The intention is to have the methods act like hash keys to make them easy to use, but for the object to have the speed and size as close to an array as possible.

Given an attribute name in the Data Description, the following methods are available to call on an object.

attributeGet	return the value of the attribute
attributeSet	store a new value in the attribute
attributeInc	increment the value of the attribute by 1.
attributeDec	decrement the value of the attribute by 1.
attributeAdd	Add a value to the attribute
attributeSub	Subtract a value from the attribute	
attributeMul	Multiply the attribute by some value	
attributeDiv	Divide the attribute by some value	
attributeNeg	Negate the attribute (multiply by -1)	
attributeMod	Take the modulus of the attribute and put in attribute	

This means that in the above example, after calling use Class::Holon, package Helicopter would contain subroutines such as:

SpeedGet
SpeedSet
AltitudeGet
AltitudeSet

Note, Get and Set may change to Rd and Wr Get and Set are too similar for my comfort.

THE NEXT LEVEL UP

DEBUG: introduce MovableAtom module.

Documentation ran out of steam at this point. skipping to ending boiler plate.

BUGS

none known so far.

QUOTES

True creativity often starts where language ends - Authur Koestler

DSLIP

DSLIP = ADPHP

AUTHOR

Greg London http://www.greglondon.com

COPYRIGHT NOTICE

Copyright (c) 2001 Greg London. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.