Posted 18 July 2017 - 01:13 PM
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().)