This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
sab0t's profile picture

Extending 'window'

Started by sab0t, 12 June 2014 - 12:26 PM
sab0t #1
Posted 12 June 2014 - 02:26 PM
I would like to extend the window Class (or is it just an API? i'm still getting used to Lua :P/>) to add some convenience functionality tailored to my program. My problem is that I have no idea how to do that in Lua , let alone in CC.

I read up on how one would go about doing this in regular Lua here, which, to its credit, explains it really well and has the excellent tried and true animal examples for class extension. In CC though I've had no luck so far, and just due to my inexperience in Lua I'm not quite sure how to even go about experimenting and would really appreciate a point in the right direction.

To give a bit more detail, I want to extend 'window' into 'labeledwindow', that basically has a prefixed label string, and when writing to the window, it's smart about knowing about its label and not overwriting it, etc. etc. It's pretty basic stuff and so far has been a great way to get used to Lua, I just can't figure out the inheritance :(/>

going off of the example in the link I posted above, I turned this:


require 'class'
Dog = class(Animal)

function Dog:speak()
  return 'bark'
end
into:

require 'class'
labeledwindow = class(window)

function labeledwindow:rpwrite(window, text)
  window.clear()
  window.setCursorPos(1,1)
  window.write(text)
end

attempt to call nil is thrown on the require 'class' line. i've also tried it without that require, the same error is thrown on the next line..again, I'm really not too sure how to even go about experimenting, so if anyone has any pointers, advice or otherwise, I would appreciate it so much!

(I haven't been able to find anything in the CC Wiki or otherwise regarding inheritance, but I apologize if something does exist, feel free to just point me there if my question's been answered elsewhere)

Thanks in advance everyone, if anyone needs any more info please just ask!
CometWolf #2
Posted 12 June 2014 - 04:27 PM
require is not a feature in Lua 5.1, which is what CC uses. And in guessing this 'class' that is being required is a custom function of some sort, eitherway trying to call it will result in an error, since there is no function by that name.

I'd suggest reading this instead
http://www.lua.org/pil/16.html

Also, window is an API, however it returns an object containing the window parameters and functions.
Bomb Bloke #3
Posted 12 June 2014 - 04:42 PM
I guess a good start would be which languages are you familiar with? I'm assuming Java, but you didn't specify any prior knowledge…

In Lua, tables are a common device that're used in a similar manner to basic arrays (but far more versatile - you can treat them as a regular array, or as a hashmap, or both at once). Variables can and do have just about anything stored against them - including function pointers - and can be assigned data of a different type whenever you please. You can literally take the pointer to the window API for eg - which is stored in a variable called "window" - and replace it with a random string. Of course, that'll likely lead to a crash as soon as your system tries to call that API ("pretty much straight away"), but with any luck you get the idea.

With that in mind, your typical Lua "API" is basically a table containing pointers to functions. When a custom API (such as many of those ComputerCraft uses, eg the window API) is loaded into memory from whatever Lua source file they're stored in, these functions are pre-compiled into byte-code. You then can't really modify these functions with your external code short of replacing them entirely.

In short, you may be better off making a copy of the window API's source, modifying that to suit your needs, then loading the new API source file that results. Or maybe make your own API from scratch - depending on your needs, the original window API might not suit your purpose at all (its more of a "display buffer" API than anything).

I suggest reading this tutorial, if only to ensure your current views match what's in it. Have you located the API source in the ComputerCraft mod archive?
sab0t #4
Posted 13 June 2014 - 02:32 AM
thank you both for your responses!

Bomb Bloke, I apologize I forgot to mention my programming background! I am fairly well versed in PHP, but switched to writing Java full-time fairly recently, though I know much of the Java "theory" I guess you could say from college I still consider myself fairly inexperienced using it. Also C# from college and from mucking about in Unity here and there, and I started with C, though I haven't written anything non-trivial in it.

Re-reading my OP I guess I was really looking for a brief summary on how Classes are "done" so to speak, in Lua, and you've given me great insight into that (as well as the nature of tables and variables in general - confirms my thoughts that Lua gives you lots of rope :lol:/> ). Thank you both for the links, I'll be going through them shortly. I'll likely be going with the suggestion of loading and modifying the window API to match my needs, as I really only intend to add a small amount of extra functionality.
natedogith1 #5
Posted 13 June 2014 - 09:06 AM
You could try something along the lines of

function create(parentTerm, x, y, width, height, visible) --creation function
local win=window.create(parentTerm,x,y,width,height,visible) --getting the default version
local labeledWindow={} --create table for our stuff
function labeledWindow.example(text) --an example function
  win.write(text)
end
return setmetatable(win,{__index=labeledWindow}) --metatables are fun things
-- the __index=table makes it so that if win[k] returns nil then you get labeledWindow[k] instead
end
metatables are wonderful things I've discovered, unless your pretending to be the actual thing of course
You could also just add your function straight to the returned window like so

function create(parentTerm, x, y, width, height, visible) --creation function
local labeledWindow=window.create(parentTerm,x,y,width,height,visible) --getting the default version
function labeledWindow.example(text) --an example function
  labeledWindow.write(text)
end
return labeledWindow --return the modified table
end

Also, require is a feature of Lua 5.1, it's just been removed along with the rest of the modules library because of its potential danger.
Bubba #6
Posted 13 June 2014 - 03:50 PM
Also, require is a feature of Lua 5.1, it's just been removed along with the rest of the modules library because of its potential danger.

You do realize that ComputerCraft uses Lua 5.1, yes?

However, in this case ComputerCraft doesn't have a require function - I suppose it has been disabled in CC's implementation or it was never included with LuaJ.


Edit: Apologies, misunderstood your post.
Edited on 13 June 2014 - 02:00 PM
Lyqyd #7
Posted 13 June 2014 - 03:56 PM
You two are in agreement; he was disputing CometWolf's statement above. It would have been clearer had he quoted the post he was disagreeing with.
Bubba #8
Posted 13 June 2014 - 04:00 PM
You two are in agreement; he was disputing CometWolf's statement above. It would have been clearer had he quoted the post he was disagreeing with.

Hah, yeah I get that now that I read it a bit more carefully.
sab0t #9
Posted 14 June 2014 - 07:38 PM
You could try something along the lines of

function create(parentTerm, x, y, width, height, visible) --creation function
local win=window.create(parentTerm,x,y,width,height,visible) --getting the default version
local labeledWindow={} --create table for our stuff
function labeledWindow.example(text) --an example function
  win.write(text)
end
return setmetatable(win,{__index=labeledWindow}) --metatables are fun things
-- the __index=table makes it so that if win[k] returns nil then you get labeledWindow[k] instead
end
metatables are wonderful things I've discovered, unless your pretending to be the actual thing of course
You could also just add your function straight to the returned window like so

function create(parentTerm, x, y, width, height, visible) --creation function
local labeledWindow=window.create(parentTerm,x,y,width,height,visible) --getting the default version
function labeledWindow.example(text) --an example function
  labeledWindow.write(text)
end
return labeledWindow --return the modified table
end

Also, require is a feature of Lua 5.1, it's just been removed along with the rest of the modules library because of its potential danger.

i (like many others) learn best from/using/modifying/working off of direct examples, so i really appreciate these examples. though, i'm not sure i'm perfectly understanding the concept of metatables, even despite the example - is this Lua concept analogous to something in another language like PHP, C, C++, Java, JS, jQuery?

Thanks again!!
Edited on 14 June 2014 - 05:54 PM
Bomb Bloke #10
Posted 15 June 2014 - 03:22 AM
It's similar-ish to the way Java works. If you think of a basic table as being like a Java object which you can store pretty much anything in, metatables let you add some actions to that object.

Most of these actions are sorta pre-defined: functions that Lua expects to be there and will automatically call under certain circumstances. For example, if you check a table index which doesn't exist, then Lua will check to see if there's a function attached to that table that you want to run under that circumstance.

Tables can also be linked, such that you can have one with a number of functions assigned to it, and others linked to that which hold data to use with those functions. Again, much like how you might spawn new instances of an object in Java, each with the same basic form but different characteristics.

Read this whole chapter.