Sunday, March 1, 2015

Seven More Languages In Seven Weeks - Lua Day 2


The second day of Lua seemed much more interesting - and challenging! - than the first. We're finally in the realm of things that feel specifically Lua-ish, rather than generic to most scripting languages.

Lua dictionaries and arrays are essentially the same data structure, a key-value collection called a "table". If you provide the table with keys, it's a dictionary. If you leave out the keys, it creates them for you in the form of sequential numbers - so you can then access the values using a not-unfamiliar array square-bracket notation. What will put some noses out of joint, but is rather splendid in my opinion, is that array indexes start from 1: I'm in favour of anything that makes programming languages easier for ordinary humans to grok, and a[1] being the second element of an array, a[2] the third and so on, is really bad from this point of view. Just because we, as professionals, have gotten used to this and are never caught out by it any more doesn't make it a good feature. It just means Stockholm Syndrome has set in.

More intriguing than the tables themselves are the fact that they have "metatables", which can be used to override table default behaviour. So for instance if you want to define how the contents of your table are viewable to the world, you set "__tostring" in the metatable. We're shown how to redefine the default ability to read and write to a table with "__index" and "__newindex" in the metatable respectively. All handy stuff.

Of course this is all leading towards a demonstration of how to do object-oriented stuff in Lua. We see a table that acts as a prototype, with a "new" method that returns instance objects. The crucial lines look a little like black magic at first:
setmetatable(obj, self)
self.__index = self
"self" being the prototype object and "obj" the returned instance. But all it really means is that the instance can refer back up to its parent for methods that it doesn't find locally.

A brief mention of inheritance and syntactic sugar later, we move onto coroutines, which is what Lua uses for multitasking in lieu of threads. Generators seem to have gotten quite in vogue lately - even PHP has come round to them now - so it's useful stuff to be getting to grips with.

The exercises are more interesting this week, though partly a strange reason: the "hard" task was easier than the "medium" ones, possibly even than one of the "easy" ones! Either that or I completely missed the point somewhere, but it did feel like the author thinks of coroutines as harder to get to grips with than I found to be the case. Whereas it took me a long time reading up on the global metatable (which hasn't even been mentioned before these exercises) to get a picture of how to correctly use it to globally override an operator, and almost as long poring over examples of Lua OO to feel like my class was sufficiently elegant. Even the "easy" concatenate function took me longer than I was expecting, simply because it turns out to be the case that if you set "array2 = array1" then it is a reference, not a copy, and any changes to array2 will be made to array1 as well. The last thing I wanted to do was to pass two arrays to my "concatenate" function and have either of them altered in the process.


Exercises:

function concatenate(a1, a2)
 local add_values_to_array = function(from_array, to_array)
   for k, v in pairs(from_array) do
     to_array[#to_array + 1] = v
   end
 end 
 local a3 = {}
 add_values_to_array(a1, a3)
 add_values_to_array(a2, a3) 
 return a3
end


function strict_write(table, key, value)
  if _private[key] and value ~= nil then
    error("Duplicate key: " .. key)
  else
    _private[key] = value
  end
end


setmetatable(_G, {__newindex = function(t, k, v)
  rawset(t, k, v)
  if type(v) == "table" then
    setmetatable(v, {__add = concatenate})
  end
end})


Queue = {}
Queue.__index = Queue

function Queue.new()
  local self = setmetatable({}, Queue)
  
  self.items = {}
  
  self.add = function(self, item)
    self.items[#self.items + 1] = item  
  end
  
  self.remove = function(self)
    if #self.items == 0 then return nil end
    first = self.items[1]
    self.items[1] = nil
    for i = 1, #self.items do
      self.items[i] = self.items[i+1]
    end
    return first
 end
  
  return self
end


function retry(count, body)
  local failures = 0
  for i = 1, count do
    print("Try " .. i)
    generator = coroutine.create(body)
    _, value = coroutine.resume(generator)
    if value == nil then return end
  end
  print("Failed")
end

Sunday, February 22, 2015

Seven More Languages In Seven Weeks - Lua Day 1

Our adventures in Lua begin with a preamble singing the praises of "rich syntax and proper semantics", "famously clean code" and a "quick, portable little language" that outdoes the competition. Sounds great, where can I learn more? We are then told of Lua's fabulous tables, which are infinitely more elegant and wieldy than the given example of a CSV file. They look a little like this:

Monster {
  name = "knight",
  treasure = {-1000, 200}
}

and can even more marvellously pass around first class functions, like so:

Monster {
  name = "cobra",
  speed = function() return 10 * damage_to_player() end
}

But hang on, don't these look an awfully lot like JavaScript objects? Mention on the following page of "the prototype style of object-oriented programming" does make me suspect that we could be dealing with something a lot like JS here. A sidebar later in the chapter provides a head-to-head comparison between Lua and JS where Lua's support for tail call optimization allows it to recursively reverse a large string, where trying to do the same in JavaScript results in stack error.

Oh well, a language that's like JavaScript but better could be of use to us, or at least help us get better at JS (since, by historical accident or otherwise, it seems like JS is here to stay). Let's see where Lua takes us.

The first day is something of a gentle stroll through the usual basics. Lua turns out to be dynamically typed, with logical expressions that short-circuit, and functions as first-class values. Functions are flexible about the number of parameters they're sent, can be variadic, can return multiple values. All of these things seem elegant and sensible. A little more alarmingly, variables are global by default, and you have to use a keyword to make them local: apparently this is For Good Reasons, but wiser heads than mine are going to need to explain them. Whatever, I'm sure it can't be any crazier than JavaScript variable scope.

Nothing too outrageous in the exercises, I don't think. Some preliminary forays into the functional programming that languages with first class programming facilitates - I guess the main thing to say is, doesn't the simple elimination of all the semicolons and curly braces make Lua look a hundred times nicer than JS?

ETA: Though I suppose it is worth mentioning that I initially formulated first_n_primes_ending_in_3 in terms of naively checking each successive number from 2 upwards for "ends_in_3" as well as "is_prime"... but that does seem like a lot of unnecessary work when we know that a full 90% of numbers do not end in 3, and we have a quick way of iterating through the ones that do...

Exercises:


function ends_in_3(num)
  return num % 10 == 3
end

function is_prime(num)
  for i = 2, math.sqrt(num) do
    if num % i == 0 then return false end
  end
  return true
end

function first_n_primes_ending_in_3(n)
  local candidate = 3
  while n > 0 do
    if is_prime(candidate) then
      print(candidate)
      n = n - 1
    end
    candidate = candidate + 10
  end
end

function for_loop(a, b, f)
  while b >= a do
   f(a)
   a = a + 1
  end
end

function reduce(max, init, f)
  local current = 1
  while max >= current do
   init = f(init, current)
   current = current + 1
  end
  return init
end

function factorial(n)
  return reduce(n, 1, function(x, y) return x * y end)
end