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

[not urgent] enviroment probblems

Started by BigSHinyToys, 31 August 2012 - 03:26 AM
BigSHinyToys #1
Posted 31 August 2012 - 05:26 AM
I have been trying to understand how environments in lua work and built this script to test.

The Fprint function is meant to be a copy of print but in its own environment and with a altered term.getSize() altered so a scroll bar could be on the right side. doing it this way i had hoped that i would not have to write a custom print function that left the required space.

the print is meant to be as normal in the _G environment when created by bios as normal. but some how the changes made to Fprint affect print as well I have done something wrong here or misunderstand something.

This is not a urgent matter and thanks for any help rendered.
Spoiler

--[[term.clear()
term.setCursorPos(1,1)
local apiTerm = term
term.getSize = function()
	local termX,termY = apiTerm.getSize()
	return termX-2,termY
end
]]--
termX,termY = term.getSize()
print(termX.." "..termY)
Fprint = print
local diffenv = {}
diffenv["back"] = {}
diffenv["back"]["back"] = term.getSize
setmetatable( diffenv, { __index = _G } )
setfenv( Fprint, diffenv )
diffenv["term"]["getSize"] = function()
	local termX,termY = diffenv.back.back()
	return termX-5,termY
end


testText = [[TEST
test 1
this is a test of my text viewer function. There shoudl be no text in the two spaces on the X line next to eatch line theis is where a scroll bar should be.]]
term.clear()
term.setCursorPos(1,1)
print(testText)
Fprint(testText)
Lyqyd #2
Posted 31 August 2012 - 06:57 AM
Fprint and print are identical in your example; changes to the environment of one affect both, since you can use either name to refer to the one function.

Honestly, I'm a little surprised it worked for both instead of neither, which I would have picked as the more likely outcome.
BigSHinyToys #3
Posted 31 August 2012 - 07:38 AM
looking at the code I didn't ever think it would work at all but it sorta did.

So Fprint and print are both a link to the same function meaning when I change environment for one it apples to both? if so how do I clone print into Fprint making it two separate function then apply my term.getSize changes?
KaoS #4
Posted 31 August 2012 - 07:40 AM
replace 'local apiTerm = term' with

local apiTerm=textutils.unserialize(textutils.serialize(term))
if you don't then when you say apiTerm=term then it links them both to a table reference so any changes to one effect the other

Explanation:
Spoilerif you say print(term) it will print table*reference number* rather than the actual table. that string is a reference to an object in Lua (the object is in fact your table) so if you say apiTerm=term you are just telling it to use the same reference and therefore refer to THE SAME TABLE that is stored in the Lua environment somewhere so if you change anything it looks up that table and modifies it, both references point to the same table so they will both read the same change

we serialize the table to convert it to text which is now entirely separate from the table reference, unserialize it and it creates a new table rather than link to the old one
ardera #5
Posted 31 August 2012 - 10:33 AM
replace 'local apiTerm = term' with

local apiTerm=textutils.unserialize(textutils.serialize(term))
if you don't then when you say apiTerm=term then it links them both to a table reference so any changes to one effect the other

Explanation:
Spoilerif you say print(term) it will print table*reference number* rather than the actual table. that string is a reference to an object in Lua (the object is in fact your table) so if you say apiTerm=term you are just telling it to use the same reference and therefore refer to THE SAME TABLE that is stored in the Lua environment somewhere so if you change anything it looks up that table and modifies it, both references point to the same table so they will both read the same change

we serialize the table to convert it to text which is now entirely separate from the table reference, unserialize it and it creates a new table rather than link to the old one

I think it will fail, because textutils.serialize connot serialize functions.

use the deepcopy function of the lua-users wiki:


function deepcopy(object)
  local lookup_table = {}
  local function _copy(object)
  if type(object) ~= "table" then
	return object
  elseif lookup_table[object] then
	return lookup_table[object]
   end
   local new_table = {}
   lookup_table[object] = new_table
   for index, value in pairs(object) do
	 new_table[_copy(index)] = _copy(value)
   end
   return new_table
end
return _copy(object)
end
It helped me too.

If you want to run a function with for example a different screen resolution, you can deepcopy the _G table, (otherwise it will create a "link" to the _G table), and replace term.getSize function (how you did) so this is the correct code:

function deepcopy(object) --the deepcopy function
  local lookup_table = {}
  local function _copy(object)
  if type(object) ~= "table" then
	return object
  elseif lookup_table[object] then
	return lookup_table[object]
   end
   local new_table = {}
   lookup_table[object] = new_table
   for index, value in pairs(object) do
	 new_table[_copy(index)] = _copy(value)
   end
   return new_table
end
return _copy(object)
end

g2=deepcopy(_G) --copies the global table
setfenv(youfunction, g2) --sets the environment of your function to g2
yourfunction() --runs your function
KaoS #6
Posted 31 August 2012 - 11:13 AM
you are right lol… blonde moment
Lyqyd #7
Posted 31 August 2012 - 03:44 PM
This really is the wrong way to go about it, though. You'd be better off using terminal redirection.
Magus #8
Posted 31 August 2012 - 04:38 PM
you can also create the environment without copying anything

env = setmetatable(
   { term = setmetatable({}, { __index = term }), { __index = _G } )

env.term.getSize = function () 
-- your code here

end