[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Arguments by reference?
- From: Rici Lake <lua@...>
- Date: Thu, 1 Sep 2005 09:47:05 -0500
On 1-Sep-05, at 8:18 AM, Lisa Parratt wrote:
Boyko Bantchev wrote:
... assuming `simple' values are meant. Because tables, e.g.,
_are_ passed by reference.
They might look like they're being passed by reference, but they're
not. All arguments in Lua are passed by value. They are not passed by
copy, so when you pass a table (by value) you are passed the same
table, which means you can mutate it (arg[key] = 42) or compare its
object identity with another table, etc. Immutable objects (such as
numbers and strings) are not copied either, since there are no
mutators, so the copy is unnecessary.
Not really - you can't wholesale change the calling functions idea of
which table is being referred to by a symbol, which you could if it
were being passed truly by reference, only the members of said table.
It's a bit of a special case, and a bit of a mish-mash.
I think reasonable people could argue with the word "mish-mash". It's
"not like C" :)
R.
PD. The simplest way to create a "reference" type in Lua is by creating
a one-element table.
a = {value = "some value"}
Deref: a.value
Mutate: a.value = newvalue
Constructor to save a couple of keystrokes:
function Box(val) return {value = val} end
Here's an overly complicated implementation illustrating various other
options, depending on your needs/desires/sense of aesthetics.
do
local meta = {}
-- protect
meta.__metatable = false
-- box() dereferences the box
function meta:__call() return self[1] end
-- so does box.value
function meta:__index(key)
if key == "value" then return self[1]
else return meta[key]
end
end
-- which is read/write
function meta:__newindex(key, val)
if key == "value" then self[1] = val
-- allow them to set attributes on a box
else rawset(self, key, val)
end
end
-- That slows down dereferencing a lot, so if you don't need that
-- style, use this instead:
-- meta.__index = meta
-- so does box:get()
-- function meta:get() return self[1] end
meta.get = meta.__call -- :)
-- change the value with box:set(val)
function meta:set(val) self[1] = val end
-- change the value and get the old value
-- with box:flip(val). (Some people like this
-- semantic
function meta:flip(val)
local old = self[1]
self[1] = val
return old
end
------ Actually create the object. You might prefer to call this Ref
function Box(initial_value)
return setmetatable({initial_value}, meta)
end
end
-- Test run
> salutation = Box("Hello")
> audience = Box("world")
> function greet() print(salutation()..", "..audience()) end
> greet()
Hello, world
> salutation.value = "Good morning"
> audience:set "Luaphiles"
> greet()
Good morning, Luaphiles
> =salutation.value
Good morning
> =salutation()
Good morning
> =salutation:get()
Good morning
> old = salutation:flip("Good afternoon")
> greet()
Good afternoon, Luaphiles
> old = salutation:flip(old)
> greet()
Good morning, Luaphiles
>