This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Imque's profile picture

Higher Debug/Sandboxing Level & setfenv

Started by Imque, 14 April 2013 - 02:09 AM
Imque #1
Posted 14 April 2013 - 04:09 AM
Hi. What does one mean when saying higher debug or sandboxing level and I have had a look on the PIL and still don't quite understand what setfenv does. Maybe you can explain it and give an example?
SuicidalSTDz #2
Posted 14 April 2013 - 05:22 AM
The PIL explains it better than I ever could. Re-read it and think harder.
Bubba #3
Posted 14 April 2013 - 05:23 AM
setfenv is a way of setting the environment that a function runs in. The environment is the table of global variables that are persistent across programs. You can access the global table with _G. So for example if I wanted to access the term.getSize function from the global table, I could write:

local x, y, = _G["term"]["getSize"]()

Of course, there is no real reason to use _G when access global variables as it is much simpler to write:

local x,y = term.getSize()

Now setfenv, and its partner function getfenv, are functions that give us a high level of control over the _G table. In fact, if I use setfenv and set the environment to an empty table, the _G table disappears from the scope of the currently running function. For example:

local function brokenFunction()
   setfenv(1, {}) --The '1' describes the level at which we are manipulating the environment: 1 is for the current function, 2 is for the calling function
   print("lol")
end

brokenFunction()

When you run this function, it will error and give you an "attempt to call nil on line 3" due to the fact that the print function, which is usually stored in our global table, is no longer visible. Of course, we can populate the environment with a few of our own functions if we want to:

local function workingFunction()
  setfenv(1, {print = print, globals = _G})
  print("_G exists in the form of the 'globals' table now. Watch.")
  globals.print(globals.type( {} )) --Ima output 'table'
end

workingFunction()

As you might be able to imagine, this level of control over the global environment can be enormously useful when sandboxing a program.

Hopefully this will get you started on environments and setfenv. You really should go try to re-read the PIL because it is much more comprehensive.
Imque #4
Posted 14 April 2013 - 02:31 PM
Thanks Bubba. Is the default env level 0? (The env which already contains all the global stuff?)

EDIT: getfenv returns the current env?
Bubba #5
Posted 14 April 2013 - 04:51 PM
Thanks Bubba. Is the default env level 0? (The env which already contains all the global stuff?)

EDIT: getfenv returns the current env?

getfenv does indeed return the current environment.

Edit: By default env level are you talking about the default env level for getfenv()? If so, then I believe that 1 is indeed the default.
Smiley43210 #6
Posted 14 April 2013 - 09:28 PM
Thanks Bubba. Is the default env level 0? (The env which already contains all the global stuff?)

EDIT: getfenv returns the current env?
If you're thinking what I think you're thinking, no. The int level that you specify in setfenv is relative to the function that called setfenv, and not from the 'root'.

Think of it just like error()'s level parameter.
Imque #7
Posted 14 April 2013 - 09:38 PM
Ok thanks! I don't really a pratical use. What would you need to use this for?
Engineer #8
Posted 15 April 2013 - 10:06 AM
If you want to sandbox your program. So lets say, you want people to write a little snippet and you do not want them to use print or write. Than you set the environment that they cant use that.

This is a vague description…
JokerRH #9
Posted 15 April 2013 - 10:17 AM
Ok thanks! I don't really a pratical use. What would you need to use this for?

You have to use it for every function that shouldn't use the global enviroment.
os.loadAPI / os.run use it for example, but I used it to program object oriented, too. (You could find the program in the programs section :D/>)
Bubba #10
Posted 15 April 2013 - 10:31 AM
I used it to program object oriented, too. (You could find the program in the programs section :D/>)

Object orientation is much easier to do with metatables than setfenv…

local person = {
  mt = {
    __index = {
	  race = "Human";
	  stature = "Medium";
	  intelligence = "Medium/High";
    }
  };
  new = function(self, attr)
	 setmetatable(attr, self.mt)
	 return attr
  end;
}

local bob = person:new({
name = "Bob";
job = "Unemployed";
whatever = "etc. etc.";
})

print("I have successfully created a new person: "..bob.name)
print("He is of the race..": bob.race)
--etc. etc.
JokerRH #11
Posted 15 April 2013 - 10:41 AM
Object orientation is much easier to do with metatables than setfenv…

#1 You have to use self (if you forget the : it'll take you a long time debugging)
#2 A table has always the same function enviroment as it's creating function
#3 Extending a table with anotherone isn't that simple as extends(object)
#4 It is always getting unclear
Smiley43210 #12
Posted 15 April 2013 - 12:50 PM
Object orientation is much easier to do with metatables than setfenv…

#1 You have to use self (if you forget the : it'll take you a long time debugging)
#2 A table has always the same function enviroment as it's creating function
#3 Extending a table with anotherone isn't that simple as extends(object)
#4 It is always getting unclear
Meh, different people have different preferences, I personally prefer using metatables (it's more Java-like).
Bubba #13
Posted 15 April 2013 - 03:04 PM
Object orientation is much easier to do with metatables than setfenv…

#1 You have to use self (if you forget the : it'll take you a long time debugging)
#2 A table has always the same function enviroment as it's creating function
#3 Extending a table with anotherone isn't that simple as extends(object)
#4 It is always getting unclear

1) The way I did it yes. But you can easily create one that does not require you use a colon or self.


local mt = {
  __index = {
    stuff = "hi";
  }
}

local function newPerson(attr)
   setmetatable(attr, mt)
   return attr
end

bob = newPerson({
height=15;
})

2) That is not a disadvantage unless you want to sandbox the user, which is pointless for the majority of purposes.
3) I'm not sure what you're saying here, but if you are saying that using metatables is harder than using setfenv/getfenv, then IMO you're wrong. Metatables really aren't that difficult. Not to mention they are powerful. You have complete control over how the table works. Using metatables you can control what is done upon creating new values, make the table behave as a function, perform regular comparisons directly with the table, and more. You can't do that through a regular environment.
4) They're not unclear at all unless you make it that way.
Imque #14
Posted 15 April 2013 - 04:07 PM
What even is object orientation programing? (OOP)
Bubba #15
Posted 15 April 2013 - 04:58 PM
Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known as methods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.
'

Wikipedia has a pretty good definition of it, even if some people don't trust that as a source. It's good enough to get basic knowledge.
JokerRH #16
Posted 16 April 2013 - 10:22 AM
@Smiley: No. The fenv way is way more like java :P/>
Smiley43210 #17
Posted 16 April 2013 - 10:40 AM
@Smiley: No. The fenv way is way more like java :P/>
Java:
(I don't remember what parameters are needed to create these objects)
private JPanel container = new JPanel(); // I think I forgot the LayoutManager or something...
private JLabel myButton = new JButton("Label Text");
container.add(myButton);
container.revalidate();
container.repaint();

Lua:
container = Container:new()
btnSend = Button:new("Button Text")
container:addObject(btnSend)
container:drawAll()

Similarity?

#derailed
JokerRH #18
Posted 16 April 2013 - 10:45 AM
Look at the api I created, it is way more like java than table oop.
But I actually got a feeling that we're getting offtopic :D/>