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"
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.
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 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"
I've been working with Love2d recently to build a Conway's Game of Life implementation.
I really like the framework, but I haven't been able to figure out how to modularize my code, which I feel is crucial to solid code structure.
What I'm wanting to do is be able to import a file that has different functions in it and be able to access that through my main lua file. I have been able to write scripts and run entire files, but not specific functions.
Is there a way to do this in Lua? If so, how?
Thanks!
You can use the require function in LÖVE. It works similarly to how it works in Lua.
-- lib.lua
local lib = {} -- table to store the functions
function lib.inc(x)
return x + 1
end
return lib
And here is how you require it in another file (for example, main.lua) and use it:
local lib = require('lib')
function love.load()
print(lib.inc(1)) -- prints '2' in the terminal
end
Lua supports modules. Here is a tutorial on using them http://lua-users.org/wiki/ModulesTutorial
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...