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-11-13 09:24]
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 29: Zeile 30:
 io.stderr:​write() ​         -- Print a string to stderr io.stderr:​write() ​         -- Print a string to stderr
 </​code>​ </​code>​
 +
 +==== 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 == ===== C-style ?-operator equivalent ==
Zeile 44: Zeile 53:
 <code lua> <code lua>
 d1, d2 = table.unpack(a and {b1, b2} or {c1, c2}) 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>​ </​code>​
  
Zeile 131: 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 361: 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 505: 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 ==
  
becki/linux/lua.1384334678.txt.gz · Zuletzt geändert: 2013-11-13 09:24 von becki

Impressum - Datenschutzerklärung