Lua OOP for Event Handling - class

I'm referencing this tutorial online: https://www.tutorialspoint.com/lua/lua_object_oriented.htm
Specifically I want a class that holds four tables. The purpose of the class is to be an EventObject. The first table will hold a reference to a function in another class, the second will hold a list of all the variables/arguments, the third will have an optional function call and string to output to the log, and the last table holds a conditional that the Event System must pass before it will do the call on the function specified in the first table.
My issue is that because I'm passing in four tables and the example only has one table and then some number variables, I'm not sure if this is the right approach and I'm struggling with getting it to do what I want.
Here's my setup code. Can anyone please tell me if there is a glaring error I've missed? This is my first time ever using metatables and metamethods and stuff so I'm a little out of my depth.
TEventObject = { method = {}, args = {}, logStatement = {}, conditionals = {} }
function TEventObject:new ( method, args, logStatement, conditionals )
method = method or {}
args = args or {}
logStatement = logStatement or {}
conditionals = conditionals or {}
setmetatable(method , self)
setmetatable(args , self)
setmetatable(logStatement, self)
setmetatable(conditionals, self)
self.__index = self
self.method = method or {}
self.args = method or {}
self.logStatement = method or {}
self.conditionals = method or {}
return method, args, logStatement, conditionals
end

The code in linked tutorial is incorrect.
-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
Should actually be
-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
o.length = length or 0
o.breadth = breadth or 0
o.area = length*breadth;
return o
end
I personally would prefer
function Rectangle:new (length,breadth)
local o = {}
setmetatable(o, self)
self.__index = self
o.length = length or 0
o.breadth = breadth or 0
o.area = length*breadth;
return o
end
As you would otherwise change breadth, length and area for all rectangles to the value assigned to the latest rectangle.
In order to figure this out you both need to know what that code does and what it shoul actually do. I know this is hard for a beginner.
But the way you changed the code to your needs clearly shows that you did not even try to find out what the original code actually does.
Otherwise I cannot explain how you came up with those lines.
Please refer to the Lua Reference Manual for every line of code you read until you know for sure what it does.

Related

How to use inout on array of iVars? [duplicate]

I know that swift will optimize to copy on write for arrays but will it do this for all structs? For example:
struct Point {
var x:Float = 0
}
var p1 = Point()
var p2 = p1 //p1 and p2 share the same data under the hood
p2.x += 1 //p2 now has its own copy of the data
Array is implemented with copy-on-write behaviour – you'll get it regardless of any compiler optimisations (although of course, optimisations can decrease the number of cases where a copy needs to happen).
At a basic level, Array is just a structure that holds a reference to a heap-allocated buffer containing the elements – therefore multiple Array instances can reference the same buffer. When you come to mutate a given array instance, the implementation will check if the buffer is uniquely referenced, and if so, mutate it directly. Otherwise, the array will perform a copy of the underlying buffer in order to preserve value semantics.
However, with your Point structure – you're not implementing copy-on-write at a language level. Of course, as #Alexander says, this doesn't stop the compiler from performing all sorts of optimisations to minimise the cost of copying whole structures about. These optimisations needn't follow the exact behaviour of copy-on-write though – the compiler is simply free to do whatever it wishes, as long as the program runs according to the language specification.
In your specific example, both p1 and p2 are global, therefore the compiler needs to make them distinct instances, as other .swift files in the same module have access to them (although this could potentially be optimised away with whole-module optimisation). However, the compiler still doesn't need to copy the instances – it can just evaluate the floating-point addition at compile-time and initialise one of the globals with 0.0, and the other with 1.0.
And if they were local variables in a function, for example:
struct Point {
var x: Float = 0
}
func foo() {
var p1 = Point()
var p2 = p1
p2.x += 1
print(p2.x)
}
foo()
The compiler doesn't even have to create two Point instances to begin with – it can just create a single floating-point local variable initialised to 1.0, and print that.
Regarding passing value types as function arguments, for large enough types and (in the case of structures) functions that utilise enough of their properties, the compiler can pass them by reference rather than copying. The callee can then make a copy of them only if needed, such as when needing to work with a mutable copy.
In other cases where structures are passed by value, it's also possible for the compiler to specialise functions in order to only copy across the properties that the function needs.
For the following code:
struct Point {
var x: Float = 0
var y: Float = 1
}
func foo(p: Point) {
print(p.x)
}
var p1 = Point()
foo(p: p1)
Assuming foo(p:) isn't inlined by the compiler (it will in this example, but once its implementation reaches a certain size, the compiler won't think it worth it) – the compiler can specialise the function as:
func foo(px: Float) {
print(px)
}
foo(px: 0)
It only passes the value of Point's x property into the function, thereby saving the cost of copying the y property.
So the compiler will do whatever it can in order to reduce the copying of value types. But with so many various optimisations in different circumstances, you cannot simply boil the optimised behaviour of arbitrary value types down to just copy-on-write.
Swift Copy On Write(COW)
Make a copy only when it is necessary(e.g. when we change/write).
By default Value Type[About] does not support COW(Copy on Write) mechanism. But some of system structures like Collections(Array, Dictionary, Set) support it
Print address
// Print memory address
func address(_ object: UnsafeRawPointer) -> String {
let address = Int(bitPattern: object)
return NSString(format: "%p", address) as String
}
Value type default behaviour
struct A {
var value: Int = 0
}
//Default behavior(COW is not used)
var a1 = A()
var a2 = a1
//different addresses
print(address(&a1)) //0x7ffee48f24a8
print(address(&a2)) //0x7ffee48f24a0
//COW for a2 is not used
a2.value = 1
print(address(&a2)) //0x7ffee48f24a0
Value type with COW (Collection)
//collection(COW is realized)
var collection1 = [A()]
var collection2 = collection1
//same addresses
print(address(&collection1)) //0x600000c2c0e0
print(address(&collection2)) //0x600000c2c0e0
//COW for collection2 is used
collection2.append(A())
print(address(&collection2)) //0x600000c2c440
Use COW semantics for large values to minimise copying data every time. There are two common ways:
use a wrapper with value type which support COW.
use a wrapper which has a reference to heap where we can save large data. The point is:
we are able to create multiple copies of lite wrapper which will be pointed to the same large data in a heap
when we try to modify(write) a new reference with a copy of large data will be created - COW in action. AnyObject.isKnownUniquelyReferenced() which can say if there is a
single reference to this object
struct Box<T> {
fileprivate var ref: Ref<T>
init(value: T) {
self.ref = Ref(value: value)
}
var value: T {
get {
return ref.value
}
set {
//it is true when there is only one(single) reference to this object
//that is why it is safe to update,
//if not - new reference to heap is created with a copy of value
if (isKnownUniquelyReferenced(&self.ref)) {
self.ref.value = newValue
} else {
self.ref = Ref(value: newValue)
}
}
}
final class Ref<T> {
var value: T
init(value: T) {
self.value = value
}
}
}
let value = 0
var box1 = Box(value: value)
var box2 = box1
//same addresses
print(address(&box1.ref.value)) //0x600000ac2490
print(address(&box2.ref.value)) //0x600000ac2490
box2.value = 1
print(box1.value) //0
print(box2.value) //1
//COW in action
//different addresses
print(address(&box1.ref.value)) //0x600000ac2490
print(address(&box2.ref.value)) //0x600000a9dd30

Does swift copy on write for all structs?

I know that swift will optimize to copy on write for arrays but will it do this for all structs? For example:
struct Point {
var x:Float = 0
}
var p1 = Point()
var p2 = p1 //p1 and p2 share the same data under the hood
p2.x += 1 //p2 now has its own copy of the data
Array is implemented with copy-on-write behaviour – you'll get it regardless of any compiler optimisations (although of course, optimisations can decrease the number of cases where a copy needs to happen).
At a basic level, Array is just a structure that holds a reference to a heap-allocated buffer containing the elements – therefore multiple Array instances can reference the same buffer. When you come to mutate a given array instance, the implementation will check if the buffer is uniquely referenced, and if so, mutate it directly. Otherwise, the array will perform a copy of the underlying buffer in order to preserve value semantics.
However, with your Point structure – you're not implementing copy-on-write at a language level. Of course, as #Alexander says, this doesn't stop the compiler from performing all sorts of optimisations to minimise the cost of copying whole structures about. These optimisations needn't follow the exact behaviour of copy-on-write though – the compiler is simply free to do whatever it wishes, as long as the program runs according to the language specification.
In your specific example, both p1 and p2 are global, therefore the compiler needs to make them distinct instances, as other .swift files in the same module have access to them (although this could potentially be optimised away with whole-module optimisation). However, the compiler still doesn't need to copy the instances – it can just evaluate the floating-point addition at compile-time and initialise one of the globals with 0.0, and the other with 1.0.
And if they were local variables in a function, for example:
struct Point {
var x: Float = 0
}
func foo() {
var p1 = Point()
var p2 = p1
p2.x += 1
print(p2.x)
}
foo()
The compiler doesn't even have to create two Point instances to begin with – it can just create a single floating-point local variable initialised to 1.0, and print that.
Regarding passing value types as function arguments, for large enough types and (in the case of structures) functions that utilise enough of their properties, the compiler can pass them by reference rather than copying. The callee can then make a copy of them only if needed, such as when needing to work with a mutable copy.
In other cases where structures are passed by value, it's also possible for the compiler to specialise functions in order to only copy across the properties that the function needs.
For the following code:
struct Point {
var x: Float = 0
var y: Float = 1
}
func foo(p: Point) {
print(p.x)
}
var p1 = Point()
foo(p: p1)
Assuming foo(p:) isn't inlined by the compiler (it will in this example, but once its implementation reaches a certain size, the compiler won't think it worth it) – the compiler can specialise the function as:
func foo(px: Float) {
print(px)
}
foo(px: 0)
It only passes the value of Point's x property into the function, thereby saving the cost of copying the y property.
So the compiler will do whatever it can in order to reduce the copying of value types. But with so many various optimisations in different circumstances, you cannot simply boil the optimised behaviour of arbitrary value types down to just copy-on-write.
Swift Copy On Write(COW)
Make a copy only when it is necessary(e.g. when we change/write).
By default Value Type[About] does not support COW(Copy on Write) mechanism. But some of system structures like Collections(Array, Dictionary, Set) support it
Print address
// Print memory address
func address(_ object: UnsafeRawPointer) -> String {
let address = Int(bitPattern: object)
return NSString(format: "%p", address) as String
}
Value type default behaviour
struct A {
var value: Int = 0
}
//Default behavior(COW is not used)
var a1 = A()
var a2 = a1
//different addresses
print(address(&a1)) //0x7ffee48f24a8
print(address(&a2)) //0x7ffee48f24a0
//COW for a2 is not used
a2.value = 1
print(address(&a2)) //0x7ffee48f24a0
Value type with COW (Collection)
//collection(COW is realized)
var collection1 = [A()]
var collection2 = collection1
//same addresses
print(address(&collection1)) //0x600000c2c0e0
print(address(&collection2)) //0x600000c2c0e0
//COW for collection2 is used
collection2.append(A())
print(address(&collection2)) //0x600000c2c440
Use COW semantics for large values to minimise copying data every time. There are two common ways:
use a wrapper with value type which support COW.
use a wrapper which has a reference to heap where we can save large data. The point is:
we are able to create multiple copies of lite wrapper which will be pointed to the same large data in a heap
when we try to modify(write) a new reference with a copy of large data will be created - COW in action. AnyObject.isKnownUniquelyReferenced() which can say if there is a
single reference to this object
struct Box<T> {
fileprivate var ref: Ref<T>
init(value: T) {
self.ref = Ref(value: value)
}
var value: T {
get {
return ref.value
}
set {
//it is true when there is only one(single) reference to this object
//that is why it is safe to update,
//if not - new reference to heap is created with a copy of value
if (isKnownUniquelyReferenced(&self.ref)) {
self.ref.value = newValue
} else {
self.ref = Ref(value: newValue)
}
}
}
final class Ref<T> {
var value: T
init(value: T) {
self.value = value
}
}
}
let value = 0
var box1 = Box(value: value)
var box2 = box1
//same addresses
print(address(&box1.ref.value)) //0x600000ac2490
print(address(&box2.ref.value)) //0x600000ac2490
box2.value = 1
print(box1.value) //0
print(box2.value) //1
//COW in action
//different addresses
print(address(&box1.ref.value)) //0x600000ac2490
print(address(&box2.ref.value)) //0x600000a9dd30

What do parentheses around a closure mean?

I am trying to understand how this custom Navigation bar / Paging View works, found here. What is tripping me up when I went through the README was setting up the tinder-like custom behavior:
// Tinder Like
controller?.pagingViewMoving = ({ subviews in
for v in subviews {
var lbl = v as UIImageView
var c = gray
if(lbl.frame.origin.x > 45 && lbl.frame.origin.x < 145) {
c = self.gradient(Double(lbl.frame.origin.x), topX: Double(46), bottomX: Double(144), initC: orange, goal: gray)
}
else if (lbl.frame.origin.x > 145 && lbl.frame.origin.x < 245) {
c = self.gradient(Double(lbl.frame.origin.x), topX: Double(146), bottomX: Double(244), initC: gray, goal: orange)
}
else if(lbl.frame.origin.x == 145){
c = orange
}
lbl.tintColor = c
}
})
I don't understand why there are parentheses around the closure that is being set to the controller?.pagingViewMoving property.
When I look in the SLPagingViewSwift.swift file, the .pagingViewMoving property is set to this alias:
public typealias SLPagingViewMoving = ((subviews: [UIView])-> ())
What are the extra set of parentheses doing outside the function type?
In this case the parentheses are purely for clarity and are unnecessary. Its just like saying let a = (2 + 2). Although this should not be confused with closures provided as arguments in the following case.
If a function itself takes an argument which is a closure, the closure is simply within the parentheses thats contain the functions parameters.
So thanks to the syntax higher order functions that take a closure as their last (or only) argument that be represented in two ways - inside the argument parentheses or as whats known as a trailing closure. Consider the following function:
func foo(bar: (Int -> Int)) {...}
it can be called in two ways - first with the closure in the parentheses like so:
foo({(i) in i + 2})
or as a trailing closure:
foo {(i) in i + 2}

How to create a UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>

I'm working with a C API from Swift and for one of the methods that I need to call I need to give a
UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>
More Info:
Swift Interface:
public func presage_predict(prsg: presage_t, _ result: UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>) -> presage_error_code_t
Original C:
presage_error_code_t presage_predict(presage_t prsg, char*** result);
Generally, if a function takes a UnsafePointer<T> parameter
then you can pass a variable of type T as in "inout" parameter with &. In your case, T is
UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
which is the Swift mapping of char **. So you can call the C function
as
var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil
if presage_predict(prsg, &prediction) == PRESAGE_OK { ... }
From the documentation and sample code of the Presage library I
understand that this allocates an array of strings and assigns the
address of this array to the variable pointed to by prediction.
To avoid a memory leak, these strings have to be released eventually
with
presage_free_string_array(prediction)
To demonstrate that this actually works, I have taken the first
part of the demo code at presage_c_demo.c and translated it
to Swift:
// Duplicate the C strings to avoid premature deallocation:
let past = strdup("did you not sa")
let future = strdup("")
func get_past_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> {
return UnsafePointer(past)
}
func get_future_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> {
return UnsafePointer(future)
}
var prsg = presage_t()
presage_new(get_past_stream, nil, get_future_stream, nil, &prsg)
var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil
if presage_predict(prsg, &prediction) == PRESAGE_OK {
for var i = 0; prediction[i] != nil; i++ {
// Convert C string to Swift `String`:
let pred = String.fromCString(prediction[i])!
print ("prediction[\(i)]: \(pred)")
}
presage_free_string_array(prediction)
}
free(past)
free(future)
This actually worked and produced the output
prediction[0]: say
prediction[1]: said
prediction[2]: savages
prediction[3]: saw
prediction[4]: sat
prediction[5]: same
There may be a better way but this runs in playground and defines a value r with the type you want:
func ptrFromAddress<T>(p:UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T>
{
return p
}
var myInt:Int8 = 0
var p = ptrFromAddress(&myInt)
var q = ptrFromAddress(&p)
var r = ptrFromAddress(&q)
What's the point of defining ptrFromAddress, which seems like it does nothing? My thinking is that the section of the Swift interop book which discusses mutable pointers shows many ways to initialize them by passing some expression as an argument (like &x), but does not seem to show corresponding ways where you simply call UnsafeMutablePointer's initializer. So let's define a no-op function just to use those special initialization methods based on argument-passing
Update:
While I believe the method above is correct, it was pointed out by #alisoftware in another forum that this seems to be a safer and more idiomatic way to do the same thing:
var myInt: Int8 = 0
withUnsafeMutablePointer(&myInt) { (var p) in
withUnsafeMutablePointer(&p) { (var pp) in
withUnsafeMutablePointer(&pp) { (var ppp) in
// Do stuff with ppp which is a UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>
}
}
}
It's more idiomatic because you're using the function withUnsafeMutablePointer which is supplied by the Swift standard library, rather than defining your own helper. It's safer because you are guaranteed that the UnsafeMutablePointer is only alive during the extent of the call to the closure (so long as the closure itself does not store the pointer).

What are 'get' and 'set' in Swift?

I'm learning Swift and I'm reading The Swift Programming Language from Apple. I don't have any Objective-C background (only PHP, JavaScript, and others, but not Objective-C).
On page 24-25 I see this code:
//...Class definition stuff...
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
//...Class continues...
This part is not specified in the book, and I can't get what those are for.
What are get and set?
The getting and setting of variables within classes refers to either retrieving ("getting") or altering ("setting") their contents.
Consider a variable members of a class family. Naturally, this variable would need to be an integer, since a family can never consist of two point something people.
So you would probably go ahead by defining the members variable like this:
class family {
var members: Int
}
This, however, will give people using this class the possibility to set the number of family members to something like 0 or 1. And since there is no such thing as a family of 1 or 0, this is quite unfortunate.
This is where the getters and setters come in. This way you can decide for yourself how variables can be altered and what values they can receive, as well as deciding what content they return.
Returning to our family class, let's make sure nobody can set the members value to anything less than 2:
class family {
var _members: Int = 2
var members: Int {
get {
return _members
}
set (newVal) {
if newVal >= 2 {
_members = newVal
} else {
println('error: cannot have family with less than 2 members')
}
}
}
}
Now we can access the members variable as before, by typing instanceOfFamily.members, and thanks to the setter function, we can also set it's value as before, by typing, for example: instanceOfFamily.members = 3. What has changed, however, is the fact that we cannot set this variable to anything smaller than 2 anymore.
Note the introduction of the _members variable, which is the actual variable to store the value that we set through the members setter function. The original members has now become a computed property, meaning that it only acts as an interface to deal with our actual variable.
A simple question should be followed by a short, simple and clear answer.
When we are getting a value of the property it fires its get{} part.
When we are setting a value to the property it fires its set{} part.
PS. When setting a value to the property, Swift automatically creates a constant named "newValue" = a value we are setting. After a constant "newValue" becomes accessible in the property's set{} part.
Example:
var A:Int = 0
var B:Int = 0
var C:Int {
get {return 1}
set {print("Recived new value", newValue, " and stored into 'B' ")
B = newValue
}
}
// When we are getting a value of C it fires get{} part of C property
A = C
A // Now A = 1
// When we are setting a value to C it fires set{} part of C property
C = 2
B // Now B = 2
You should look at Computed Properties.
In your code sample, perimeter is a property not backed up by a class variable. Instead its value is computed using the get method and stored via the set method - usually referred to as getter and setter.
When you use that property like this:
var cp = myClass.perimeter
you are invoking the code contained in the get code block, and when you use it like this:
myClass.perimeter = 5.0
You are invoking the code contained in the set code block, where newValue is automatically filled with the value provided at the right of the assignment operator.
Computed properties can be read/write if both a getter and a setter are specified, or read-only if the getter only is specified.
A variable declares and is called like this in a class:
class X {
var x: Int = 3
}
var y = X()
print("value of x is: ", y.x)
//value of x is: 3
Now you want the program to make the default value of x more than or equal to 3. Now take the hypothetical case if x is less than 3: your program will fail.
So, you want people to either put in 3 or more than 3. Swift got it easy for you and it is important to understand this bit - it is an advanced way of dating the variable value, because they will extensively use it in iOS development. Now let's see how get and set will be used here.
class X {
var _x: Int = 3
var x: Int {
get {
return _x
}
set(newVal) { // Set always take one argument
if newVal >= 3 {
_x = newVal // Updating _x with the input value by the user
print("new value is: ", _x)
}
else {
print("error must be greater than 3")
}
}
}
}
let y = X()
y.x = 1
print(y.x) // The error must be greater than 3
y.x = 8 // // The new value is: 8
If you still have doubts, just remember the use of get and set is to update any variable the way we want it to be updated. get and set will give you better control to rule your logic. It is a powerful tool, hence not easily understandable.