Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Data::Remember::Class(User Contributed Perl DocumentatData::Remember::Class(3)

       Data::Remember::Class - remember	complex	information without giving
       yourself	a headache, now	with POOP!

       version 0.140490

	 use Data::Remember::Class;

	 my $store = Data::Remember::Class->new('Memory');

	 $store->remember(foo => 1);
	 $store->remember([ bar	=> 7 ],	[ 'spaz', 'w00t', 'doof', 'flibble' ]);
	 $store->remember([ 'xyz', 'abc', 'mno'	] => { some => 'thing' });

	 $store->remember_these(cook =>	'goose');
	 $store->remember_these(cook =>	'duck');
	 $store->remember_these(cook =>	'turkey');

	 my $foo     = $store->recall('foo');	     # retrieve	a simple key
	 my $wibbler = $store->recall([	bar => 7 ]); # retrieve	a complex key
	 my $alpha   = $store->recall('xyz');	     # retrieve	a subkey

	 my $cook    = $store->recall([	'cook' ]);   # retrieves [ qw/ goose duck turkey / ]


	 my $foo_again = $store->recall('foo');	# $foo_again is	undef

	 $store->forget_when(sub { /^duck$/ }, [ 'cook'	]);

	 my $cook_again	= $store->recall('cook'); # $cook_again	is [ qw/ goose turkey /	]

       While designing some IRC	bots and such I	got really tired of statements
       that looked like:

	 $heap->{job}{$job} = {
	     source  =>	$source,
	     dest    =>	$destination,
	     options =>	$options,

       and later:

	 if ($heap->{job}{$job}{options}{wibble} eq $something_else) {
	     # do something...

       I could simplify	things with intermediate variables, but	then I
       inevitably end up with 4	or 5 lines of init at the start	or middle of
       each subroutine.	Yech.

       So, I decided that it would be nice to simplify the above to:

	 remember [ job	=> $job	], {
	     source  =>	$source,
	     dest    =>	$destination,
	     options =>	$options,

       and later:

	 if (recall [ job => $job, options => 'wibble' ] eq $something_else) {
	     # do something...

       Which I consider	to far more readable.

       At my next job, I decided to use	Bread::Board and Moose and all that
       jazz into the internals of the new bot I	wrote. As such,	I couldn't
       really make much	use of this module, but	I wanted to. So, now I've
       added this Perl object-oriented programming interface, which does this:

	 $store->remember([ job	=> $job	], {
	     source  =>	$source,
	     dest    =>	$destination,
	     options =>	$options,

       and this:

	 if ($store->recall([ job => $job, options => 'wibble' ]) eq $something_else) {
	     # do something...

       Which I consider	both readable and flexible.

       The second aspect that this deals with is long-term storage. I started
       using DBM::Deep to remember the important bits of state across bot
       restarts. This package will store your information persistently for you
       too if you want:

	 use Data::Remember::Class;
	 my $store = Data::Remember::Class->new( DBM =>	'state.db' );

       By using	that command, the Data::Remember::DBM "brain" is used instead
       of the usual Data::Remember::Memory brain, which	just stores things in
       a Perl data structure.

       Each method takes a $que	argument. The que is a memory que to store the
       information with. This que may be a scalar, an array, or	a hash,
       depending on what suits your needs. However, you	will want to be	aware
       of how these are	translated into	memory locations in the	brain plugin.

       Any que argument	is passed to the brain as an array. A scalar que is
       just wrapped in an array	reference:

	 $store->remember(foo => 1);

       is the same as:

	 $store->remember([ 'foo' ] => 1);

       An array	que is passed exactly as it is to the brain plugin.

       A hash que is converted to an array by sorting the keys in string order
       and keeping the pairs together. For example:

	 $store->remember({ foo	=> 3, bar => 2,	baz => 1 } => 'xyz');

       is the same as:

	 $store->remember([ 'bar', 2, 'baz', 1,	'foo', 3 ] => 'xyz');

       This is different from storing:

	 $store->remember([ foo	=> 3, bar => 2,	baz => 1 ] => 'xyz');

       The use of an anonymous array instead of	an anonymous hash preserves
       the order of your choice.

       Finally,	you can	get access to the root of your brain's memory by using
       the empty que:

	 $store->remember([], {	store => 1, all	=> 2, the => 3,	things => 4 });

       Once the	array is built the brains are required to treat	these in the
       same way	as hash	keys for a hash	of hashes. For example,	you can	think

	 $store->remember([ foo	=> 3, bar => 2,	baz => 1 ] => 'xyz');

       as being	similar	to storing:

	 $memory->{foo}{3}{bar}{2}{baz}{1} = 'xyz';

       This means that you could later recall a	subset of the previous key:

	 my $bar = $store->recall([ foo	=> 3, 'bar' ]);

       which would return a hash reference similar to:

	 my $bar = { 2 => { baz	=> { 1 => 'xyz'	} } };

       (assuming you hadn't stored anything else under "[ foo => 3, 'bar' ]").

       Clear as	mud? Good!

	 my $store = Data::Remember::Class->new($brain,	@options);

       The $brain argument lets	you select a brain plugin to use. The brain
       plugins available with this distribution	currently include:

	   A brain that	stores everything in plain Perl	data structures. Data
	   in this brain is not	persistent.

	   A brain that	stores everything via DBM::Deep. Data stored here will
	   be persistent. This brain also requires additional arguments	(see
	   the module documentation for	details).

	   A brain that	stores everything via YAML. This is great for storing
	   configuration data.

	   A brain that	doesn't	store anything,	but lets you use mix storage

	   Automagically use a brain that is stored in the POE::Session	heap.

       You can specify $brain as a short name if it exists under
       ""Data::Remember::"". (For example, ""DBM"" will	load
       ""Data::Remember::DBM"".) if $brain contains a ""::"", then it will be
       treated as a fully qualified name, in case you want to create your own
       brain. See "CREATING A BRAIN" in	Data::Remember.

       The @options are	whatever options described in the brain's module

	 $store->remember($que,	$fact);

       Remember	the given $fact	at memory que $que. See	"QUE" for an in	depth
       discussion of $que. The $fact can be anything your brain	can store.
       This will generally include, at least, scalars, hash references,	and
       array references.

	 $store->remember_these($que, $fact);

       Stores the given	$fact at the give $que,	but stores it by pushing it
       onto the	back of	an array stored	at $que. This allows you to remember a
       list of things at a given $que:

	 $store->remember_these(stooges	=> 'Larry');
	 $store->remember_these(stooges	=> 'Curly');
	 $store->remember_these(stooges	=> 'Moe');

	 my $stooges = $store->recall('stooges');
	 # ^^^ returns the array [ qw( Larry Curly Moe ) ]

	 my $fact = $store->recall($que);

       Recalls a previously stored fact	located	at the memory location
       described by $que. See "QUE" for	an in depth discussion of that

       If no fact is found at that que,	"undef"	will be	returned.

	 my $iter = $store->recall_each($que);
	 while (my ($k,	$v) = $iter->()) {

       Given a que defined as a	usual "QUE", this will return an iterator that
       will iterate over all the keys in a nested part of the store. The way
       the iterator works will depend on what kind of data $que	points to.

       o   Hash. For hashes, the iterator will work similar to the built-in
	   "each" operator. It will return each	key/value pair found in	the
	   hash	in no particular order.

       o   Array. For arrays, the iterator will	return each index and value as
	   a pair, in order.

       o   Scalar. For anything	else, it will return a single pair. The	first
	   element in the pair will be "undef" and the second will be the
	   scalar value.

       When the	iterator is finished it	returns	an empty list.

       The iterator captures the keys and array	length at the time it was
       created.	If changes are made to the data	stored,	it will	return the
       same keys or array indexes that were stored at the moment of the	call,
       but the values returned will be whatever	is current stored. If the
       value at	the que	is removed entirely, the iterator closes over the
       original	reference and will proceed anyway.

	 my $count = $store->recall_and_update(sub { ... }, $que);

       This helper allows you to simultaneously	recall and update an entry.
       For example, if you want	to increment the entry while recalling it:

	 my $count = $store->recall_and_update(sub { $_++ }, 'count');

       any modification	to $_ will be stored back into the given que. The
       result of the code run is returned by the function. For example,	if you
       wanted to replace every "G" with	"Q" in the brain, but wanted to	use
       the original unmodified string, you could:

	 my $with_g = $store->recall_and_update(sub { my $copy = $_; s/G/Q/g; $copy }, 'some_que');


       Tells the brain to forget a previously remembered fact stored at	$que.
       See "QUE" for an	in depth discussion of the argument. If	no fact	is
       stored at the given $que, this subroutine does nothing.

	 $store->forget_when(sub { ... }, $que);

       Tells the brain to forget a previously remembered fact stored at	$que.
       The behavior of "forget_when" changes depending on the nature of	the
       fact stored at $que.

       If $que is a hash, the code reference given as the first	argument will
       be called for each key/value pair and passed the	key in $_[0] and the
       value in	$_[1]. When the	code reference returns true, that pair will be

       If $que is an array, the	code reference given as	the first argument
       will be called for each index/value pair	and passed the index in	$_[0]
       and the value in	$_[1], the value will be passed	in $_ as well. If the
       code reference returns a	true value, that value will be forgotten.

       For any other type of fact stored in the	brain, the code	reference will
       be called with $_[0] set	to "undef" and $_[1] and $_ set	to the value
       of the fact. The	whole que will be forgotten if the code	reference
       returns true.

	 my $brain = $store->brain;

       Returns the inner object	used to	store data. This can be	used in	case
       the brain plugin	provides additional methods or features	that need
       manual access. For example, if you want to use DBM::Deeps locking
       features, you could:


	 my $balance = $store->recall('balance');
	 $store->remember(balance => $balance +	150);


       If you would like to create a custom brain plugin, you need to create a
       package that implements four methods: "new", "remember",	"recall", and

       The "new" method	will take the list of options passed to	"import" for
       your brain in addition to the class name. It should return a blessed
       reference that will be used for all further method calls.

       The "remember" method will be passed a normalized reference to a	que
       array and the fact the user has asked to	store. You should read through
       "QUE" and handle	the first argument as described	there. Then, store the
       second argument at the memory location described.

       The "recall" method will	be passed a normalized reference to a que
       array, which should be treated as described in "QUE". Your
       implementation should return the	fact stored at that location or
       "undef".	It's important that your implementation	avoid the pit-falls
       caused by auto-vivifying	keys. The "recall" method should never modify
       the memory of your brain.

       The "forget" method will	be passed a normalized reference to a que
       array, which should be treated as described in "QUE". Your
       implementation should then delete any fact stored there.	Other than
       deleting	this key, the "forget" method should not modify	any other
       aspect of the memory of your brain.

       To build	a brain, I highly recommend extending Data::Remember::Memory,
       which performs (or should perform) all the work of safely storing and
       fetching	records	from a Perl data structure according to	the interface
       described here. It stores everything under "$self->{brain}". At the
       very least, you should read through that	code before building your

       The Data::Remember::DBM or other	included brains	may also be a good
       place to	look. They extend Data::Remember::Memory so that I didn't have
       to repeat myself.

       This class emits	the following warnings:

       The brain BRAIN may not have loaded correctly: ERROR
	   This	message	indicates that an error	occurred while loading the
	   package named "BRAIN". "ERROR" contains the nested error message.
	   This	is only	a warning because it's possible	that this failure is
	   normal (e.g., if the	package	is not defined in it's own Perl

       Undefined que element used in call to SUB.
	   This	message	indicates that you attempted to	pass an	undefined
	   value as a component	of the que to the named	subroutine. Such calls
	   are ignored by Data::Remember. (Hence the warning.)

       Whenever	possible, this library attempts	not to throw exceptions. The
       major exception that rule (HAH!)	is during initialization. Any problems
       detected	there are generally very important, so exceptions are thrown

       Here are	the exceptions that are	emitted	by this	class:

       This does not look like a valid brain: BRAIN
	   The brain plugin name given does not	look like a valid Perl class
	   name. Data::Remember	won't even check to see	if it is a brain
	   plugin unless it could be a package name.

       Your brain cannot remember facts: BRAIN
	   You attempted to use	a brain	class that does	not provide a
	   "remember()"	method.

       Your brain cannot recall	facts: BRAIN
	   You attempted to use	a brain	class that does	not provide a
	   "recall()" method.

       Your brain cannot forget	facts: BRAIN
	   You attempted to use	a brain	class that does	not provide a
	   "forget()" method.

       Data::Remember::Memory, Data::Remember::DBM, Data::Remember::YAML,

       Andrew Sterling Hanenkamp <>

       This software is	copyright (c) 2014 by Qubling Software LLC.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.32.1			  2014-02-18	      Data::Remember::Class(3)


Want to link to this manual page? Use this URL:

home | help