Showing posts with label OOP. Show all posts
Showing posts with label OOP. Show all posts

Friday, August 17, 2012

Interlude 11 - Classes in Lua and Codea

   

Interlude 11.1 What is a Class?


In Object Oriented Programming (OOP) a class is a coding construct used to define and create an object. Our original training was in the days of Procedural Programming, so we have some sympathy for those grappling with classes and other OOP paradigms for the first time. One way to think of a class is that it is the blueprint for an object.
  
When you create a new object using a class it is called an instance of that class. A class normally consists of data and functions which are associated with the object, this concept is called encapsulation. The class functions (sometimes called methods) act on the data variables to modify the behaviour of the object or provide information about its state. The purist approach is that only an objects functions can modify its variables. 

There are many benefits to using classes (code reuse, maintainability, modularity, inheritance etc.) but for us, the best thing about them is the mapping of a physical object or concept to a virtual object in your code. This makes it easier to conceptualise, write and understand complicated applications.
   
To be balanced we should point out that there is a camp of OOP haters (this rant by Linus Torvalds against C++ is quite amusing), it can make your code larger than necessary and arguably harder to maintain. Like most things in life moderation is the key. Abstraction for its own sake is pointless.
     

Interlude 11.2 Classes in Lua

   
As the comic at the start of the Interlude suggests, there is no class type in Lua. If that is the case then why the hell are we doing a tutorial on classes? Well it is possible to emulate a class in Lua using tables and because they are so useful the good folk at Two Lives Left have done it for you and it is included in Codea implementation of Lua. If you are really interested in how this is done then you can read the description on the Codea Wiki.
  

Interlude 11.2 Classes in Codea

    
The usual tutorial examples for classes are cars, employee data or animals. Whilst not wishing to anger the coding gods, we thought we would do something a bit more relevant to our next tutorial in the series (our interpretation of the classic SpaceWar! game). For this game we want to have a reusable ship class. The first step is to think about what sort of attributes a ship has which are relevant for us to model. Let's start with its position, speed and screen representation.
   
As mentioned above, Codea comes with a built-in global function called logically enough - class(). You can declare a class just about anywhere (with the usual caveat that if it refers to another class or function then this must have been defined before it in the tab order), but it is usually best to use the "+" tab at the top right of the screen when you are in a project to create your class. Tapping the "+" will bring up a popover with the "Create New Class" button at the top. Tapping this button allows you to enter the name of your new class and when "Done" is then tapped, Codea will create a new tab with your class template code. By convention class names start with a capital and class instances start with a lower case letter. This helps with the readability of your code, as you can immediately tell if you are referring to the class or its instance.
    

Interlude 11.3 The Ship Class

    
OK let's give it a go. Create a new project called SpaceWar! then tap the "+" tab and create a new class called Ship. You should end up with something that looks like Figure 1.
  
Figure 1. Default Class Template in Codea.
   
Codea automatically adds three functions to your class which you will usually need. The init(x) function is often called a constructor in OOP terminology. Whenever you create an instance of a new class this function will be called to set it up. Notice the x? When you create a new class you can pass in parameters to be used in the initialisation. The line self.x = x is assigning the parameter that you pass in (x) to the class variable (self.x). You don't have to do this, in which case your function would look like Ship:init() and you would also delete the line self.x = x in the body of the function. 

The draw() function you would be familiar with from earlier tutorials. Within a class we use it to handle the drawing of your object (if required). As the embedded comment says, Codea won't automatically call this function, you need to explicitly call it from the draw() function in Main. We will show you how to do this shortly.
    
Similarly, the touched() function looks after how your object handles touches. As for draw(), Codea won't call the class touch function automatically, so you need to do it in the Main touch() function. We won't be using touch until later.
   
So we have a ship class but it isn't much use at the moment. To keep track of our ship we want to use screen co-ordinates (x,y), assign a speed and allocate an image to represent the ship. The following code will achieve these objectives. 
      
Ship = class()
   
function Ship:init(x, y)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.speed = 5
    self.image = readImage("Tyrian Remastered:Boss D")
end
    
function Ship:draw()
    -- Codea does not automatically call this method
    -- Draw the ship
   
    sprite(self.image, self.x, self.y)
   
end
   
function Ship:touched(touch)
    -- Codea does not automatically call this method
end
        
We want to initialise our ship located in the middle of the screen so in the setup() function of your Main class you would have:
    
myShip = Ship(WIDTH/2, HEIGHT/2)
  
And then to draw you ship, in the Main draw() function, after the line background(40, 40, 50) add the line:
   
myShip:draw()
  
It is as simple as that. In subsequent tutorials we will look at the concept of inheritance and ways of moving your ship (the earlier Move Ship code in Tutorial 8 illustrates one method).

Thursday, July 12, 2012

Interlude 7 - Recursion & Closures in Lua (Updated 23/01/16)

Webcomic Courtesy of Ethanol & Entropy

Interlude 7.1 Preamble


Before part 2 of the MineSweeper tutorial, we need to go over two concepts which you may not have come across before, namely recursion and closures. Writing recursive code is a fairly common technique but Lua is the first language that we have come across that uses closures.


Interlude 7.2 Recursion


Recursion in programming is using a function to call itself to solve a problem. The example given in every lecture on computer science is calculating the factorial of a number. We can't think of a better example so let's go with that.

What is a factorial? Well we are glad you asked. The factorial of an integer n greater than 0 (designated by n!) is the product of all positive integers less than or equal to n. So factorial five is:

5! = 5 x 4 x 3 x 2 x 1 = 120

Note that factorial zero is defined as 1. The iterative solution to a factorial function, could look something like this:


-- Given a number 'n' calculate its factorial the iterative way

function factorial(n)

    if n == 0
        return 1

    local temp = 1

    for i = 1, n do
        temp = temp * i
    end

    return temp

end


And the recursive version:


-- Given a number 'n' calculate its factorial the recursive way

function factorial(n)

  if n == 0 then
      return 1
  else
      return n * factorial(n - 1)
  end

end


The recursive version will be marginally slower, it is a bit shorter to code, and it is a bit simpler and closer to the mathematical definition of recursion. For very large values of n, the recursive function will crash due to a stack overflow. Every time a recursive call is made, the function clones itself and pushes the previous function onto the stack. You can only do this so many times before running out of memory.

There are two rules for using recursion:
  1. If you use recursion then you must always have a base case which stops your code from calling itself forever. This won't happen of course, instead your program will crash with a stack overflow when it runs out of memory. The base case for the factorial function is n == 0.
  2. Your function must also make progress towards your base case or you will be caught in infinite recursion and crash. In the factorial example, each recursive call decrements n, so eventually it will get to the base case of zero.
The advantage of a recursive solution is its simplicity and elegance, the disadvantage can be the speed and the amount of memory used if the depth of recursion is large.

The MineSweeper game uses recursion to reveal the neighbouring cells if you tap a cell with no neighbouring mines. Have a look at the revealCell() function in the Main class.


Interlude 7.3 Tail Recursion



@gunnar_z had the following to add on the topic of recursion: 

"Lua supports something called tail recursion, or tail calls. The idea is that if the calling function does not actually do anything else but return to its caller after the called function has returned, the call is basically replaced by a jump and the current stack frame is reused. That is, the call needs to have the form "return fun(args)". With a bit of thinking, this can be made to work with a lot of recursive problems. For your example (factorial), it might look like this:

function fact(n, s)

    s = s or 1
    if n == 0 then
        return s
    else
        return fact(n-1, s*n)
    end

end

Recursion is a bit slower than iteration for trivial problems, but that is hardly noticable. For non-trivial problems (for example a recursive vs. iterative implementation of a quicksort or a tree traversal algorithm), this difference in speed shrinks rapidly, as you (may) need a stack for them anyway, and it may even be faster to implicitly use the stack provided by the language runtime through recursion than to simulate your own."


Interlude 7.4 Closures


When a function is enclosed in another function, then it has access to all the local variables of that function. This is called lexical scoping and the external local variable is called an "upvalue". 

To understand how this is useful, consider if we wanted to create a calculator application. This has a number of digit buttons that we display on the screen.


function digitButton (digit) 
    return Button{ label = digit, action = function () add_to_display(digit) end } 
end


In this example, we assume that Button is a class that creates new buttons; label is the button label; and action is the callback function to be called when the button is pressed. (It is actually a closure, because it accesses the upvalue digit.)

In our MineSweeper game, the inNeighbourCells() function uses closures to access the cell index upvalues and count the number of mines in neighbouring cells.

Another use for closures is to produce an iterator.


function makeIterator()

    local n = 0

    function iterator()
        n = n + 1
        return n
    end

    return iterator

end

-- Make two different iterator's

iterator_a = makeIterator()
iterator_b = makeIterator() 

print(iterator_a())         -- Will print 1
print(iterator_a())         -- Will print 2
print(iterator_b())         -- Will print 1
print(iterator_a())         -- Will print 3
print(iterator_b())         -- Will print 2


Once again we have a function within a function. makeIterator() is a constructor of iterator()'s and every time iterator() gets called it can see the upValue n and increments it.

@gunnar_z contributed the following additional information on closures:

"Closures are created whenever a function is created in a lexical block, not only within functions. When a function is created in a do .. end block, or even within a loop, it creates a closure. Also, all functions created within a file (or a tab in the codea world) are closures existing in the lexical context of that file (or tab). Btw. some time ago the scoping of the 

for i=1,n do ... end

construct was changed to create a new scope for every iteration. Thus, the following:

t={}

for i=1,10 do
    t[i] = function() print(i) end

end

will create a table with 10 functions, each one printing the value of i during its iteration."