I'm trying to create an object oriented implementation in Lua, for example:
Parent = {
ChildVariable = "Hello",
ChildFunction = function ()
print(Parent.ChildVariable)
end
}
What I would like is rather than doing Parent.ChildVariable I can do ChildVariable instead; it is in the table so I thought must be some way to access it.
Parent = {
ChildVariable = "Hello",
ChildFunction = function(self)
print(self.ChildVariable)
end
}
Parent:ChildFunction()
Lua has a special construct for that: the colon operator.
The two following lines are equivalent:
tbl.func(tbl)
and
tbl:func()
Related
In JavaScript you can do the following:
var obj = {
property: 1,
method1: function() {
//...
},
method2: function() {
//...
}
};
obj.method1()
I am wondering if there is a groovy equivalent for this (a map containing a method). I know this is just like a class, but I dont want a class ha..
Yes, you can put closures inside a map. But this is not the way to get
objects in Groovy. There is no concept of "this", that knows about the
map.
def obj = [
inc: { it + 1 }
]
println obj.inc(10)
Ok so Javascript is not OOP. They have OBJECTS but that is it. What you are showing is an OBJECT.
In Groovy, you can do this with a class that can instantiate the object and then you can do that on the object. For example you can create a CommandObject (which is what you are probably wanting) and then fill in the properties like you want or fill them in on instantiation. For example (using above example):
def paramsDesc = new ParamsDescriptor()
paramsDesc.paramType = 'paramtype'
paramsDesc.keyType = 'keyType'
paramsDesc.name = 'name'
paramsDesc.idReferences = 'id'
paramsDesc.description = 'desc'
paramsDesc.mockData = 'mock'
paramsDesc.values = []
OR (if you create a constructor) you can instantiate all at once:
def paramsDesc = new ParamsDescriptor('paramtype','keyType','name','id','desc','mock',[])
CommandObjects can have methods and functions (like above). But you just have to instantiate them first (def paramsDesc = new ParamsDescriptor())
This is the difference between a class and an object; think of a class as the blueprint and the object as what is created from the blueprint.
Is it possible to have a function that can access arbitrarily nested entries of a table?
The following example is just for one table. But in my real application I need the function to check several different tables for the given (nested) index.
local table1 = {
value1 = "test1",
subtable1 = {
subvalue1 = "subvalue1",
},
}
local function myAccess(index)
return table1[index]
end
-- This is fine:
print (myAccess("value1"))
-- But how do I access subtable1.subvalue1?
print (myAccess("subtable1.subvalue1???"))
You won't be able to do this using a string unless you use load to treat it as Lua code or make a function to walk on a table.
You can make a function which will split your string by . to get each key and then go one by one.
You can do this using gmatch + one local above gmatch with current table.
#Spar: Is this what you were suggesting? It works anyway, so thanks!
local table1 = {
value1 = "test1",
subtable1 = {
subvalue1 = "subvalue1",
},
}
local function myAccess(index)
local returnValue = table1
for key in string.gmatch(index, "[^.]+") do
if returnValue[key] then
returnValue = returnValue[key]
else
return nil
end
end
return returnValue
end
-- This is fine:
print (myAccess("value1"))
-- So is this:
print (myAccess("subtable1.subvalue1"))
In Kotlin, if you want to use the element of the forEach, you can use the it keyword. So now I wonder that what should I do if I have a forEach inside forEach like that:
list.forEach {
val parent = it
it.forEach {
// `it` now become the element of the parent.
}
}
I think that defines a new variable only for the naming convention be so stupid. Have any other solution for this problem?
it is just a default param name inside of all single argument closures. You could specify param name by yourself:
collection.forEach { customName ->
...
}
In addition to the correct answer above by Artyom, I'd like to say that if you only care for the inner it, you can simply ignore the name overloading.
See:
>> var a = "abc"
>> a?.let { it[2]?.let { it } }
c
The value returned is the most inner "it". "it", there, refers to the outermost "it[2]", that is, the character 'c' from the string "abc".
Now, if you want to access the outermost "it", you should name it something else like Artyom says. The code below is equivalent to the code above, but it allows you to refer to "outerIt" from the outer 'let' block in the innermost 'let' block, if that's what you need.
>> var a = "abc"
>> a?.let { outerIt -> outerIt[2]?.let { it } }
c
This way, if you need to refer to the outermost it, you can. For example:
>> var a = "abc"
>> a?.let { outerIt -> outerIt[2]?.let { "${outerIt[1]} $it" } }
b c
If you don't need to refer to the outermost "it", I'd personally prefer the first construct because it is terser.
I want to use a key insde an anonymous table from within that same table, like so:
loadstring( [[return {
a = "One",
b = a.." two"
}]] )
From my perspective, this should return the following table:
{ a = "One", b = "One two" }
However, it just returns nil.
Is this possible to do, and how?
As the other answer said, you can't reference a key in a table that is being constructed, but you can use a variable to hold the value you want to reference several times:
local a = "One"
local t = { a = a, b = a.." two" }
No, you can't do that. At the point you are using a the table has not been constructed. Lua looks for a global variable a, which is why you get nil.
If you want to refer to keys in a table they must be defined first.
local t = { a = 'One' }
t.b = t.a..' two'
I have to declare a table in a table that will act like this:
table = {'79402d' = {'-5.4','5','1.6'}, '5813g1' = {'3','0.15','18'}}
So when I loop through it, I can use something similar to table['79402d'][0] to print coordinates.
There are two types of syntax for table constructors. The general form:
t = { ['key'] = value }
(If the key is a valid identifier)The syntax sugar form:
t = { key = value }
Here you are mixing them up. Because 79402d isn't a valid identifier (beginning with letters or underscore), you have to use the general form:
t = {['79402d'] = {'-5.4','5','1.6'}, ['5813g1'] = {'3','0.15','18'}}