←  Ask a Pro

ComputerCraft | Programmable Computers for Minecraft

»

call copy function from within a program

Nex4rius's Photo Nex4rius 17 Jul 2017

In OpenComputers you could do
local copy = loadfile("/bin/cp.lua")
copy("1", "2")
and it would copy the file but in ComputerCraft when I try
local copy = loadfile("/rom/programs/copy")
copy("1", "2")

I'm getting an error.
Posted Image

What am I doing wrong?
Quote

Bomb Bloke's Photo Bomb Bloke 17 Jul 2017

You're trying to call a function that doesn't exist. Try fs.copy() instead.
Quote

KingofGamesYami's Photo KingofGamesYami 18 Jul 2017

Note that loadfile does exist, and does work. You're simply not pointing to the correct file (which would be shell.resolveProgram( "copy" )). It's much better practice to call fs.copy directly though, and there are some environment issues associated with loadfile (shell would be nil).
Quote

Bomb Bloke's Photo Bomb Bloke 18 Jul 2017

Gah, I skimmed.

Truth be told he is pointing to the "correct" file, it's just the shell table missing from the environment that leads to the error.

Still: use fs.copy().
Quote

Nex4rius's Photo Nex4rius 18 Jul 2017

Thanks :)

But why is the shell table missing?
Quote

Bomb Bloke's Photo Bomb Bloke 18 Jul 2017

A ComputerCraft computer loads a number of APIs on boot, each of which is basically a collection of functions (eg "copy") shoved into a table (eg "fs") which then goes into _G. Most code can access _G and hence see those APIs.

However, the global environment table our scripts use is not _G. Rather, the tables are unique ones generated by the CraftOS shell, through which we can access _G's contents (via metatable magic), but not so readily fill _G with our globals. I assume this system is intended to stop newbies who know nothing about environments / scope from making too much of a hash of things.

Because a system can run multiple shell instances at the same time, and each of those instances will have their own idea about such things as where the current working directory might be, the shell "API" isn't placed within _G - rather, each shell instance dumps its function table into its own unique environment.

loadfile doesn't use that environment unless you specifically tell it to, so: no shell table for your loaded function. You could getfenv the current environment and pass as a second argument to loadfile, though, if you really wanted to.

(I suspect there'll be a bit of that happening once 1.80 hits - as of that build, not only does each shell instance have its own environment table, but so does every script you start via shell.run().)
Quote

Nex4rius's Photo Nex4rius 18 Jul 2017

Thanks for the explanation.
I don't need multiple shell instances. My program is seperated into multiple files and I'm too lazy to change all loadfiles with getfenv so I'm taking the "easy" way and just include
_G.shell = shell
at the start.
Quote