Benutzer-Werkzeuge

Webseiten-Werkzeuge


becki:linux:lua

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
becki:linux:lua [2013-01-31 08:43]
becki
becki:linux:lua [2023-12-27 13:57] (aktuell)
becki [Classes and Objects]
Zeile 12: Zeile 12:
   * [[http://​lua-users.org/​wiki/​LibrariesAndBindings|Manual]]   * [[http://​lua-users.org/​wiki/​LibrariesAndBindings|Manual]]
  
-===== Standalone lua == +===== Implementations == 
-==== Shebang ==+==== Standalone lua == 
 +=== Shebang ==
  
 ''#​!/​usr/​bin/​lua''​ ''#​!/​usr/​bin/​lua''​
  
-==== Command Line Arguments ==+=== Command Line Arguments ==
  
 Use global table ''​arg''​ Use global table ''​arg''​
  
-==== StdIo ==+=== StdIo ==
  
 <code lua> <code lua>
Zeile 30: Zeile 31:
 </​code>​ </​code>​
  
-===== For Loop ==+==== Lua for Web Browsers ​=
 + 
 +[[http://​kripken.github.io/​lua.vm.js/​script_example.html|lua.vm.js]] thanks to asm.js 
 + 
 +==== Lua for Java/​Android == 
 + 
 +[[https://​sourceforge.net/​projects/​luaj/​|Luaj]],​ seen at [[https://​github.com/​M66B/​XPrivacyLua/​blob/​master/​README.md|XPrivacyLua]] 
 + 
 +===== C-style ?-operator equivalent == 
 + 
 +This C code 
 +<code c> 
 +d= a ? b : c 
 +</​code>​ 
 +is in lua: 
 +<code lua> 
 +d= a and b or c 
 +</​code>​ 
 + 
 +Note that this works only for //single// assignment. Use auxiliary tables for mulitiple assignment:​ 
 +<code lua> 
 +d1, d2 = table.unpack(a and {b1, b2} or {c1, c2}) 
 +</​code>​ 
 + 
 +<note warning>​Take care if b can become ''​nil''​ or ''​false''​. In this case the equivalent doesn'​t work. Instead use:</​note>​ 
 +<code lua> 
 +if a then d=b else d=c end 
 +</​code>​ 
 + 
 +===== Default values for missing arguments == 
 + 
 +<code lua> 
 +function foo(a) 
 +    a= a or "​defaultvalue"​ 
 +end 
 +</​code>​ 
 + 
 +Take care, if ''​false''​ is a valid value, instead use: 
 + 
 +<code lua> 
 +function foo(a) 
 +    if a==nil then a="​defaultvalue"​ end 
 +end 
 +</​code>​ 
 + 
 + 
 +===== Difference between nil and no value == 
 +<code lua> 
 +function return_nil() 
 +    return nil 
 +end 
 + 
 +function return_nothing() 
 +end 
 + 
 +function count_args(...) 
 +    print(table.pack(...).n) 
 +end 
 + 
 +count_args(nil) ​                  ​-->​ 1 
 +count_args() ​                     --> 0 
 +--=> Passed nils increment argument count 
 + 
 +count_args(return_nil()) ​         --> 1 
 +count_args(return_nothing()) ​     --> 0 
 +--=> Returned nils increment return value count 
 + 
 +print(tonumber(nil)) ​             --> nil 
 +print(tonumber(return_nil())) ​    ​-->​ nil 
 +--=> tonumber() accepts nil as argument 
 + 
 +print(tonumber()) ​                ​-->​ bad argument #1 to '​tonumber'​ (value expected) 
 +print(tonumber(return_nothing())) --> bad argument #1 to '​tonumber'​ (value expected) 
 +--=> tonumber() does not accept nothing as argument 
 +</​code>​ 
 + 
 +<note warning>​An example for a function returning nothing is the result of string.gmatch()</​note>​ 
 + 
 +===== Lexical scoping == 
 + 
 +<code lua> 
 +local strict= require"​fs.strict"​ 
 +local g,h,i 
 + 
 +local function f() 
 +    g() -- ok 
 +    h() -- ok 
 +    --i() -- err, because i refers to old upvalue which is still nill 
 +end 
 + 
 +g= function() end      -- existing upvalue g is assigned a function 
 +function h() end       -- same as above (mind the missing "​local"​!) 
 +local function i() end -- a new upvalue is created which hides old i(assumption) 
 + 
 +f() 
 +i() -- ok 
 +</​code>​ 
 + 
 +===== Numeric for Loop ==
  
 <code lua> <code lua>
Zeile 37: Zeile 136:
 end end
 </​code>​ </​code>​
 +
 ===== Tables == ===== Tables ==
 ==== Length == ==== Length ==
Zeile 114: Zeile 214:
  
 ===== Error Handling == ===== Error Handling ==
 +==== pcall() differs from Lua Convention ==
 +''​pcall()'':​
 +  success: true, value(s)
 +  failure: false, error
  
-<note warning>​FIXME needs rework!</note>+Lua [[http://​lua-users.org/​wiki/​FinalizedExceptions|convention]]:​ 
 +  success: value(s) 
 +  failure: nil, error
  
-<note tip>Convention: Most Lua functions return nil (as payloadin case of error, followed by message string describing ​the error. [[http://​lua-users.org/​wiki/​FinalizedExceptions|Source]] +<note tip>Error handling code after ''​pcall()''​ differs from error code after calling ​function which complies to the convention!</​note>​
-</​note>​+
  
-This is simliar to [[golang|Go]]+==== Raise error or return error? == 
 +=== Converting between raise and return ==
  
-throw/catch mechanism is possible with error() / pcall(). ​[[lua>pil/8.4.html|More]]+''​pcall()''​ converts an error raising function into an error returning function. 
 + 
 +''​assert()''​ or similar converts an error returning function into an error raising function. 
 + 
 +=== Pro Error Raising == 
 + 
 +  - function which //returns// the error forces the user of that function to //always// check the return code (or convert to raise, regadless if he wants to handle the error or just pass it upward. 
 +  - A function which //raises// the error can not get forgotten to check for errors. 
 +  - If the user wants to pass the error upward, checking and converting can be avaoided completely if both the called function and the caller use error raising. In any other case he has to check and/or convert: 
 + 
 +^ caller⇓ callee⇒ ^ return ^ raise ^ 
 +^ return | check | pcall() ​+ check | 
 +^ raise | assert() | nothing | 
 + 
 +=== Pro Error Returning == 
 + 
 +  - If the user wants to handle the error, he simply checks the return value of an error returning functionIf the function raises the error, the user must convert it to a error returning function by help of pcall() before. 
 +  - FIXME A typical ''​try {...}''​-block is done with a function in Lua. That means you end up having one function more for each try/catch usage 
 + 
 +=== Rules: == 
 + 
 +<note tip> 
 + 
 +  - //Return// error if it can be expected, that the user needs to handle the error directly after calling the func in question. 
 +  - //Raise// the error if it can be expected, that the user does not care for errors directly after calling the func in question and simple passes it upward. 
 +  - <​del>​If in doubt, raise the error</​del>​ FIXME What to do when in doubt? 
 +</​note>​
  
 ===== Classes and Objects == ===== Classes and Objects ==
 +
 +See also projects/​accounting/​sbaccimport which has since rev 482:​c85c255f1870 classes with inheritance where the constructor new() is a class method and can therefore be reused in child classes similar to PIL capter 21 
 ==== Classes as Object templates == ==== Classes as Object templates ==
 <code lua> <code lua>
Zeile 344: Zeile 478:
 </​code>​ </​code>​
  
 +===== File access ==
 +
 +Each of the following constructs is equivalent, it reads a file line by line:
 +
 +<code lua>
 +local f= io.open"​file.txt"​
 +repeat
 +    local l= f:​read("​l"​)
 +    if l then print(l) end
 +until not l
 +f:close()
 +</​code>​
 +
 +<code lua>
 +local f= io.open"​file.txt"​
 +for l in f:​lines("​l"​) do
 +    print(l)
 +end
 +f:close()
 +</​code>​
 +
 +<code lua>
 +for l in io.lines("​file.txt",​ "​l"​) do
 +    print(l)
 +end
 +</​code>​
 +
 +  - ''"​l"''​ as arg for ''​read()''​ is the default, it can be omitted
 +  - ''​file:​lines()''​ and ''​io.lines()''​ accept the same format args as ''​read()''​. (Tested. Nowhere found in docu). Thus you could read a file eg chunk by chunk as well.
 +  - io.lines() without arguments returns an iterater wich returns stdin line by line
 +
 +==== Load CSV-like files ==
 +
 +<code lua>
 +#​!/​usr/​bin/​lua
 +local separator=":"​
 +for line in io.lines() do
 +    print(line)
 +    for cell in line:​gmatch("​[^"​..separator.."​]+"​) do
 +        print("",​ cell)
 +    end
 +end
 +</​code>​
 ===== Includes and Modules == ===== Includes and Modules ==
 ==== Include == ==== Include ==
Zeile 363: Zeile 540:
 chunk() chunk()
  
-for key,value in pairs(extenv) do +for k,in pairs(extenv) do 
-    io.write("​[", ​key, "] = ", ​value, "​\n"​)+    io.write("​[", ​k, "] = ", ​tostring(v), "​\n"​)
 end end
 </​code>​ </​code>​
Zeile 405: Zeile 582:
 ==== Using Locals == ==== Using Locals ==
  
-<note tip>​Local variables (indexed access) are much faster than global ​variables (table access)This is also true for file-local variables</note>+<code lua global.lua> 
 +do 
 +    var= 0 
 +    ​for i=1,​102000000 do 
 +        var= var+1 
 +    end 
 +end 
 +-- real 0m4.516s 
 +</code>
  
-Example: +<code lua local.lua> 
-<code lua+do 
--- global.lua +    local var= 0 
-a=0 +    for i=1,102000000 ​do 
-b=0 +        varvar+1 
-for i=1, 10000000 ​do +    ​end
-    ab+1 +
-    ​b= a+
 end end
 +-- real 0m1.003s
 </​code>​ </​code>​
-<code>$time global.lua + 
-real 0m1.178s +<​code ​lua chunk.lua> 
-user 0m1.176s +local var= 0 
-sys 0m0.001s+do 
 +    for i=1,​102000000 do 
 +        var= var+1 
 +    end 
 +end 
 +--real ​0m0.970s
 </​code>​ </​code>​
  
-<code lua+<code lua closure.lua> 
--- local.lua +do 
-local a=0 +    ​local var= 0 
-local b=0 +    local closurefunction() 
-for i=1, 10000000 ​do +        for i=1,102000000 ​do 
-    ab+1 +            varvar+1 
-    ​b= a+        end 
 +    ​end 
 +    closure()
 end end
 +-- real 0m1.666s
 </​code>​ </​code>​
-<code>$time local.lua + 
-real 0m0.161s +<​code ​lua map.lua> 
-user 0m0.157s +do 
-sys 0m0.003s+    local tab= {var= 0} 
 +    for i=1,​102000000 do 
 +        tab.var= tab.var+1 
 +    end 
 +end 
 +-- real 0m4.248s
 </​code>​ </​code>​
 +
 +<code lua array.lua>​
 +do
 +    local tab= {0}
 +    for i=1,​102000000 do
 +        tab[1]= tab[1]+1
 +    end
 +end
 +-- real 0m4.767s
 +</​code>​
 +
 +<note tip>
 +
 +  - Local variables (compiled indexed access) are much faster than global variables (table access).
 +  - Chunk-local variables are as fast as function-local variables
 +  - Upvalues (non-local variables of closures) are only a little slower than local variables
 +  - Table access (array or map) is as slow as accessing global variables
 +</​note>​
 +
 +Tested with Lua 5.2
 +
  
 ==== Strings == ==== Strings ==
Zeile 447: Zeile 665:
  
 ===== Coroutines == ===== Coroutines ==
 +==== Basic Rules ==
 +
 +A newly created coroutine is in state ''​supended'':​
 +<code lua>
 +co1= coroutine.create(function() end)
 +print(coroutine.status (co1)) --> suspended
 +</​code>​
 +
 +A coroutine which resumes another coroutine goes from state ''​running''​ to ''​normal''​ while the resumed couroutine goes from state ''​suspended'' ​ to''​running'':​
 +<code lua>
 +co1= coroutine.create(function()
 +    print("​in co1: state main:",​ coroutine.status(main))
 +    print("​in co1: state co1", coroutine.status(co1))
 +end)
 +
 +main= coroutine.running() -- get handle to main coroutine
 +print("​in main: state main:",​ coroutine.status(main))
 +print("​in main: state co1:", coroutine.status(co1))
 +coroutine.resume(co1)
 +</​code>​
 +<​code>​Result:​
 +in main: state main:​ running
 +in main: state co1:​ suspended
 +in co1: state main:​ normal
 +in co1: state co1 running
 +</​code>​
 +
 +
 +A ''​running''​ couroutine can yield() back to its resumer, which puts the resumer back to ''​running''​ and itself back to ''​suspended'':​
 +<code lua>
 +co1= coroutine.create(function()
 +    print("​in co1: state main:",​ coroutine.status(main))
 +    print("​in co1: state co1", coroutine.status(co1))
 +    coroutine.yield()
 +end)
 +
 +main= coroutine.running() -- get handle to main coroutine
 +coroutine.resume(co1)
 +print("​in main: state main:",​ coroutine.status(main))
 +print("​in main: state co1:", coroutine.status(co1))
 +</​code>​
 +<​code>​Result:​
 +in co1: state main:​ normal
 +in co1: state co1 running
 +in main: state main:​ running
 +in main: state co1:​ suspended
 +</​code>​
 +
 +Alternatively a ''​running''​ couroutine can resume another coroutine (which is in state ''​suspended''​):​
 +<code lua>
 +co1= coroutine.create(function()
 +    coroutine.resume(co2)
 +end)
 +
 +co2= coroutine.create(function()
 +    print("​in co2: state main:",​ coroutine.status(main))
 +    print("​in co2: state co1", coroutine.status(co1))
 +    print("​in co2: state co2", coroutine.status(co2))
 +end)
 +
 +main= coroutine.running() -- get handle to main coroutine
 +coroutine.resume(co1)
 +</​code>​
 +<​code>​Result:​
 +in co2: state main:​ normal
 +in co2: state co1 normal
 +in co2: state co2 running
 +</​code>​
 +
 +
 +But a ''​running''​ couroutine cannot resume a non-suspended coroutine. Only  coroutines in state ''​suspended''​ can be resumed:
 +<code lua>
 +co1= coroutine.create(function()
 +    local res, err= coroutine.resume(main)
 +    print(res, err)
 +end)
 +
 +main= coroutine.running() -- get handle to main coroutine
 +coroutine.resume(co1)
 +</​code>​
 +<​code>​Result:​
 +false cannot resume non-suspended coroutine
 +</​code>​
 +
 ==== Pipe-like Data exchange between Coroutines == ==== Pipe-like Data exchange between Coroutines ==
  
Zeile 473: Zeile 775:
 <note tip>​Coroutines can be used to convert a recursive data source/sink into an iterative one. See "​Programming in Lua, 2nd editon, p.79"</​note>​ <note tip>​Coroutines can be used to convert a recursive data source/sink into an iterative one. See "​Programming in Lua, 2nd editon, p.79"</​note>​
  
 +===== Documentation Generation ==
 +
 +[[http://​stevedonovan.github.io/​ldoc/​topics/​doc.md.html|Ldoc]] is preferred (over [[http://​keplerproject.github.io/​luadoc/​manual.html#​howto|LuaDoc]]).
becki/linux/lua.1359621814.txt.gz · Zuletzt geändert: 2013-01-31 08:43 von becki

Impressum - Datenschutzerklärung