Factory function, nested tables, modules, and environment

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Factory function, nested tables, modules, and environment

Marc Lepage
Hi,

I would like to have a factory function node(t) which returns an object (a table is fine). I would like these to be able to nest. If node just returns t, this works:

A = node { }
B = node { node {} }

In this case, A is a node with no children, and B is a node with one child.

Now, I want to be able to make these in modules. Supposing I expect to find a tree root in mod.tree, then this is fine:

----- BEGIN MODULE -----
return {
    tree = node { node {}, node { node {} } }
}
----- END MODULE -----

And if I configure a table and environment (like the module function), I can omit the table creation:

----- BEGIN MODULE -----
tree = node { node {}, node { node {} } }
----- END MODULE -----

So far so good, that is semantically what I want. But I'd like to make the syntax simpler, something like:

----- BEGIN MODULE -----
node {}
node { node {} }
----- END MODULE -----

where the root level mod.tree node is implicitly made, and the top level nodes in the module implicitly add themselves as children to the root level node.

In other words, previous two modules produce the same result, just differ in syntax.

This means, in the above syntax, that the two top level nodes have to add themselves to the implicit tree root node, but the child node must not do that.

So, any suggestion as to techniques to accomplish something like this?

Thanks,
Marc

Reply | Threaded
Open this post in threaded view
|

Re: Factory function, nested tables, modules, and environment

Choonster TheMage
On 2 December 2013 05:21, Marc Lepage <[hidden email]> wrote:

> Hi,
>
> I would like to have a factory function node(t) which returns an object (a
> table is fine). I would like these to be able to nest. If node just returns
> t, this works:
>
> A = node { }
> B = node { node {} }
>
> In this case, A is a node with no children, and B is a node with one child.
>
> Now, I want to be able to make these in modules. Supposing I expect to find
> a tree root in mod.tree, then this is fine:
>
> ----- BEGIN MODULE -----
> return {
>     tree = node { node {}, node { node {} } }
> }
> ----- END MODULE -----
>
> And if I configure a table and environment (like the module function), I can
> omit the table creation:
>
> ----- BEGIN MODULE -----
> tree = node { node {}, node { node {} } }
> ----- END MODULE -----
>
> So far so good, that is semantically what I want. But I'd like to make the
> syntax simpler, something like:
>
> ----- BEGIN MODULE -----
> node {}
> node { node {} }
> ----- END MODULE -----
>
> where the root level mod.tree node is implicitly made, and the top level
> nodes in the module implicitly add themselves as children to the root level
> node.
>
> In other words, previous two modules produce the same result, just differ in
> syntax.
>
> This means, in the above syntax, that the two top level nodes have to add
> themselves to the implicit tree root node, but the child node must not do
> that.
>
> So, any suggestion as to techniques to accomplish something like this?
>
> Thanks,
> Marc
>
I've written a `node` function that can create a tree implicitly with
the first call and add non-child nodes to it, but I don't think
there's any way to add that tree to the module's environment unless
you explicitly assign it like in your second example or you call an
initialisation function in each module and pass it the environment
table as an argument. There may or may not be a way around this using
the debug library.

I've attached my implementation of the `node` function and a small
script to test its functionality.

Regards,
Choonster

nodes.lua (960 bytes) Download Attachment
nodes_test.lua (706 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Factory function, nested tables, modules, and environment

Chris Emerson
In reply to this post by Marc Lepage
Hi,

On Sun, Dec 01, 2013 at 01:21:41PM -0500, Marc Lepage wrote:
[...]

> ----- BEGIN MODULE -----
> tree = node { node {}, node { node {} } }
> ----- END MODULE -----
>
> So far so good, that is semantically what I want. But I'd like to make the
> syntax simpler, something like:
>
> ----- BEGIN MODULE -----
> node {}
> node { node {} }
> ----- END MODULE -----
>
> where the root level mod.tree node is implicitly made, and the top level
> nodes in the module implicitly add themselves as children to the root level
> node.

You could have all nodes add themselves to the top level, but also have
them remove their children from it.

Chris

Reply | Threaded
Open this post in threaded view
|

Re: Factory function, nested tables, modules, and environment

Andrew Starks


On Sunday, December 1, 2013, Chris Emerson wrote:
Hi,

On Sun, Dec 01, 2013 at 01:21:41PM -0500, Marc Lepage wrote:
[...]
> ----- BEGIN MODULE -----
> tree = node { node {}, node { node {} } }
> ----- END MODULE -----
>
> So far so good, that is semantically what I want. But I'd like to make the
> syntax simpler, something like:
>
> ----- BEGIN MODULE -----
> node {}
> node { node {} }
> ----- END MODULE -----
>
> where the root level mod.tree node is implicitly made, and the top level
> nodes in the module implicitly add themselves as children to the root level
> node.

You could have all nodes add themselves to the top level, but also have
them remove their children from it.

Chris

That seems like a nice solution. It makes everything consistent and would work for re- rooting branches, if you made the new parent search upward, recursively. 
Reply | Threaded
Open this post in threaded view
|

Re: Factory function, nested tables, modules, and environment

Sven Olsen
In reply to this post by Marc Lepage
This means, in the above syntax, that the two top level nodes have to add themselves to the implicit tree root node, but the child node must not do that.

As others have shown, this is certainly doable, provided you're willing to track and maintain a few supplemental datastructures.  But it feels unnecessary.  What are we gaining by attaching two different semantics to a single function name?  Why not use a tree configuration file like:

  add_node {}
  add_node { node{}, node {}  }

It might actually be easier to read, and it would certainly be simpler to implement.

Over-optimizing for simple syntax can be every bit as dangerous as over-optimizing for computational efficiency.  And I'll admit that that's a lesson I've had to learn from personal experience :-P

-Sven
Reply | Threaded
Open this post in threaded view
|

Re: Factory function, nested tables, modules, and environment

Marc Lepage
On Mon, Dec 2, 2013 at 5:54 PM, Sven Olsen <[hidden email]> wrote:
This means, in the above syntax, that the two top level nodes have to add themselves to the implicit tree root node, but the child node must not do that.

As others have shown, this is certainly doable, provided you're willing to track and maintain a few supplemental datastructures.  But it feels unnecessary.  What are we gaining by attaching two different semantics to a single function name?  Why not use a tree configuration file like:

  add_node {}
  add_node { node{}, node {}  }

It might actually be easier to read, and it would certainly be simpler to implement.

Over-optimizing for simple syntax can be every bit as dangerous as over-optimizing for computational efficiency.  And I'll admit that that's a lesson I've had to learn from personal experience :-P

-Sven

These are all good suggestions, thanks everyone.