Jump to content




Advanced function replacement


59 replies to this topic

#21 Cranium

    Ninja Scripter

  • Moderators
  • 4,031 posts
  • LocationLincoln, Nebraska

Posted 17 August 2012 - 04:20 PM

Ah...I gotcha. I did not see that. I just saw the last few posts, and assumed.... I fail.

#22 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 17 August 2012 - 04:21 PM

ah I know, you cannot apply a local change to a specific table value, what you do is simply

local os=os --making a local table that you can now modify
os.pullEvent=os.pullEventRaw

and that should do it

#23 Cranium

    Ninja Scripter

  • Moderators
  • 4,031 posts
  • LocationLincoln, Nebraska

Posted 17 August 2012 - 04:27 PM

Makes sense. My brain is hurting from other things today, and I can't focus on much else...

#24 ElvishJerricco

  • Members
  • 803 posts

Posted 17 August 2012 - 07:11 PM

View Postimmibis, on 17 August 2012 - 08:08 AM, said:

You should probably mention that functions are values (technically "first class objects") in Lua. That's why
function foo()
print("Hi!")
end
and
foo = function()
print("Hi!")
end
are exactly equivalent (in fact, the first gets translated into the second when Lua compiles it)

View PostElvishJerricco, on 01 August 2012 - 12:11 PM, said:

There's something interesting about step 4 though. We're not simply calling a function. We're giving the location of the function with the "test" token,
You are reading the value from the variable "test", and calling it. There is nothing special about variables that happen to contain functions.


View PostElvishJerricco, on 01 August 2012 - 12:11 PM, said:

function myPrint(msg)
	-- calculate condition
	condition = conditionFindingFunction()
	
	-- compare to see if printing is allowed
	if condition then
		--call the backup of print() that get's made before this function is called
		printBackup(msg)
	end
end

-- backup print to printBackup so that we don't lose the original print
printBackup = print

-- replace print with myPrint
print = myPrint
print("Testing!")
If printBackup was local (to the file, or some other scope) then people couldn't just call printBackup to get around your restriction.

View PostElvishJerricco, on 01 August 2012 - 12:11 PM, said:

For some reason when calling a function stored in a table, you have to use a colon instead of a period before the key. I think it's because a period would ask for the value (for a function, the location of the function).

Wrong. Because functions are just values, you can get a function from a table the same way you get any other element in the table. window.print(msg) works fine, if the window object is programmed to work that way. However, in Lua it's very common for functions in tables to have the table itself as the first parameter, as there's no implicit "this" parameter like in Java.
window:print("hi") is just a shortcut for writing window.print(window, msg).

View PostKaoS, on 16 August 2012 - 08:07 AM, said:

I wonder if any functions you call from your program also get the local variables, something to investigate because if they do then if you call read() etc it will be using the local pullevent as well and should prevent termination, not sure
I'm guessing you mean something like
local os.pullEvent = os.pullEventRaw
Not only will that not work, it's a syntax error.

Yes after i wrote this tutorial i discovered why the colon is required for some things. I'll go ahead and update it. And
local os.pullEvent = os.pullEventRaw
is actually a syntax error. The new local os table had never been declared as a table so you can't index it with .pullEvent.

Also, i understand that functions are first class objects, but that's just a fancy term for object with a pointer, which is a reference to a spot in memory that holds the actual object. My wording was less technical, but that was on purpose because not everyone is a programming pro.

#25 Cloudy

    Ex-Developer

  • Members
  • 2,543 posts

Posted 17 August 2012 - 08:18 PM

View PostKaoS, on 17 August 2012 - 04:21 PM, said:

ah I know, you cannot apply a local change to a specific table value, what you do is simply

local os=os --making a local table that you can now modify
os.pullEvent=os.pullEventRaw

and that should do it

Except that won't work. You'll be creating a local called os that is a reference to the real os - meaning changes that happen to the local happen to the main table.

#26 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 17 August 2012 - 08:58 PM

Whoah, that is the wierdest thing I have ever seen, I thought that if you declare a variable (like os), then set another variable to be equal to the first (like temp or whatever)
, then change temp os will remain the same as it is not equal to temp. it is the other way around...

in variables this is correct but in tables if you do the following
tableone={"01","02","03","04"}
tabletwo=tableone
tabletwo[3]=nil
then tableone[3] becomes nil as well.... all I have to say is wtf... the only way to change this is manually going through each value
local temp={}
for k in pairs(os) do
temp[k]=os[k]
end
local os=temp
temp=nil
then finally all changes made to os during the function are local only

I have no explanation for the first observation :(/> but atleast have finally worked out how to do it :)/> I tested it so I know it works

#27 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 18 August 2012 - 12:02 PM

View PostKaoS, on 17 August 2012 - 03:56 PM, said:

How is that a syntax error?
Because os.pullEvent is not a valid identifer (as it contains a dot)

View PostKaoS, on 17 August 2012 - 04:21 PM, said:

ah I know, you cannot apply a local change to a specific table value, what you do is simply

local os=os --making a local table that you can now modify
os.pullEvent=os.pullEventRaw

and that should do it

That makes "os" local, so if you do os=something then the change is not visible outside your program.

#28 ElvishJerricco

  • Members
  • 803 posts

Posted 18 August 2012 - 07:03 PM

View Postimmibis, on 18 August 2012 - 12:02 PM, said:

View PostKaoS, on 17 August 2012 - 03:56 PM, said:

How is that a syntax error?
Because os.pullEvent is not a valid identifer (as it contains a dot)

View PostKaoS, on 17 August 2012 - 04:21 PM, said:

ah I know, you cannot apply a local change to a specific table value, what you do is simply

local os=os --making a local table that you can now modify
os.pullEvent=os.pullEventRaw

and that should do it

That makes "os" local, so if you do os=something then the change is not visible outside your program.

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

t = {"one", "two", "three"}


t2 = t

print(t2[1])

This will output "one", because t2 is now a reference to the same object as t. Similarly,

t = {"one", "two", "three"}

t2 = t

t2[4] = "four"

print(t[4])

should output "four" because you're using t2 to set the table's 4 value to "four", then referencing the same table to get the value of 4

#29 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 19 August 2012 - 12:06 PM

View PostElvishJerricco, on 18 August 2012 - 07:03 PM, said:

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

I think I know how pointers/references work. "local os = os" makes a local variable called os that points to the same table as os did before, and changing its contents will change the contents of the global os table. I simply pointed out that "os=5" would not set the global os table to 5 after that.

And the reason "local os.pullEvent = os.pullEventRaw" is a syntax error is because os.pullEvent is not a valid identifier (or Name, as the reference manual defines it)
Syntax of a local declaration: stat ::= local namelist ['=' explist]
Definition of a namelist (about halfway through the section): namelist ::= Name {',' Name}
Definition of a Name

"os.pullEvent" is not a valid name, so "os.pullEvent" is not a valid namelist, so "local os.pullEvent = os.pullEventRaw" is not a valid local declaration (noting that "os.pullEventRaw" is a valid explist)

#30 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 24 August 2012 - 11:12 AM

@ElvishJerrico Yes, I understand that now, the variable used to access a table is not the table itself, merely a reference to an object that is actually the table, that is why this works


View PostKaoS, on 17 August 2012 - 08:58 PM, said:

Whoah, that is the wierdest thing I have ever seen, I thought that if you declare a variable (like os), then set another variable to be equal to the first (like temp or whatever)
, then change temp os will remain the same as it is not equal to temp. it is the other way around...

in variables this is correct but in tables if you do the following
tableone={"01","02","03","04"}
tabletwo=tableone
tabletwo[3]=nil
then tableone[3] becomes nil as well.... all I have to say is wtf... the only way to change this is manually going through each value
local temp={}
for k in pairs(os) do
temp[k]=os[k]
end
local os=temp
temp=nil
then finally all changes made to os during the function are local only

I have no explanation for the first observation Posted Image but atleast have finally worked out how to do it Posted Image I tested it so I know it works


#31 ElvishJerricco

  • Members
  • 803 posts

Posted 24 August 2012 - 06:53 PM

View Postimmibis, on 19 August 2012 - 12:06 PM, said:

View PostElvishJerricco, on 18 August 2012 - 07:03 PM, said:

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

I think I know how pointers/references work. "local os = os" makes a local variable called os that points to the same table as os did before, and changing its contents will change the contents of the global os table. I simply pointed out that "os=5" would not set the global os table to 5 after that.

And the reason "local os.pullEvent = os.pullEventRaw" is a syntax error is because os.pullEvent is not a valid identifier (or Name, as the reference manual defines it)
Syntax of a local declaration: stat ::= local namelist ['=' explist]
Definition of a namelist (about halfway through the section): namelist ::= Name {',' Name}
Definition of a Name

"os.pullEvent" is not a valid name, so "os.pullEvent" is not a valid namelist, so "local os.pullEvent = os.pullEventRaw" is not a valid local declaration (noting that "os.pullEventRaw" is a valid explist)

You said it was because it had a dot in it. You can see where confusion might be drawn from that.

#32 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 25 August 2012 - 06:25 AM

View PostElvishJerricco, on 24 August 2012 - 06:53 PM, said:

View Postimmibis, on 19 August 2012 - 12:06 PM, said:

View PostElvishJerricco, on 18 August 2012 - 07:03 PM, said:

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

I think I know how pointers/references work. "local os = os" makes a local variable called os that points to the same table as os did before, and changing its contents will change the contents of the global os table. I simply pointed out that "os=5" would not set the global os table to 5 after that.

And the reason "local os.pullEvent = os.pullEventRaw" is a syntax error is because os.pullEvent is not a valid identifier (or Name, as the reference manual defines it)
Syntax of a local declaration: stat ::= local namelist ['=' explist]
Definition of a namelist (about halfway through the section): namelist ::= Name {',' Name}
Definition of a Name

"os.pullEvent" is not a valid name, so "os.pullEvent" is not a valid namelist, so "local os.pullEvent = os.pullEventRaw" is not a valid local declaration (noting that "os.pullEventRaw" is a valid explist)

You said it was because it had a dot in it. You can see where confusion might be drawn from that.
The dot is the reason os.pullEvent is not a valid identifier/Name.

#33 KaoS

    Diabolical Coder

  • Members
  • 1,510 posts
  • LocationThat dark shadow under your bed...

Posted 25 August 2012 - 06:34 AM

the dot is not the main problem here, the fact is that there is a table, in order to locally make changes to the table we have to make a new local table which cannot be achieved by using
local os=non-local-table
as this still makes a reference to the same table object and makes global changes, in order to do this we have to make a new, identical table that is used in the place of the os table locally by doing this
local temp={}
for k in pairs(os) do
temp[k]=os[k]
end --this is creating a copy table called temp


local os=temp
temp=nil


#34 ElvishJerricco

  • Members
  • 803 posts

Posted 25 August 2012 - 10:44 PM

View Postimmibis, on 25 August 2012 - 06:25 AM, said:

View PostElvishJerricco, on 24 August 2012 - 06:53 PM, said:

View Postimmibis, on 19 August 2012 - 12:06 PM, said:

View PostElvishJerricco, on 18 August 2012 - 07:03 PM, said:

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

I think I know how pointers/references work. "local os = os" makes a local variable called os that points to the same table as os did before, and changing its contents will change the contents of the global os table. I simply pointed out that "os=5" would not set the global os table to 5 after that.

And the reason "local os.pullEvent = os.pullEventRaw" is a syntax error is because os.pullEvent is not a valid identifier (or Name, as the reference manual defines it)
Syntax of a local declaration: stat ::= local namelist ['=' explist]
Definition of a namelist (about halfway through the section): namelist ::= Name {',' Name}
Definition of a Name

"os.pullEvent" is not a valid name, so "os.pullEvent" is not a valid namelist, so "local os.pullEvent = os.pullEventRaw" is not a valid local declaration (noting that "os.pullEventRaw" is a valid explist)

You said it was because it had a dot in it. You can see where confusion might be drawn from that.
The dot is the reason os.pullEvent is not a valid identifier/Name.

Sorta. The dot makes lua try to interpret the os identifier as a table. Then when it finds out that it's not a table it throws that "attempt to index ?" error.

#35 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 26 August 2012 - 05:38 AM

View PostElvishJerricco, on 25 August 2012 - 10:44 PM, said:

View Postimmibis, on 25 August 2012 - 06:25 AM, said:

View PostElvishJerricco, on 24 August 2012 - 06:53 PM, said:

View Postimmibis, on 19 August 2012 - 12:06 PM, said:

View PostElvishJerricco, on 18 August 2012 - 07:03 PM, said:

You are not correct on either account. The reason it's a syntax error is because the local table "os" hasn't been declared as a table yet, so you can't use dot notation yet. And local os = os will not make os local. It'll give you a reference to the real os stored on the system. It doesn't copy it or anything. so local os = os; os.pullEvent = os.pullEventRaw will work EXACTLY as if you were using the regular table. Tables variables are references to objects in memory, so to set one table to another is to provide a reference. For example:

I think I know how pointers/references work. "local os = os" makes a local variable called os that points to the same table as os did before, and changing its contents will change the contents of the global os table. I simply pointed out that "os=5" would not set the global os table to 5 after that.

And the reason "local os.pullEvent = os.pullEventRaw" is a syntax error is because os.pullEvent is not a valid identifier (or Name, as the reference manual defines it)
Syntax of a local declaration: stat ::= local namelist ['=' explist]
Definition of a namelist (about halfway through the section): namelist ::= Name {',' Name}
Definition of a Name

"os.pullEvent" is not a valid name, so "os.pullEvent" is not a valid namelist, so "local os.pullEvent = os.pullEventRaw" is not a valid local declaration (noting that "os.pullEventRaw" is a valid explist)

You said it was because it had a dot in it. You can see where confusion might be drawn from that.
The dot is the reason os.pullEvent is not a valid identifier/Name.

Sorta. The dot makes lua try to interpret the os identifier as a table. Then when it finds out that it's not a table it throws that "attempt to index ?" error.
I'm referring to the reason "local os.pullEvent=os.pullEvent" has a syntax error.........................................................

#36 Hazrock

  • Members
  • 16 posts

Posted 18 September 2012 - 12:06 AM

This is how I made my first password program, before I knew about pullEvent=pullEventRaw.

I replaced shell.run with:
local loggedIn = false
local run = shell.run
function shell.run(prog, ...)
 if loggedIn or prog=="startup" then
  run(prog,...)
 elseif prog==login then
  pass = ...
  loggedIn = pass==cpass
  if loggedIn then
   print("Logged in!")
  else
   print("Access denied.")
  end
 else
  print("You have to log in!")
 end
end

I set up startup to just open my door, and could ctrl+t out and login with "login <password>" to do anything else :)/>

#37 K_Schumacher

  • New Members
  • 4 posts

Posted 18 September 2012 - 05:06 PM

My problem with disabling Ctrl-T with pullEvent=pullEventRaw is that even if you store pullEvent and recall it when program is complete if the program ever crashes or the server shuts down it will be forever disabled. So reading this post made me think of another way. Could you make a local function that is the same as pullEventRaw? What do you think? I'm thinking that way if the program ever ended in a unexpected way you would be covered.

#38 GopherAtl

  • Members
  • 888 posts

Posted 18 September 2012 - 05:30 PM

if you want a given program you run to ignore ctrl-T, you can use this program I just invented while reading this thread!

unstoppable

--grab command-line params
local args={...}
--create the coroutine
local routine=coroutine.create(function() shell.run(unpack(args)) end)
local e,p1,p2,p3,p4,p5
--run once to get it started
local _,waitingFor=coroutine.resume(routine,e,p1,p2,p3,p4,p5)
while coroutine.status(routine)~="dead"
  --wait for an event
  e,p1,p2,p3,p4,p5=os.pullEventRaw()  
  --if it's the right event...
  if waitingFor==nil or e==waitingFor then
    --resume routine passing in event and params
    _,waitingFor=coroutine.resume(routine,e,p1,p2,p3,p4,p5)
  end
end

usage (at command line):
> unstoppable myprogram <any parameters here>

if the program you call exits or errors out, so will unstoppable, and ctrl-t will be back to normal.

#39 Jajnick

  • New Members
  • 41 posts
  • LocationPoland

Posted 18 September 2012 - 06:15 PM

This article in a nutshell:

Quote

Functions are values
I don't really see the point of this wall of text.

#40 Cranium

    Ninja Scripter

  • Moderators
  • 4,031 posts
  • LocationLincoln, Nebraska

Posted 18 September 2012 - 06:52 PM

View PostJajnick, on 18 September 2012 - 06:15 PM, said:

This article in a nutshell:

Quote

Functions are values
I don't really see the point of this wall of text.
Not everyone knows this. If you don't have anything useful to add, why did you post? Please stop flaming, and go be helpful somewhere.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users