Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Codea 2.3: Lua 5.3

SimeonSimeon Admin Mod
edited March 2015 in General Posts: 4,882

Hi Everyone

The changes for the Codea 2.3 are now listed here http://codea.io/talk/discussion/98/codea-roadmap-next-version-2-3-current-2-2

Codea 2.3 will cause some code breakage — nothing major, but it's just something we have to deal with in the upgrade to Lua 5.3.

I've outlined the most common cases below:

varargs

You've probably written varargs like this before, which is actually deprecated in Lua 5.1 (but it was allowed)

function foo(...)
    if arg.n > 0 then
        print(arg[1])
    end
end

You can rewrite this function right now the correct way in Lua 5.1, which will work with Lua 5.3 when Codea 2.3 comes out:

You've probably written varargs like this before, which is actually deprecated in Lua 5.1 (but it was allowed)

function foo(...)
    -- get the number of args
    local n = select('#', ...)

    -- make a table out of the args
    local arg = {...}

    if n > 0 then
        print(arg[1])
    end
end

integers

Lua supports native integers now, which is awesome. But this means you can't just give any old number to certain functions. Specifically math.random(int), math.random(int, int).

If you have a floating point number and want to convert it to an integer you can use math.floor to ensure it gets clipped. Lua will then convert it when it is passed to a function accepting integers. Not doing this will cause a runtime error.

(Note math.random() — no arguments, returns a floating point number as normal.)

Those are the big ones, and you can make your code compatible right now without impacting compatibility with the current version of Codea.

Tagged:
«1

Comments

  • edited March 2015 Posts: 300

    @Simeon If I have a game that uses math.random with integers and I don't update yet until after releasing it, will the 2.3 runtime automatically be downloaded on export and bug out the game?

    I'm slightly confused on how math.floor works. Like say if I have math.random(128, WIDTH-128), I have to use math.floor instead? If so, how would I do it? The above is actual code in a game I'm making and plan to submit to apple in the next few days.

  • dave1707dave1707 Mod
    edited March 2015 Posts: 7,514

    @Crumble All math.floor does is to drop the decimal part of a number. example 23.12 will be 23, 56.999 will be 56, and 45.00 will be 45 .

  • edited March 2015 Posts: 300

    @dave1707 I see.

    So what if I had a division in math.random that gave a repeating decimal, 17/3 for example? The 5.666666666... result would cause an error and I would need to use math.floor? Is there a way to tell math.floor how many numbers past the decimal you want to keep, or does it always make it an integer?

    Sorry for all the questions.

  • dave1707dave1707 Mod
    Posts: 7,514

    @Crumble math.floor always makes an integer. If you need a set number of digits past the decimal point for some reason, then string.format should be used.

  • dave1707dave1707 Mod
    Posts: 7,514

    @Simeon The following code gives red line editor errors. If you comment out the error line, the error will be on the next line. It will show an error for each line, but it will run and give the correct result. When I exit the program and go back to the editor, the red line error isn't there anymore until I come back into the editor.

    function setup()
        print("9&3 ",9&3)
        print("9|3 ",9|3)
        print("9~3 ",9~3)
        print("9>>2 ",9>>2)
        print("9<<2 ",9<<2)
    end
    
  • Posts: 1,595

    @dave1707 try:

    local var = 25.86789
    print(math.floor(var*100)/100)
    

    That should floor after two decimal places

  • SimeonSimeon Admin Mod
    Posts: 4,882

    @dave1707 that was fixed but Apple only allows two builds per 24 hours, so I still have to wait a few hours before I can release it for testing.

  • dave1707dave1707 Mod
    edited March 2015 Posts: 7,514

    @Luatee I meant that there wasn't any option in math.floor itself to give decimal places. But your way works just fine.

    EDIT: The only problem with that option is the result isn't rounded properly. The value 25.86789 would print as 25.86 . But a correct value to 2 decimal places should be 25.87 .

  • IgnatzIgnatz Mod
    Posts: 5,396

    Maybe the simplest way to alter existing code is to define a new math.random function that makes adjustments like those above, then you don't need to make any changes to existing code.

    Whenever I want fractional random results, I always use math.random()*number

  • Jmv38Jmv38 Mod
    edited March 2015 Posts: 3,295

    @Dave1707

    local var = 25.86789
    print(math.floor(var*100+0.5)/100)
    
  • This will mean that Ignatz may have to rewrite some of the tutorials on the Coolcodea website, otherwise some of the tutorials on there wont work properly with the new version of Codea.

  • IgnatzIgnatz Mod
    Posts: 5,396

    :((

  • edited March 2015 Posts: 154

    @Jmv38, nice trick, but as @dave1707 already said, this is what string.format is for. You shouldn't be doing math to format things.

    local var = 25.86789
    print(string.format("%0.2f", var))
    
  • Sorry to make you cry Ignatz. Maybe you could write a program to automatically translate all of the code for you so it works on the new version of Lua/Codea, rather than editing it all manually?

  • SimeonSimeon Admin Mod
    Posts: 4,882

    They are pretty minor changes really. Most projects won't need anything changed.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @juce - but if you're not printing, but planning to use the number in calculations, string.format returns a string that Codea would have to convert back to a number, so I would use the method Luatee suggested in that case.

  • dave1707dave1707 Mod
    Posts: 7,514

    Perfect example that there's always multiple ways to do something. You just need to think of what you want the outcome to be and write the code to do it.

  • SimeonSimeon Admin Mod
    Posts: 4,882

    @Luatee math.floor isn't necessary in some cases, your example below:

    local var = 25.86789
    print(math.floor(var*100)/100)
    

    Can be re-written

    local var = 25.86789
    print( var // 0.01 / 100 )
    

    The // operator is the new integer division operator in Lua 5.3.

  • edited March 2015 Posts: 1,595

    @Simeon I like that method a whole lot better, was this possible before 5.3 // operator?

    Also my method is to floor/ceil to a decimal place not rounding.

  • Posts: 427

    The use of environments has also changed. For me, this is one of the bigger changes. The functions setfenv and getfenv don't exist any more, and loadstring is replaced by load.

    (I don't know if @toadkick is still around; if so, you may be interested to know that I've adapted cmodule to Lua 5.3. Not sure how well I've done it, but it's functional.)

  • Posts: 1,595

    @LoopSpace do you have a link to cmodule and how to use it?

  • IgnatzIgnatz Mod
    Posts: 5,396

    @LoopSpace - does this affect that neat program for running multiple programs in different tabs? If so, I'd like to use it to fix a number of tutorial demos thar are going to break.

  • edited March 2015 Posts: 34

    Here's another way to get the result of 25.86:

    local var = 25.86789
    print(var-(var%0.01))
    

    This will print the first 5 digits of pi.

    local pi = math.pi
    print(pi-(pi%.1^4))
    
  • Posts: 154

    @Ignatz - fair point. I misunderstood that the original goal was to round the number, not necessarily to output it.

    (i have to say though that the example with integer division by @Simeon - that's a bit extreme :) )

  • dave1707dave1707 Mod
    Posts: 7,514

    @Simeon bitwise operators aren't flagged as errors in 2.3(44).

  • dave1707dave1707 Mod
    Posts: 7,514

    Don't forget the modf function.

    function setup()
        var=25.86789
        print(math.modf(var*100+.5)/100)
    end
    
  • Sorry @Simeon, but the post was a little confusing, which is now the correct way to use varargs?

  • SimeonSimeon Admin Mod
    Posts: 4,882

    @TheSolderKing use select, the arg variable doesn't exist any more unless you explicitly create it by doing arg = {...}

  • Ah, thanks Simeon. So

    function foo(...)
    arg={...}
    print(arg[1])
    end
    

    would work? Sorry for being a pain, just didn't understand varargs much in the first place until recently :P.

  • SimeonSimeon Admin Mod
    edited March 2015 Posts: 4,882

    Yes, that would work, though you'd probably want local arg = {...}

    You could also use select instead (more efficient if you only want access to a specific argument)

    function foo(...)
        local x = select(1, ...)
        print( x )
    end
    

    Here's the manual entry for select

    select (index, ···)

    If index is a number, returns all arguments after argument number index; a negative number indexes from the end (-1 is the last argument). Otherwise, index must be the string "#", and select returns the total number of extra arguments it received.

  • dave1707dave1707 Mod
    Posts: 7,514

    @TheSolderKing Here's some examples for arg and select.


    function setup() useArg(1,3,5,7,9) print() useSelect(2,4,6,8,0) end function useArg(...) arg={...} print("size of arg ",#arg) for z=1,#arg do print("values of arg ",arg[z]) end end function useSelect(...) a=select("#",...) print("size of ... ",a) a=select(2,...) print("value of 2nd pos ",a) a,b=select(3,...) print("values at pos 3 and 4 ",a,b) end
  • Posts: 427

    @Ignatz Yes, I believe it does since those used setfenv. I think it is possible to emulate setfenv using the debug library, or if we make the invocation just a little more detailed. I'll need to dig up the code and examine it.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @LoopSpace - that would be great if you have the time, thanks

  • Posts: 427

    @Ignatz just found it. The key question is whether you would sanction the use of the debug library or not. If not, then I think that the invocation has to be a little more wordy. Something like:

    _ENV = localise()
    

    instead of just

    localise()
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    Thanks

  • Posts: 427

    Just been playing with your lighting step-by-step program. The following seems to work:

    New localise function:

    function localise(n,d)
        if d then tabDesc[n]=d end
        local t= {}
        setmetatable(t,{__index = _G})
        tabs[n] = t
        return t
    end
    

    Then change the invocation to:

    if localise then _ENV = localise(1,"Ambient") end
    

    and similar for the other tabs

  • IgnatzIgnatz Mod
    Posts: 5,396

    brilliant, that saved me some time, thanks! =D>

  • @Simeon sorry to sound obsessed :P but does this update include sockets, as they are included in Lua 5.3? The answer is probably no, just thought I'd ask anyways :D

  • Posts: 547

    @TheSolderKing yes it does actually, codea 2.3 has the LuaSocket library (http://w3.impa.br/~diego/software/luasocket/introduction.html)

  • Oh my gosh, you have no idea how excited I am! YES! :D

  • SimeonSimeon Admin Mod
    edited March 2015 Posts: 4,882

    @TheSolderKing Codea 2.3 includes two "private" libraries. Private in the sense that they will not be documented as an official feature of Codea. Not because they aren't allowed to be put in — they are — but because I don't see them as a basic part of the Codea API.

    To use socket you will need to use require, i.e.

    local socket = require("socket")
    

    Codea 2.3 also includes LPEG as a private library, which is an incredibly powerful parsing expression grammar (http://www.inf.puc-rio.br/~roberto/lpeg/). It's a native library with a good Lua API for composing complex grammars. The reason it is included is so that the JSON library can make use of it for speed reasons.

    The plan for these private libraries is to build future public Codea features on top of them, but you can use them directly if you want to.

  • dave1707dave1707 Mod
    Posts: 7,514

    I've been trying to figure out LPeg, but it seems really confusing. I can't wait for @Ignatz to do a tutorial on it.

  • IgnatzIgnatz Mod
    Posts: 5,396

    I'd better update to 2.3 and see what all this is about! :)

  • dave1707dave1707 Mod
    edited March 2015 Posts: 7,514

    @Ignatz Just go to this link for LPeg.

    http://www.inf.puc-rio.br/~roberto/lpeg/
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    I thought quaternions were hard, until I started reading the paper describing LPEG :-S

  • SimeonSimeon Admin Mod
    edited March 2015 Posts: 4,882

    A good starting point is Lpeg recipes, it shows how to build simple parsers for common use cases:

    http://lua-users.org/wiki/LpegRecipes (the final ones are an entire Lua lexer and parser in Lpeg)

    Edit: There's also a regular expression library written in lpeg. It's basically Lua code that compiles a regular expression to an lpeg expression using lpeg. I haven't tested but you should be able to get it as follows:

    local re = require("re")
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    If someone can help build a PTP socket program, I will write it up, because I'm certain it will be an extremely popular feature for game development.

  • Ill try and help build it @Ignatz though I don't know how good at it I will be. I guess Ill try my hand at it when the next release version comes out :D

  • edited March 2015 Posts: 1,595

    Did I miss something or can the sound function no longer work with *floats for volume?

  • Posts: 418

    @Simeon Maybe I'm just stupid, but can what code did work in 2.2 but won't work in 2.3? I don't know anything more than basic programming vocabulary.

    @Luatee I think it needs to be a float within 1.0 -0.0. 1.0 being max system volume and 0.0 being no sound at all. Could be wrong tho.

Sign In or Register to comment.