require()

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

require()

Markus Huber
First of all the main program require(FileA) and FileA then
require(FileB) and if FileB now require(FileA) again then ups we
are falling into a loop. But why? Because FileA is already required with
the first call from the main prog.


Markus


Reply | Threaded
Open this post in threaded view
|

Re: require()

Luiz Henrique de Figueiredo
>First of all the main program require(FileA) and FileA then
>require(FileB) and if FileB now require(FileA) again then ups we
>are falling into a loop. But why? Because FileA is already required with
>the first call from the main prog.

This seems correct to me: "require" is for loading libraries and your hierarchy
of libraries has a loop. For executing code, use "dofile".
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: require()

Markus Huber
Dear Luiz,

> > First of all the main program require(FileA) and FileA then
> > require(FileB) and if FileB now require(FileA) again then ups we
> > are falling into a loop. But why? Because FileA is already required
> > with the first call from the main prog.

> This seems correct to me: "require" is for loading libraries and
> your hierarchy of libraries has a loop.

Correct I have a loop and would like to arrange with it instead of a
dull redesign. Each of two simple libs thematically separated need the
opposite one. Isn't require() designed to load/require one file only
once? dofile doesn't help here because if five libs need the XML lib
then the XML lib is dofiled five times! I know I can arrange an own
solution to suppress both behaviours (patch require or check if a
file is already slowly dofiled) but I feel that require() should do this
alone. Now require isn't so much usefull as it could be. And I don't see
arguments to let require() as it is.


Markus


Reply | Threaded
Open this post in threaded view
|

Re: require()

Wim Couwenberg-2
Hi,

> I know I can arrange an own
> solution to suppress both behaviours (patch require or check if a
> file is already slowly dofiled) but I feel that require() should do this
> alone. Now require isn't so much usefull as it could be. And I don't see
> arguments to let require() as it is.

Well circular module dependencies _may_ cause trouble and can therefore not
easily be supported in general.  In some cases, the following might work.
Mark the module as loaded (in the global _LOADED table) just before
"luaB_require" runs the module (in lbaselib.c, ln 480 for lua5.0b) instead
of afterwards.  This prevents cyclic loading of packages.  If the modules
involved do not actually use any other module's variables in their _global_
scope then this will do the trick.  In other cases the behavior may be
unpredictable... [!]

Btw, generically speaking,  it will be possible to factor out the "common"
stuff in cyclic dependencies, thereby breaking the cycles.  I think this
should be the preferred method, though it may take some (tricky) redesign.

Bye,
Wim



Reply | Threaded
Open this post in threaded view
|

RE: require()

Bilyk, Alex
In reply to this post by Markus Huber
That's what I did in our project. The dofile was overloaded in order to load a file once. That was in Lua 4. Stack overflow is pretty silly IMHO and I would assume is a result of scarce human resources dedicated to official Lua implementation. I would allow loops and either complain about them to stderr or just let people work out run-time issues (if any) produced by such loops on their own rather than producing stack overflows. On the other hand, it is really easy to implement this in Lua itself and so it doesn't seem to be a big deal to me, just not pretty.   

AB

-----Original Message-----
From: Wim Couwenberg [[hidden email]]
Sent: Thursday, January 23, 2003 1:37 PM
To: Multiple recipients of list
Subject: Re: require()

Hi,

> I know I can arrange an own
> solution to suppress both behaviours (patch require or check if a
> file is already slowly dofiled) but I feel that require() should do this
> alone. Now require isn't so much usefull as it could be. And I don't see
> arguments to let require() as it is.

Well circular module dependencies _may_ cause trouble and can therefore not
easily be supported in general.  In some cases, the following might work.
Mark the module as loaded (in the global _LOADED table) just before
"luaB_require" runs the module (in lbaselib.c, ln 480 for lua5.0b) instead
of afterwards.  This prevents cyclic loading of packages.  If the modules
involved do not actually use any other module's variables in their _global_
scope then this will do the trick.  In other cases the behavior may be
unpredictable... [!]

Btw, generically speaking,  it will be possible to factor out the "common"
stuff in cyclic dependencies, thereby breaking the cycles.  I think this
should be the preferred method, though it may take some (tricky) redesign.

Bye,
Wim



Reply | Threaded
Open this post in threaded view
|

Re: require()

Peter Hill-2
In reply to this post by Wim Couwenberg-2
Wim Couwenberg:
> Well circular module dependencies _may_ cause trouble and can therefore
> not easily be supported in general.
...
> Btw, generically speaking,  it will be possible to factor out the "common"
> stuff in cyclic dependencies, thereby breaking the cycles.  I think this
> should be the preferred method, though it may take some (tricky) redesign.

Hmm, I hadn't thought about circular require() but you have a point.

To help detect such errors perhaps _LOADED should have three states for a
library:
- unloaded
- partially loaded (set when require() starts).
- loaded (set when require() ends).

An attempt to require() a partially-loaded library will report an error
about circular library references (and will abort the load, even if the
error function choses to 'continue' processing).

That way we get circular-reference errors if we stuff up, and if someone
actually wants a certain circular reference then they can explicitly
override the error function around the require() call.

*cheers*
Peter Hill.



Reply | Threaded
Open this post in threaded view
|

Re: require()

Markus Huber
In reply to this post by Markus Huber
> "Peter Hill" <corwin@i...> wrote:

> Hmm, I hadn't thought about circular require() but you have a point.

> To help detect such errors perhaps _LOADED should have three states
> for a library:
> - unloaded
> - partially loaded (set when require() starts).
> - loaded (set when require() ends).

Now you get the point. In more detail both ways are usefull:

- mark as loaded on start of the required file
  it must be already loaded to start
  and inside the table is named _LOADED
- mark as finished initialised
  but this second form is *useless* in conjunction with require()
  require() never now if init of the required file was successfull
  so for that point you have to implement an own check system

> An attempt to require() a partially-loaded library will report an
> error about circular library references (and will abort the load, even
> if the error function choses to 'continue' processing).

I don't think that this is an error. Its an big mistake is to protect
the user against programming "errors". Especially Lua is so well
designed to give a enormous freedom.

> That way we get circular-reference errors if we stuff up, and if
> someone actually wants a certain circular reference then they can
> explicitly override the error function around the require() call.

Using loops is the base of programming! Do you allow recursive
progamming? Then why? Its a good place for infinity errors. So disallow
it. You won't do that right? Then: I can't see any good argument to
disallow a loop usage with require().

And has to override it each time he needs require(). I don't accept this
overhead. The question is why is there a require() loop? Do you write
programms and surprisingly there is a require() loop you don't like? I
don't think so.

I have already patched require to set the correct behaviour.



Markus


Reply | Threaded
Open this post in threaded view
|

Re: require()

Jay Carlson
In reply to this post by Wim Couwenberg-2
"Wim Couwenberg" <[hidden email]> writes:

> Hi,
>
> > I know I can arrange an own
> > solution to suppress both behaviours (patch require or check if a
> > file is already slowly dofiled) but I feel that require() should do this
> > alone. Now require isn't so much usefull as it could be. And I don't see
> > arguments to let require() as it is.
>
> Well circular module dependencies _may_ cause trouble and can therefore
not
> easily be supported in general.  In some cases, the following might work.
> Mark the module as loaded (in the global _LOADED table) just before
> "luaB_require" runs the module (in lbaselib.c, ln 480 for lua5.0b) instead
> of afterwards.  This prevents cyclic loading of packages.  If the modules
> involved do not actually use any other module's variables in their
_global_
> scope then this will do the trick.  In other cases the behavior may be
> unpredictable... [!]

This is what I did in my require() implementation for 4.0, by analogy to
this C idiom:

#ifndef _FOO_H
#define _FOO_H

#include <bar.h>
#include <baz.h>

/* foo.h body goes here */
#endif

If nested includes call for this header, it will only be included once. This
seems natural to C people, at least....

By the way, it can be quite useful to have access to the body of the _LOADED
table; at some point, this was not accessible to Lua code.  I'm too lazy to
look at 5.0 right now.

Jay