I was wondering if there's a way to do a lua file only once and have any subsequent attempts to do that lua file will result in a no-op.
I've already thought about doing something akin to C++ header's #if/else/endif trick. I'm wondering if there's a standard way to implement this.
James
well, require pretty much does that.
require "file" -- runs "file.lua"
require "file" -- does not run the "file" again
The only problem with require is that it works on module names, not file names. In particular, require does not handle names with paths (although it does use package.path and package.cpath to locate modules in the file system).
If you want to handle names with paths you can write a simple wrapper to dofile as follows:
do
local cache={}
local olddofile=dofile
function dofile(x)
if cache[x]==nil then
olddofile(x)
cache[x]=true
end
end
end
based on lhf's answer, but utilising package, you can also do this once:
package.preload["something"]=dofile "/path/to/your/file.lua"
and then use:
local x=require "something"
to get the preloaded package again. but that's a bit abusive...
Related
So in lua, i want to import a module.
I want to have my "polygon" lib in a subfolder, so i reference it like this
local polygon = require('polygon.polygon')
however, it needs another module called 'delaunay', it cannot find it as it checks the main folder
Is there anyway short of editing my library, to get this to work? (some kind of ability to add search paths?)
Thanks
To know where to look for modules, Lua's require uses the variables package.path (.lua) and package.cpath (.so/.dll). You can change them in your program to look in the directory you have it in. For consistency's sake, you can look at their contents to know which OS-specific separator to use. For example:
local sep = package.path:find("\\") and "\\" or "/"
package.path = package.path .. ";." .. sep .. "polygon" .. sep .. "?.lua"
This would include ./polygon/?.lua into the search path, and a call to require "delaunay" would therefore have the require function look for ./polygon/delaunay.lua in addition to existing paths. Bear in mind that in require strings, . denotes a separator as far as file searching is concerned, so calling require "polygon.delaunay" in this scenario will mean searching for ./polygon/polygon/delaunay.lua.
From what I understand of your question, changing the package.path variable to include the path to where your delaunay library is stored would solve your issue, although to give a specific solution more information about your project and directory structure is required.
All what loaded into package.loaded can be load with require() because require() looks first in package.loaded...
-- Lua 5.3 ( lua -i )
> package.loaded.code=load(code.dump)()
> test=require('code')
> test
function: 0x565cb820
So you can use load() or loadfile('/path/to/your_code.lua') to do this. Another nice feature of this method is to load dumped code...
> package.loaded.shell=loadfile('shell.bin')
> shell=require('shell')
> shell('cat shell.bin')
uaS�
�
xV(w#F#�d�#��F�#G���d#��F�#G���d#&�typestringoexecute
/bin/bash>
In any way, it appears that you will have to deal with the subfolders explicitly.
As in, either the module polygon will have to import delaunay as polygon.delaunay.
Or module names will have to be appended to package.path so that lua could search through subfolders for filenames:
package.path=package.path..";./polygon/?.lua"
More info is here.
It is pointed out in comments, you'd probably want to ensure that path concatenation happens only once.
Also, one should be wary of name shadowing.
Finally, while we are at stirring up the past, a pretty nifty trick to solve the issue was proposed here five years before the question.
I have been writing a lot of turtle programs lately and find that I am constantly rewriting the same functions. I would like to put all these functions into their own file and then include them at the top of my other turtle programs. Looking through the lua documentation it seems I need to use require. However I can't seem to get it to work. Here is a basic example I tried:
program1:
print("Hello World")
program2
require program1
This resulted in the following error:
bios:366: [string "program2"]:1: '=' expected
I then tried setting the package path to the current directory before making the require statement like this:
package.path = package.path .. ';./?.lua;'
That also didn't work. It seem that turtles don't use the same syntax as lua for the require statement (if they support it at all)
Is there a way to do something like this with the turtles? If it is using 'require' then what is the proper syntax? (I don't have access to the files of the server I play on so simply editing them is not an option)
require is a function; you need to call it using function syntax:
require("foo")
-- or
require "foo"
...but it doesn't look like ComputerCraft supports the require function. Try os.loadAPI("path/to/file").
(Dear developers wanting to sandbox Lua: require supports configuring how it loads modules; please use that instead of replacing require!)
You need to put program1 in quotes:
require "program1"
For example:
require('a.b.c/foo.lua')
Lua engine will translate 'a.b.c/...' to 'a/b/c/...' to search file in the pattern list, right?
Will there be any problem when 'a.b.c' are real folder name? If so, how to solve that?
If your module is located in a directory that contains . as part of its name, pulling it in with require will be difficult since there's no way to 'escape' that . so the \ substitution isn't done.
However, it may still be possible to point lua to look in the right place indirectly by playing with the package.path:
local restorepath = package.path
package.path = "./a.b.c/?.lua"
require 'foo'
package.path = restorepath
But I'd recommend that you try to reorg your project directory structure first so it better works with lua's require. Otherwise you'll have to do keep doing the above dance with other modules you might have.
Such translation is not on the spec, as far as I know. So it might work, but it might also not work. It might break on some platforms (i.e. work on Linux and Mac and not on Windows). It might work in one version of Lua and not on the next. So I would not recommend it.
The way to make sure you stay platform-agnostic is using dots everywhere. Also, I would recommend not putting the .lua part at the end, require does not always resolve that well either:
require('a.b.c.foo')
I have something like this.
/config.lua
/client/init.lua
How can I include the config.lua with include() or dofile()?
Lg
You can (and probably should) do this with require by adding ../?.lua to package.path, like so:
package.path = package.path .. ";../?.lua"
require "config"
See the require and package.path docs for more info.
You're on the right track with dofile. (However, there is no include function in Lua.) As you may have noticed, you can't do this with require:
local cfg = require'../config'
require typically works from the directory of the initial script in a one-way direction, and any required modules which require their own modules must use relative names from that starting point to work properly.
I.e., if you have the following structure:
--+ main.lua requires 'lib.test1'
+-- lib/test1.lua requires 'test2'
+-- lib/test2.lua
test1.lua will fail to require test2 because it cannot be found from the initial directory. lib.test2 is the appropriate module name here. I'm not sure if there are any good patterns for this, short of writing your own stateful require, but it's helpful to know about when writing library code.
Perhaps it's a bad sign when it comes to this.
Going back to the question, you could make an exemption for your config file in package.loaded. This is effectively loading it manually:
package.loaded.config = dofile'../config.lua'
-- ...
local cfg = require'config'
I need to call the require on a lua file that will not always be in the same place. I was trying to call require on the full path name but that doesn't seem to be working either. I even tried replacing one of my working normal requires with a correct full path name to the same file
example changing
require "foo"
to
require "C:\Users\Me\MyLuaProject\foo"
but when i switched it to the full path name it could no longer find it. So I am wondering if you can even call require on a full path and if not how would i achieve the same result differently?
If you just need to load a file, use dofile, which takes a path:
dofile("C:\\Users\\Me\\MyLuaProject\\foo")
Add the directory containing the file to package.path:
package.path = package.path .. ";C:\\Users\\Me\\MyLuaProject"
require "foo"
You can also add it to the LUA_PATH environment variable, but this is probably less easy to modify on the fly.
A common pattern for modules is to have abc.lua and abc/xyz.lua; to require files in a subdirectory like that, use the following:
require "abc"
require "abc.xyz"