Advanced function replacement
KaoS 19 Sep 2012
Jajnick 19 Sep 2012
Uh... Did I say something wrong?
I'm just asking why the original post is so long, while it can be shortened and be even more understandable... Why are you raging at me?
I'm just asking why the original post is so long, while it can be shortened and be even more understandable... Why are you raging at me?
KaoS 19 Sep 2012
Jajnick, on 18 September 2012 - 06:15 PM, said:
This article in a nutshell:
I don't really see the point of this wall of text.
Quote
Functions are values
I apologise if I offended you, we were just looking at various methods of replacing existing functions, most functions are stored in a table and I wanted to be able to locally change a function, not globally. this caused multiple issues, I have worked it out now though. that was the point for me, not sure about the other people. what I was saying is that these forums are here so we can assist each other in learning CC and showing others what we have learned. please try to avoid criticising other threads. that was pretty much my point
ElvishJerricco 05 Oct 2012
Jajnick, on 19 September 2012 - 09:46 AM, said:
Uh... Did I say something wrong?
I'm just asking why the original post is so long, while it can be shortened and be even more understandable... Why are you raging at me?
I'm just asking why the original post is so long, while it can be shortened and be even more understandable... Why are you raging at me?
Sorry about being late to this conversation...
The reason it's so long is to show examples and give a very clear understanding of the concept. In most compiled languages, functions and methods aren't values in the same way they are in lua. It's a concept that's weird to grasp coming from C or Java. But lua is a scripting language, and in most scripting languages functions work the way they do here. If i told a novice lua programmer that functions are values and said the symbols can be redefined, they wouldn't really know what to do with it. The tutorials forum is meant to have deep explanation of each topic. That's what i tried to do.
FunshineX 05 Oct 2012
Be careful when you replace functions and save a backup pointer. If you run the program multiple times you'll get unexpected results. Best to os.reboot() in between to restore the originals
ElvishJerricco 06 Oct 2012
FunshineX, on 05 October 2012 - 09:18 PM, said:
Be careful when you replace functions and save a backup pointer. If you run the program multiple times you'll get unexpected results. Best to os.reboot() in between to restore the originals
Where would the issue arise? Only thing I can think of is if you don't check to see if someFunction already equals myReplacementFunction, then when you do the replacement again it ends up replacement calling old (identical besides the pointer to the function) replacement calling original. And yea I guess that's a pretty big problem...
FunshineX 07 Oct 2012
ElvishJerricco, on 06 October 2012 - 04:43 AM, said:
Where would the issue arise? Only thing I can think of is if you don't check to see if someFunction already equals myReplacementFunction, then when you do the replacement again it ends up replacement calling old (identical besides the pointer to the function) replacement calling original. And yea I guess that's a pretty big problem...
The 4th block of code in the original post suffers from this
ElvishJerricco 08 Oct 2012
FunshineX, on 07 October 2012 - 08:00 AM, said:
ElvishJerricco, on 06 October 2012 - 04:43 AM, said:
Where would the issue arise? Only thing I can think of is if you don't check to see if someFunction already equals myReplacementFunction, then when you do the replacement again it ends up replacement calling old (identical besides the pointer to the function) replacement calling original. And yea I guess that's a pretty big problem...
The 4th block of code in the original post suffers from this
In that case it's actually intentional. You'll notice I said that I'd only do that code if I were writing my own OS, where I want to manage all the Apis and I want to control the print statement for all of runtime. The replacement should only get called once for the entire lifetime of the computer from bootup to shutdown
tiin57, on 07 October 2012 - 08:39 AM, said:
As long as this post is revived, good job, ElvishJerrico.
Thanks :3
Cabu 21 Nov 2012
Hi,
I am new to lua and computercraft, but i am writing an API for advanced turtle functions like turnTo(direction) and moveTo(X, Y, Z, direction). They work pretty well now. But i want to integrate my API deeper into the system.
For now to keep track of the turtle position, I read its GPS position once and the api user should not use the turtle.forward() / turtle.back() / turtle.up() / turtle.down() / turtle.turnLeft() / turtle.turnRight() anymore but the my API equivalents one.
I would like to override the turtle functions by my own, but i still need in my own function be able to call the original function and the local variable of my API.
Here is an extract of my API:
An you use it like that:
I am new to lua and computercraft, but i am writing an API for advanced turtle functions like turnTo(direction) and moveTo(X, Y, Z, direction). They work pretty well now. But i want to integrate my API deeper into the system.
For now to keep track of the turtle position, I read its GPS position once and the api user should not use the turtle.forward() / turtle.back() / turtle.up() / turtle.down() / turtle.turnLeft() / turtle.turnRight() anymore but the my API equivalents one.
I would like to override the turtle functions by my own, but i still need in my own function be able to call the original function and the local variable of my API.
Here is an extract of my API:
-- Cache of the current turtle position and direction local cachedX, cachedY, cachedZ, cachedDir -- Directions North, West, South, East, Up, Down = 0, 1, 2, 3, 4, 5 local deltas = {[North] = {0, 0, -1}, [West] = {-1, 0, 0}, [South] = {0, 0, 1}, [East] = {1, 0, 0}, [Up] = {0, 1, 0}, [Down] = {0, -1, 0}} -- cache world geometry local cachedWorld = {} ... function forward() local D = deltas[cachedDir] local x, y, z = cachedX + D[1], cachedY + D[2], cachedZ + D[3] local idx_pos = x..":"..y..":"..z if turtle.forward() then cachedX, cachedY, cachedZ = x, y, z -- update the position cache cachedWorld[idx_pos] = 0 -- clear the world cache return true else cachedWorld[idx_pos] = (turtle.detect() and 1 or 0.5) -- update the world cache return false end end ...
An you use it like that:
os.loadAPI("egps") if egps.startGPS() then local x, y, z, d = egps.locate() print(x, ' ', y, ' ', z, ' ', d) egps.forward() x, y, z, d = egps.cachedLocate() print(x, ' ', y, ' ', z, ' ', d) end
louitzie 22 Nov 2012
for my new os I want to override shell.run globaly so i can apply the right display settings depending on my own programs or default (rom) programs
tried code
i also tried without the _G
but it only changes localy.
any ideas are welcome.
found it.
if you ever want to do this override os.run instead
tried code
local run=shell.run _G.shell.run=function(command,...) --configuration code here return run(command,...)
i also tried without the _G
but it only changes localy.
any ideas are welcome.
found it.
if you ever want to do this override os.run instead
Orwell 22 Nov 2012
louitzie, on 22 November 2012 - 10:09 AM, said:
for my new os I want to override shell.run globaly so i can apply the right display settings depending on my own programs or default (rom) programs
tried code
i also tried without the _G
but it only changes localy.
any ideas are welcome.
found it.
if you ever want to do this override os.run instead
tried code
local run=shell.run _G.shell.run=function(command,...) --configuration code here return run(command,...)
i also tried without the _G
but it only changes localy.
any ideas are welcome.
found it.
if you ever want to do this override os.run instead
CoolisTheName007 25 Nov 2012
Cabu, on 21 November 2012 - 04:02 AM, said:
snip]
old_turtle=turtle turtle={} turtle.forward= function (args) stuff -here you want to go forward, so you do: old_turtle.forward() ect
Also, for the main discussion of altering code locally, I would arg that just replacing functions is incomplete, because internal functions in the API won't refer to the new one, but to the one that is still in the environment. A complete solution would be a dofile and tampering with the environment directly.
KaoS 25 Nov 2012
also: I should mention that you should be careful with stuff like this because sometimes you will run your program twice and it will double the code on the turtle commands. here is an example to explain
then if you say turtle.forward() it would move forward and output 'whoah! you just moved forwards!', then if you ran the above code again it would take the current turtle.forward() (including the print bit) and append another print onto it, then if you move forward it will print 'whoah! you just moved forwards!' twice which of course is a problem, the way to get around this is to make a variable recording if you have changed the command and prevent it from modifying it again
even easier is just to use the oldT table
some would call that un-neat as the oldT table is no longer local but I find it useful in case you need to use the original commands
local oldT=turtle turtle.forward=function(...) print('whoah! you just moved forwards!') return oldT.forward(...) --you want to always return whatever the oldT command would do so you still get back the output of the move CMD end
then if you say turtle.forward() it would move forward and output 'whoah! you just moved forwards!', then if you ran the above code again it would take the current turtle.forward() (including the print bit) and append another print onto it, then if you move forward it will print 'whoah! you just moved forwards!' twice which of course is a problem, the way to get around this is to make a variable recording if you have changed the command and prevent it from modifying it again
if not mod then local oldT=turtle mod=true turtle.forward=function(...) print('whoah! you just moved forwards!') return oldT.forward(...) --you want to always return whatever the oldT command would do so you still get back the output of the move CMD end end
even easier is just to use the oldT table
if not oldT then oldT=turtle turtle.forward=function(...) print('whoah! you just moved forwards!') return oldT.forward(...) --you want to always return whatever the oldT command would do so you still get back the output of the move CMD end end
some would call that un-neat as the oldT table is no longer local but I find it useful in case you need to use the original commands
CoolisTheName007 25 Nov 2012
KaoS 26 Nov 2012
AHAH, and behold I present unto you unparalleled genius. thanks for that idea CoolisTheName007, just remember not to do that is you are going to use a for loop to parse the turtle table and replace all functions unless you are careful and include a type(v)=='function' in it
CoolisTheName007 26 Nov 2012
KaoS, on 26 November 2012 - 02:19 AM, said:
snip
When using an old table , if you don't want to copy the API manually you may be interested in a deepcopy function. However, those often leave details such as metatables out, so I would rather use a replace on necessity method, such as
old_forward=turtle.forward
turtle.forward=function ...
KaoS 26 Nov 2012
yes, you are most correct.... an unforgivably n00b mistake on my side. don't forget to create a new table for turtle guys, I'm gonna go end my stupid misery lol, can't believe I just did that... when it comes to copying the other functions I would just use a metatable like so
turtle=setmetatable({},{__index=oldT})
turtle=setmetatable({},{__index=oldT})
ChunLing 30 Nov 2012
Why not just check if oldT already exists, so "if not oldT then oldT=turtle ...andotherstuff... end". Also, that way oldT is global so you don't lose it by going out of scope/unexpected termination.
No, nevermind, I see you already discussed all that.
Edited by ChunLing, 30 November 2012 - 12:40 PM.
No, nevermind, I see you already discussed all that.
Edited by ChunLing, 30 November 2012 - 12:40 PM.