I'm trying to create a replacement for AI::Prolog (one that uses Perl data structures and doesn't require knowledge of Prolog) and I've hit a stumbling block and my solution seems really nasty.

Imagine an arbitrarily complex data structure:

[ $var1, undef, [ undef, undef, { 'foo' => $var2 } ], { 'bar' => $var3 } ];

Let's say I have an arbitrary number of other data structures with identical structures, but different values. For every variable in the structure above (it's an instance of something called a "logic" variable), how can I efficiently assign it the corresponding value in the each of the other structures? As a simple example, let's say that structure looks like this:

my $unknown = [ undef, undef, $var ];

If I have three other structures like this:

my @structures = ( [ qw/ 1 2 3 / ], [ qw/ this that other / ], [ qw/ un deux trois / ], );

Then I'd like something like this:

foreach my $structure (@structures) { bind($unknown, $structure); print $var->value; }

That would print "3", "other", and "trois", in sequence.

As mentioned, the data structures might be arbitrarily complex and currently the only data types allowed are scalars, array refs, hashrefs, and regexes and due to how the system is built, the structure are guaranteed to be identical in shape, including size of arrays and hashes.

I am assuming that I need an easy way to spider the $unknown structure and cache the positions of all of those logic variables. The only way I've thought of it so far is to build up a string representation of the data structure and use nasty string eval tricks to get at them (sort of like XPath for Perl data structures). For example, the following will assign "3" to the logic variable:

my $struct = [ 'whaa!', undef, [undef, undef, { foo => 3}], { bar => 'baz'}, ]; my $path = "[2][2]{foo}"; $var->bind( eval "\$struct->$path" );

This seems really nasty and any advice would be welcome.

Note that things like Data::Diver and Class::XPath seem great, but they don't solve the general algorithm problem of:

foreach my $path (find_logic_var($unknown_struct)) { push @paths => $path; }

In other words, the paths are unknown up front and that's the major problem I want to solve efficiently. Maybe I should recursively walk the data structure while pushing path elements on a localized stack?

Cheers,
Ovid

New address of my CGI Course.


In reply to Efficient partial deep cloning by Ovid

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.