บทความก่อนหน้า
Standard Library และคำสั่งพื้นฐาน
คือมอดูลและคำสั่งที่ภาษา Lua มีให้ใช้งานในตัวไม่ต้องติดตั้งเพิ่มเติมได้แก่
math string table io os corutine package debug bit32(มีในรุ่น 5.2) utf8(มีในรุ่น 5.3 ขึ้นไป)
Math module
เป็นฟังก์ชันและตัวแปรเกี่ยวกับการคำนวณทางคณิตศาสตร์
- math.sqrt(x) หาค่ารากที่สอง
- math.abs(x) หาค่าสัมบูรณ์ math.abs(-5) == 5
- math.ceil(x) ปัดเศษขึ้น math.ceil(2.001) == 3 ; math.ceil(-2.999) == -2
- math.floor(x) ปัดเศษลง math.floor(2.999) == 2 ; math.floor(-2.001) == -3
- math.min(...) หาค่าน้อยสุด math.min(5,2,8,10) == 2
- math.max(...) หาค่ามากสุด math.max(5,2,8,10) == 10
- math.fmod(x, y) หาค่า remainder ของ x กับ y ( ใช้ modulo หรือ x % y แทนได้เฉพาะค่าบวก x % y == x - math.floor(x/y) * y หรือ x - x//y * y เป็นการหารแบบปัดเศษทิ้งไปทางค่าน้อยแต่ fmod() จะใช้การหารแบบปัดเศษเข้าใกล้ศูนย์ (truncate division) )
- math.modf(x) หาค่าทศนิยม math.modf(-4.6) ได้ -4 กับ -0.6
- math.huge ตัวแปรแทนค่าจำนวนมาก ( infinity )
- math.type(x) ( ใช้ในรุ่น 5.3 ขึ้นไป เดิมในรุ่นเก่าๆ ข้อมูลประเภท number เก็บเป็นเลขทศนิยม (float) อย่างเดียวแต่ในรุ่น 5.3 ได้เพิ่มประเภทย่อยเป็นจำนวนเต็ม (integer) กับจำนวนทศนิยม (float) )
ใช้ในการตรวจสอบประเภทข้อมูลเหมือนกับ type() แต่ใช้กับ number เท่านั้น
math.type(5) == "integer" และ math.type(5.0) == "float" - ฟังก์ชันและตัวแปรด้านตรีโกนมิติได้แก่
math.pi, math.sin(x), math.cos(x), math.tan(x),
math.asin(x), math.acos(x), math.atan(y[, x]) ( ใช้ในรุ่น 5.3 ขึ้นไปถ้าเป็น 5.1, 5.2 จะใช้ math.atan(x) กับ math.atan2(y, x) แทน ) math.atan(10, 2) == math.atan(10/2),
math.sinh(x), math.cosh(x), math.tanh(x),
math.rad(x) เปลี่ยนค่า degree เป็น radian,
math.deg(x) เปลี่ยนค่า radian เป็น degree - ฟังก์ชันด้านลอการิทึมและเอกซ์โพเนนเชียลได้แก่
math.exp(x) คือ ex ,
math.log(x[, ฐาน]) ( ใช้ในรุ่น 5.2 ขึ้นไปถ้าเป็น 5.1 ใช้ math.log(x) (ฐาน e) กับ math.log10(x) (ฐาน 10) แทน ) math.log(10) == loge 10 หรือ math.log(10, 2) == log2 10
math.log10(x) คือ log10 x
math.frexp(x) คืนค่า m, n โดยที่ m*2n = x
math.ldexp(m,n) คืนค่าผลลัพธ์ของ m*2n - ฟังก์ชันเลขสุ่มได้แก่
math.randomseed(x) กำหนดค่า seed (x) สำหรับการใช้คำนวณเลขสุ่มเทียม,
math.random() สุ่มเลขทศนิยมระหว่าง 0 กับ 1,
math.random([m, ]n) สุ่มเลขจำนวนเต็มระหว่าง m กับ n ถ้าไม่กำหนด m จะเป็นสุ่มระหว่าง 1 ถึง n - ฟังก์ชันและตัวแปรจัดการจำนวนเต็ม ( มีใช้ในรุ่น 5.3 ขึ้นไป )
math.toniteger(x) แปลงค่า x เป็นเลขจำนวนเต็ม
math.tointeger(4.0) == 4 ; math.tointeger("2") == 2
math.ult(m, n) ตรวจว่าค่าจำนวนเต็ม m น้อยกว่าจำนวนเต็ม n โดยไม่คิดเครื่องหมาย (unsign less than) math.ult(-8,6) == false ; math.ult(2,4) == true
math.mininteger ตัวแปรเก็บค่าน้อยที่สุดของข้อมูลประเภทจำนวนเต็ม
math.maxinteger ตัวแปรเก็บค่ามากที่สุดของข้อมูลประเภทจำนวนเต็ม
String module
เป็นฟังก์ชันการจัดการกับข้อความ ( ไม่รองรับ unicode แต่ในรุ่น 5.3 มี utf8 ให้ใช้ )
** ในภาษา Lua ทั้ง string และ table จะมี index เริ่มที่ 1 ต่างจากบางภาษาที่เริ่มที่ 0 เช่น "asdf" จะมีความยาว 4 ตัวอักษร ตัวที่ 1 คือ "a" ไล่ไปจนตัวที่ 4 คือ "f"
- string.byte(s[,i[,j]]) คืนค่ารหัสอักขระของตัวอักษรที่ตำแหน่ง i ถึง j ของข้อความ s
เช่น string.byte("abcd",2,4) จะคืนค่าสามตัว 98 ( "b" ), 99 ( "c" ) และ 100 ( "d" )
แต่ถ้าไม่ระบุ j จะคืนค่าเดียวเช่น string.byte("abcd",3) คือ 99
และถ้าไม่ระบุ i และ j จะคืนค่าอักษรตัวแรกสุดเช่น string.byte("abcd") จะได้ 97 - string.char(x) คืนค่าตัวอักษรตามรหัส x ที่ระบุเช่น string.char(102) จะได้ "f"
- string.lower(s) แปลงข้อความ s เป็นอักษรตัวเล็ก string.lower("Hello World") ได้ "hello world"
- string.upper(s) แปลงข้อความ s เป็นอักษรตัวใหญ่ string.upper("Hello World") ได้ "HELLO WORLD"
- string.rep(s,n[, ตัวแบ่ง]) ( รุ่น 5.2 ขึ้นไปถ้ารุ่น 5.1 ใช้ string.rep(s,n) ) สร้างข้อความ s ซ้ำตามจำนวน n เช่น string.rep("hello",3,"***") จะได้ "hello***hello***hello"
- string.reverse(s) กลับตัวอักษรข้อความ s เช่น string.reverse("hello") ได้ "olleh"
- string.sub(s,i[,j]) ตัดข้อความ s ที่ตำแหน่ง i ถึง j ถ้าไม่ระบุ j จะตัดไปจนสุดข้อความถ้ากำหนดค่าเป็นลบจะเป็นการตัดจากท้ายข้อความเช่น string.sub("hello", -2) ได้ "lo"
- string.len(s) นับจำนวนตัวอักษร ( เหมือนกับใช้ #s )
- ฟังก์ชันค้นหา-แทนที่ข้อความ ( อธิบายเพิ่มภายหลังในส่วนของ pattern ) ได้แก่
string.find(s,pattern[,i[,plaintext]]) ค้นหาตำแหน่งของส่วนของข้อความแรกที่ตรงกับ pattern โดยเริ่มค้นจากตำแหน่งที่ i ในข้อความ s ถ้าไม่ระบุ i จะเริ่มที่ตำแหน่งแรกสุด ( 1 ) ส่วน plaintext เป็นค่า boolean ถ้าเป็น true จะกำหนดให้ pattern เป็นข้อความธรรมดา ถ้าเป็น false จะใช้ Lua pattern ถ้าไม่กำหนดจะใช้ค่า false
ตัวอย่าง string.find("Hello world world","wor") ได้ 7 ( "w" ) กับ 9 ( "r" )
string.gsub(s,pattern,r[,n]) การค้นหาส่วนของข้อความที่ตรงกับ pattern ในข้อความ s แล้วแทนที่ด้วยข้อความ r เป็นจำนวน n ครั้งถ้าไม่กำหนด n จะแทนที่ส่วนที่ตรงกับ pattern ทั้งหมดในข้อความ s
ตัวอย่าง string.gsub("hello world","l","X",2) ได้ "heXXo world"
string.match(s,pattern[,i]) ใช้ค้นหาข้อความคล้ายกับ string.find แต่ไม่ได้คืนค่าเป็นตำแหน่ง แต่คืนค่าเป็นข้อความที่ตรงกับ pattern แทน
string.gmatch(s,pattern) ค้นหาส่วนของข้อความทั้งหมดที่ตรงกับ pattern ในข้อความ s แล้วคืนค่าเป็น iterator ( คือเป็นชุดของข้อมูลที่สามมารถเอาไปใช้ในคำสั่งวนรอบ(ลูป)ได้ )for word in string.gmatch("This is the book.","%w+") do print(word) end -- ผลลัพธ์ --[[ This is the book ]]
- string.format(s,...) ใช้จัดรูปแบบข้อความ s โดยแทนที่และจัดรูปแบบค่าใน ... ไปยังตำแหน่งที่กำหนดใน s
ตัวอย่าง string.format("My name is %s. This pen is %.4f Bath.","John",10.25) จะได้ "My name is John. This pen is 10.2500 Bath." - ฟังก์ชันจัดการเกี่ยวกับ Binary string ( มีในรุ่น 5.3 ขึ้นไป เหมือนเป็นการเข้า/ถอดรหัสข้อมูล )
string.pack(format,...) แปลงชุดข้อมูล ... เป็น binary string ตาม format ที่กำหนด
ตัวอย่าง string.pack("I2I1",1,2) ได้เป็น "\001\000\002"
string.packsize(format) บอกขนาดเป็น byte ของข้อมูลที่ทำเป็น binary string ด้วย format นั้นเช่นตัวอย่างข้างบน "I2I1" จะได้ข้อมูลขนาด 3 byte 1 แปลงเป็น "\001\000" 2 byte และ 2 เป็น "\002" 1 byte
string.unpack(format,s[,i]) ถอดข้อมูลจาก binary string (s) ที่ตำแหน่ง i ด้วย format ที่กำหนดและคืนค่าตำแหน่งถัดจากข้อมูลนั้น
ตัวแย่าง string.unpack("I2I1","asdf\002\000\003zaaa",5) ได้ข้อมูล 2 ตัวคือ 2 และ 3 ตำแหน่งที่ 8 ("z") เพื่อเอาตำแหน่งไปถอดข้อมูลต่อไปเช่นในกรณีที่มีชุดข้อมูลหลายชุดมาต่อกันเป็นข้อความเดียว - string.dump(functionname) แปลงฟังก์ชันเป็น binary string
ตัวอย่างfunction f() print"hello" end local c = string.dump(f) --[[ ข้อมูลใน c "\027LuaS\000\025\147\r\n\026\n\004\b\004\b\bxV\000\000\000\000\000\000\000 \000\000\000\000(w@\001\005=lua\001\000\000\000\001\000\000\000\000\000\002 \004\000\000\000\006\000@\000A@\000\000$@\000\001&\000\128\000\002\000\000\000 \004\006print\004\006hello\001\000\000\000\000\000\000\000\000\000\004\000\000 \000\001\000\000\000\001\000\000\000\001\000\000\000\001\000\000\000\000\000 \000\000\001\000\000\000\005_ENV" ]] -- สามารถนำกลับมาใช้ด้วย load() local d = load(c) d() -- ผลลัพธ์ --[[ hello ]]
UTF-8 module
ตัวอักษรใน Lua ปกติเป็นรหัส ASCII ที่มีอักขระละ 1 byte จึงรองรับแค่ตัวเลขตัวอักษรภาษาอังกฤษและอักขระควบคุมกับสัญลักษณ์พิเศษบางตัวรวม 128 ตัวและตัวอักษรภาษาถิ่นอีก 128 ตัวเท่านั้นแต่ในรหัส Unicode ที่รองรับกับภาษาอื่นๆ ได้หลายภาษาโดยเฉพาะรหัสแบบ UTF-8 ที่นิยมที่สุด 1 ตัวอักษรมีขนาดได้ตั้งแต่ 1-4 byte ใน Lua 5.3 จึงเพิ่มเติมฟังก์ชันที่ใช้จัดการกับรหัส Unicode ได้บางส่วนดังนี้
- utf8.char(n) คืนค่าตัวอักษรของรหัสนั้นเช่น utf8.char(3585) จะได้ "\224\184\129" หรือก็คือ "ก"
- utf8.codepoint(s[,i[,j]]) คืนค่ารหัสตัวอักษรในข้อความ s ที่ตำแหน่ง byte i ถึง j ถ้าไม่กำหนดตำแหน่งจะใช้ตำแหน่งแรก
ตัวอย่าง utf8.codepoint("กขค",1,4) จะได้ 3585 ( "ก" ) และ 3586 ( "ข" ) ( อักษรภาษาไทยตัวละ 3 byte ตัวที่สองเลยเริ่มที่ตำแหน่ง byte ที่ 4 ) - utf8.len(s[,i[,j]]) คืนค่าจำนวนตัวอักษรตั้งแต่ตำแหน่ง byte ที่ i ถึง j ของข้อความ s
ตัวอย่าง utf8.len("กขค",1,4) จะได้ 2 ( "กข" มี 2 ตัวอักษร ) - utf8.offset(s,n[,i]) คืนค่าตำแหน่ง byte เริ่มต้นของตัวอักษร unicode ลำดับที่ n ในข้อความ s เริ่มค้นหาที่ตำแหน่ง i ถ้าไม่ระบุ i จะเริ่มที่ตำแหน่งแรกสุดของข้อความ
ตัวอย่าง utf8.offset("กขค",3) จะได้ 7 ( "ก" 1-3, "ข" 4-6, "ค" 7-9 ) - utf8.codes(s) คืนค่าเป็น iterator ของตำแหน่ง byte และรหัสตัวอักษร
ตัวอย่างfor i,c in utf8.codes("กขค") do print(i,c) end -- ผลลัพธ์ --[[ 1 3585 4 3586 7 3588 ]]
- utf.charpattern เป็นตัวแปรเก็บค่า pattern ของตัวอักษร unicode
( "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" )
Table module
เป็นฟังก์ชันจัดการเกี่ยวกับข้อมูลประเภท table
- table.concat(t[,ตัวแบ่ง]) คืนค่าเป็นข้อความที่มาจาก value ของ table t คั่นด้วยตัวแบ่ง โดยที่ t ต้องเป็น table ที่มี key เป็นเลขลำดับ และมี value เป็น number กับ string เท่านั้น
ตัวอย่าง table.concat({1,"abc",30}, " #=# ") จะได้ "1 #=# abc #=# 30" - table.insert(t[,i],v) เพิ่มค่า v ไปเป็นสมาชิกใน t ที่ลำดับ key ที่ i โดยที่ t ต้องเป็น table ที่มี key เป็นเลขลำดับถ้าไม่กำหนด i จะไปเพิ่มต่อจากลำดับสุดท้าย
ตัวอย่าง t = {1,2,3}; table.insert(t,2,"a") จะได้ t == {1,"a",2,3} - table.move(t1,i,j,k[,t2]) ( มีในรุ่น 5.3 ) ก็อปปี้ค่าใน table t1 ที่ตำแหน่ง key ที่ i ถึง j ไปใส่ใน table t2 ที่ตำแหน่ง key ที่ k โดยที่ t ต้องเป็น table ที่มี key เป็นเลขลำดับถ้าไม่ระบุ t2 จะเป็นการเอาค่าไปทับใน t1 แทน
ตัวอย่าง t = {1,2,3,4,5}; table.move(t,3,5,2) จะได้ t == {1,3,4,5,5} - table.remove(t[,i]) เอาสมาชิกที่ตำแหน่ง i ออกจาก table t โดยที่ t ต้องเป็น table ที่มี key เป็นเลขลำดับและคืนค่า value ที่ตำแหน่งนั้นถ้าไม่ระบุ i จะลบสมาชิกที่ตำแหน่งสุดท้าย
ตัวอย่าง t = {"a","b","c","d"}; v = table.remove(t,2) จะได้ t == {"a","c","d"} และ v == "b" - table.sort(t[,f]) เรียงลำดับสมาชิกใน table t ตามเงื่อนไขที่กำหนดด้วยฟังก์ชั่น f โดยที่ t ต้องเป็น table ที่มี key เป็นเลขลำดับถ้าไม่กำหนด f จะเรียงจากน้อยไปมากโดยที่ value ต้องเป็น number หรือ string และสมาชิกทุกตัวต้องเป็นประเภทเดียวกัน
ตัวอย่าง t = {"a",10,"X",2,{}}; table.sort(t,function(a,b) return tostring(a),tostring(b) end) จะได้
t == {10,2,"X","a",{}} - table.pack(...) ( รุ่น 5.2 ขึ้นไป )สร้าง table แบบมี key เป็นเลขลำดับโดยมีสมาชิกเป็น ... คล้ายกับการใช้ {...} แต่จะมีสมาชิกพิเศษ n มีค่าเป็นจำนวนสมาชิกใน ...
ตัวอย่าง t = table.pack(3,"a",{},20) จะได้ t == {3,"a",{},20,n=4} - table.unpack(t[,i[,j]]) ( รุ่น 5.2 ขึ้นไป ถ้ารุ่น 5.1 ใช้ unpack(t[,i[,j]]) ) คืนค่าเป็นสมาชิกของ table t ที่ตำแหน่ง key ที่ i ถึง j ถ้าไม่กำหนด i จะเริ่มที่ตัวแรก ถ้าไม่กำหนด j จะคืนค่าจนถึงตัวสุดท้าย
ตัวอย่าง t = {1,2,3,4}; a, b, c = table.unpack(t,2,3) จะได้ a == 2, b == 3, c == nil
IO module
IO มาจาก Input Output คือการเชื่อมต่อกับภายนอก (ฮาร์ดแวร์) เช่นอ่านและเขียนข้อมูลลงไฟล์หรืออุปกรณ์อื่นๆ
- io.read([...]) หรือ io.imput:read([...]) คืนค่าข้อมูลที่อ่านจาก input ปัจจุบันถ้าไม่ได้กำหนด input จะเป็นรับข้อมูลจากคีย์บอร์ด ( standard input หรือ io.stdin ) ส่วน ... เป็นการกำหนดรูปแบบการอ่านสามารถใส่ได้หลายตัวเช่น io.read("n","l") ถ้าไม่ระบุจะอ่านค่าทีละบรรทัดแบบไม่นับรวมอักขระจบบรรทัด ( end of line หรือ EOF ) เช่น local value = io.read() โปรแกรมจะรอให้พิมพ์ข้อความที่หน้าจอเมื่อกด enter จะส่งข้อมูลที่พิมพ์เข้าไปเก็บที่ตัวแปร value
- io.write(...) หรือ io.output:write(...) เขียนข้อมูล ... ลง output ปัจจุบันถ้าไม่ได้กำหนด output จะเป็นการแสดงผลออกทางหน้าจอ ( standard output หรือ io.stdout ) คล้ายกับฟังก์ชั่น print() แต่ฟังก์ชั่นนี้จะไม่ขึ้นบรรทัดใหม่ให้
- io.input(f) กำหนด input ปัจจุบันให้เป็น f โดยที่ f จะเป็นชื่อไฟล์ ( string ) หรือเป็นไฟล์ ( userdata ) ก็ได้
- io.output(f) กำหนด output ปัจจุบันให้เป็น f โดยที่ f จะเป็นชื่อไฟล์ ( string ) หรือเป็นไฟล์ ( userdata ) ก็ได้
- io.stdin ตัวแปรเก็บค่า standard input ของระบบ ( เป็นข้อมูลประเภท userdata แบบเดียวกับไฟล์ )
- io.stdout ตัวแปรเก็บค่า standard output ของระบบ ( เป็นข้อมูลประเภท userdata แบบเดียวกับไฟล์ )
- io.stderr ตัวแปรเก็บค่า standard error ของระบบ ( เป็นข้อมูลประเภท userdata แบบเดียวกับไฟล์ )
- io.open(fname[,m]) เปิดไฟล์ที่ชื่อ fname ด้วยโหมด m ( "r", "w", "a", "r+", "w+", "a+", "rb", "wb", "ab", "r+b", "w+b", "a+b" ) แล้วคืนค่าเป็นไฟล์ ( userdata )
- io.close([f]) หรือ f:close() บันทึกข้อมูลที่ยังไม่ได้บันทึกและปิดไฟล์ f หรือถ้าไม่ระบุ f จะเป็นการปิด output ปัจจุบัน
- io.flush() หรือ io.output:flush() บันทึกข้อมูลที่ยังไม่ได้บันทึกลงใน output ปัจจุบัน
- io.lines([fname[,format]]) หรือ io.input:lines([fname[,format]]) ( มีในรุ่น 5.2 ขึ้นไปถ้ารุ่น 5.1 จะเป็น io.lines([fname]) ) คืนค่าเป็น iterator ของข้อมูลแต่ละบรรทัดในไฟล์ชื่อ fname ถ้าไม่กำหนดจะใช้ input ปัจจุบัน ส่วน format จะเหมือนกับ io.read()
ตัวอย่างf=io.input("test.txt") while true do local line = io.read() if not line then break end print(line) end io.close(f) io.input(io.stdin) -- โค้ดข้างบนสามารถเขียนได้ด้วย io.lines() เป็น for line in io.lines("test.txt") do print(line) end
- io.type(f) ใช้ในการตรวจสอบประเภทข้อมูลเหมือนกับ type() แต่ใช้กับข้อมูลประเภทไฟล์ ถ้าใช้ type() จะได้เป็น "userdata" ซึ่งอาจสับสนกับ userdata ชนิดอื่นๆ ถ้าใช้ io.type() จะได้เป็น "file" ถ้าเป็นข้อมูลประเภทอื่นจะได้ nil
- io.tmpfile() สร้างไฟล์ชั่วคราวเขียนอ่านข้อมูลโดยที่ไฟล์จะถูกลบทิ้งเมื่อจบโปรแกรม
- io.popen(c[,m]) เรืยกคำสั่ง c ของ OS ( เช่นคำสั่งใน cmd ของ Windows หรือ shell ใน Linux/Mac ) ด้วยโหมด m ( "r" หรือ "w" ) แล้วส่งผลลัพธ์เป็นข้อมูลประเภทไฟล์
OS module
เป็นฟังก์ชันเกี่ยวกับการทำงานของระบบ ( Operating System )
- ฟังก์ชันเกี่ยวกับเวลาได้แก่
os.clock() คืนค่าเป็น CPU time
os.time([t]) คืนค่าเวลาเป็นวินาทีของข้อมูลเวลาใน table 1 ถ้าไม่ระบุ t จะใช้วันเวลาปัจจุบัน
ตัวอย่าง os.time({ year = 2004, month = 8, day = 30, hour = 6, min = 32, sec = 1, dst = true }) จะได้เป็นเวลา 1093822321 วินาที ( ในเครื่องผม os.time{year=1970, month=1, day=1, hour=7} เป็น 0 เพราะ locale กรุงเทพฯ +7 ชม. )
os.date([format[,time]) คืนค่าวันเวลาของเวลาเป็นวินาที time ตามรูปแบบ format ถ้าไม่กำหนด time จะใช้วันเวลาปัจจุบัน และถ้าไม่กำหนด format จะคืนค่าเป็น string ( "วันตัวย่อ เดือนตัวย่อ วันที่ ชั่วโมง:นาที:วินาที ปีค.ศ." )
ตัวอย่าง os.date("Start date is %B %d %Y", 0) จะได้ "Start date is January 01 1970"
ถ้า format เป็น "*t" จะคืนค่าเป็น table
os.difftime(time2,time1) หาผลต่างของเวลา time2 กับ time1 ( คล้าย time2 - time1 แต่ค่าที่ได้จะเป็น float ) - os.setlocale(l[,category]) ดูหรือเปลี่ยนค่า locale l ตาม category นั้น ถ้า l เป็น nil จะเป็นการแสดงค่า locale ปัจจุบันแทนการเปลี่ยน locale ถ้าไม่กำหนด category จะแสดงหรือเปลี่ยนค่าในทุก category
- ฟังก์ชันเกี่ยวกับการจัดการไฟล์ได้แก่
os.tmpname() คืนค่าเป็นชื่อไฟล์ชั่วคราว
os.rename(old,new) เปลี่ยนชื่อไฟล์หรือโฟลเดอร์จาก old เป็น new
os.remove(fname) ลบไฟล์หรือโฟลเดอร์ว่างที่ชื่อ fname - ฟังก์ชันอื่นๆ
os.getenv(v) คืนค่าตัวแปรระบบ v เช่น os.getenv("PATH")
os.execute(c) เรียกคำสัง c ของระบบแล้วคืนค่าสามค่าคือ true, "exit", 0 ถ้าคำสั่งทำงานปกติ
os.exit([code[,close]]) ( สำหรับรุ่น 5.2 ขึ้นไปหรือ os.exit([code]) สำหรับ 5.1 ) คำสั่งจบการทำงาน code ในรุ่น 5.2 ขึ้นไปจะเป็น true, false หรือตัวเลข ถ้าไม่กำหนดจะเป็น true ส่วน 5.1 จะเป็นตัวเลขเท่านั้นถ้าไม่กำหนดจะเป็น 0 ส่วน close จะเป็นค่า true, false ถ้าไม่กำหนดจะเป็น false
Coroutine module
เป็นฟังก์ชันเกี่ยวกับการสลับการทำงาน ( อาจเป็นเรื่องที่เข้าใจยากนิดหน่อยจะอธิบายเพิ่มภายหลัง )
- coroutine.create(f) สร้างข้อมูลประเภท thread จากฟังก์ชั่น f
- coroutine.wrap(f) คล้าย coroutine.create() แต่จะคืนค่าเป็นฟังก์ชั่น f ที่สามารถเรียกให้ thread ทำงานต่อได้ในตัวเองแทนการเรียกใช้ coroutine.resume()
- coroutine.resume(thread[.value1,value2,...,valueN]) เป็นการสั่งให้ thread ทำงานต่อโดยส่ง value1 ถึง valueN ให้กับ thread ไปใช้งานโดยถ้าเป็นการเรียกครั้งแรกจะส่งให้ prarmeters ของฟังก์ชั่นนั้นแต่ถ้าเรียกครั้งต่อไปจะเริ่มทำงานต่อจากคำสั่ง coroutine.yield() ล่าสุดโดยจะส่งค่าให้กับตัวแปรที่มารับค่าจาก coroutine.yield() นั้น
- coroutine.isyieldable() คืนค่า true เมื่อ thread ที่ทำงานนั้นสามารถ yield ได้
- coroutine.yield([...]) หยุดการทำงานของ thread นั้นและส่งค่า ... คืนกลับมา
- coroutine.status(therad) ดูสถานะปัจจุบันของ thread ( "running", "suspended", "normal", "dead" )
- coroutine.running() คืนค่าเป็น thread ที่กำลังทำงานอยู่แต่ถ้าเป็นเทรดหลักจะคืนค่าเป็น nil
- coroutine.close(thread) ( *ฟังก์ชั่นใหม่มีในรุ่น 5.4 ) สั่งปิดตัวแปรใน thread ( thread ต้องมีสถานะเป็น suspended หรือ dead ) ที่กำหนดเป็น <close> และเปลี่ยนสถานะของ therad เป็น dead แล้วคืนค่า true กรณีที่ไม่มีข้อผิดพลาด
Package module
เป็นฟังก์ชันและตัวแปรสำหรับจัดการเกี่ยวกับมอดูลต่างๆ
- package.path ตัวแปรเก็บค่า ( string ) พาธที่เก็บมอดูลที่เป็นไฟล์ภาษา Lua ( .lua )
- package.cpath ตัวแปรเก็บค่า ( string ) พาธที่เก็บมอดูลที่เป็นไฟล์ไบนารี่ ( ไฟล์นามสกุล .so ใน Linux/Mac หรือ .dll ใน Windows )
- package.loaded เป็น table ที่เก็บมอดูลที่โหลดอยู่ในระบบรวมถึงมอดูลมาตรฐานด้วย
- package.loadlib(path,name) โหลดมอดูลที่เป็น C package ( มอดูลที่เป็นไฟล์ไบนารี่ )
- package.preload เป็น table ที่เก็บฟังก์ชั่นที่เราสร้างขึ้นสำหรับโหลดเป็นมอดูลในกรณีที่ต้องการการโหลดแบบพิเศษบางอย่าง
- package.searchers เป็น table ที่เก็บฟังก์ชันพิเศษของ Lua สำหรับให้ฟังก์ชัน require() เรียกเพื่อโหลดมอดูลในรูปแบบต่างๆ เช่นดูจากใน package.path, package.cpath, package.preload เป็นต้น
- package.searchpath(name,path[,sep[,rep]]) คืนค่าเป็นพาธ ( string ) ที่เก็บมอดูล name จาก path ( string ) โดยจะแทนที่ sep ใน name ด้วย rep ถ้าไม่กำหนด sep จะใช้ . และ rep จะเป็น ตัวแบ่งพาธตามระบบนั้น ( Mac/Linux ใช้ "/" ส่วน Windows ใช้ "\" )
- package.config เป็น string ที่เก็บอักขระที่ใช้จัดรูปแบบของพาธ
Debug module
เป็นฟังก์ชันที่ใช้ในการตรวจสอบการทำงานของโปรแกรม ( debug ) หรือใช้แก้ไขดัดแปลงคุณสมบัติบางอย่างหรือเพิ่มความสามารถให้กับโปรแกรมได้แก่
- debug.debug() เข้า debug interactive mode
- debug.gethook([thread]), debug.sethook([thread,]hook,mask[,count]) ดึงค่ากับตั้งค่าฟังก์ชัน hook ที่ใช้ขัดจังหวะการทำงานของโปรแกรมเมื่อโปรแกรมทำงานถึงเหตุการณ์ที่กำหนดใน mask เช่นเมื่อเรียกใช้ฟังก์ชันหรือเมื่อฟังก์ชันคืนค่าออกมา
- debug.getinfo([thread,]f[,what]) คืนค่าเป็น table ที่เก็บข้อมูลของฟังก์ชัน f เช่นประเภท ( Lua หรือ C ) ชื่อฟังก์ชัน จำนวนบรรทัด ฯลฯ
- debug.getlocal([thread,]level,l), debug.setlocal([thread,]level,l,value) ดึงค่ากับตั้งค่าตัวแปร local ลำดับ l ที่ระดับ level
- debug.getmetatable(value), debug.setmetatable(value, metatable) ดึงค่า metatable จากประภทข้อมูลของ value กับผูก metatable กับประเภทข้อมูลของ value
- debug.getregistry() คืนค่า table ที่เก็บ registry สำหรับให้ภาษา C เรียกใช้
- debug.getupvalue(f,u), debug.setupvalue(f,u,value) ดึงค่ากับตั้งค่า upvalue ที่ index u ของฟังก์ชัน fUpvalue คืออะไร?
จากที่เรารู้มาว่าตัวแปร local นั้นจะสามารถเข้าถึงได้จากภายใน block เท่านั้นหรือกล่าวได้ว่าพอออกจาก block ตัวแปรก็ถูกทำลายไปแล้วแต่ Closure สามารถเข้าถึงตัวแปร local ใน block เดียวกับที่สร้างฟังก์ชั่นนั้นได้ ซึ่งที่จริงก็คือการเข้าถึง upvalue ที่เป็นตัวแปรอิสระของ closure นั้นนั่นเอง - debug.getuservalue(u), debug.setuservalue(u,value) ดึงค่ากับตั้งค่า userdata u
- debug.traceback([thread,] [message [, level]]) แสดงการสืบค้นกลับของฟังก์ชันที่ระดับ level ที่กำหนดถ้าไม่กำหนดจะแสดงทั้งหมด
- debug.upvalueid(f,n) คืนค่าเป็น userdata ที่ชี้ไปที่ upvalue n ของฟังก์ชัน f
- debug.upvaluejoin(f1,n1,f2,n2) ทำให้ upvalue ลำดับที่ n1ของฟังก์ชัน f1 ไปใช้ค่า upvalue ลำดับที่ n2 ของฟังก์ชัน f2
คำสั่งอื่นๆ
- assert(v[,message]) แสดงข้อความ message กรณีที่ค่า v เป็นเท็จ
- warn(msg1,...) ( *ฟังก์ชันใหม่มีในรุ่น 5.4 ) แสดงข้อความ warning ด้วย arguments ในฟังก์ชัน
- error(message[,level]) หยุดการทำงานของโปรแกรมและแสดงข้อความ message
- collectgarbage([option[, arg]]) สั่งให้เก็บกวาดขยะ ( เช่นข้อมูลที่ไม่ได้ใช้งานแล้ว ) เพื่อคืนค่าหน่วยความจำในระบบ ปกติในโปรแกรมทั่วไปไม่จำเป็นต้องเรียกใช้คำสั่งนี้
- pcall(f[,arg1, ...]) เรียกใช้ฟังก์ชัน f โดยใส่ arg1, ... ไปเป็น argument ของ f โดยคืนค่าสถานะ true กับผลลัพธ์ของฟังก์ชัน f กรณีที่ฟังก์ชันทำงานถูกต้องแต่ถ้ามีข้อผิดพลาดจะคืนค่าสถานะ false และข้อความแสดงข้อผิดพลาดกลับมาโดยที่ไม่หยุดการทำงานของโปรแกรม ( คล้าย try catch exception ในภาษาอื่น )
- xpcall(f,msgf[,arg1, ...]) คล้าย pcall แต่ข้อความแสดงข้อผิดพลาดจะส่งให้กับฟังก์ชัน msgf เพื่อจัดการข้อความนั้นเช่นใส่ข้อความอธิบายเพิ่มเติมหรือบันทึก log หรือพิมพ์ออกหน้าจอเป็นต้น
- getmetatable(t), setmetatable(t, metatable) คล้ายในฟังก์ชันที่มีใน debug แต่จะทำงานกับข้อมูลประเภท table เท่านั้นและเฉพาะ table ที่เรียกใช้เท่านั้น แต่ใน debug จะทำกับทั้งประเภทข้อมูลเดียวกันทั้งหมด เช่น debug.setmetatable("a",{__call=function() ... end}) จะผูก metatable กับข้อมูลประเภท string ทั้งหมดไม่ใช่แค่ "a" เท่านั้น ดังนั้นจะใช้ "b" หรือ "" ก็ได้ผลเหมือนกัน แต่ setmetatable(table1,{__index=table2}) จะมีผลกับแค่ table1 เท่านั้น ( โดย metamethod __index จะไปดึงข้อมูลจาก table2 ในกรณีที่ table1 นั้นไม่มี index นั้นอยู่ )
- dofile([filename]) โหลดไฟล์ชื่อ filename ( ที่มีคำสั่งภาษา Lua ) และเรียกทำงานในส่วนโปรแกรมในไฟล์นั้น
- require(modname) โหลดมอดูลชื่อ modname มาเก็บไว้เพื่อเรียกฟังก์ชันในมอดูลมาใช้งานภายหลังได้โดยจะดูจากใน package.loaded ก่อนถ้ามีมอดูลนั้นอยู่แล้วจะไม่โหลดซ้ำถ้าไม่มีค่อยใช้ package.searcher ไปค้นจาก package.preload ไม่เจอก็ไปค้นจาก package.path และ package.cpath ตามลำดับ
- load(chunk[,chunkname[,mode[,env]]]) รับค่าเป็น string หรือ binary ที่เป็นโค้ดภาษา Lua ( chunk ) เช่น "a=3 c = a + 5 print(c)" หรือ string.dump(function(x) return x*2 end) แล้วคืนค่าเป็นฟังก์ชั่นที่สามารถเรียกทำงานได้
- loadfile([filename[,mode[,env]]]) คล้ายกับ load แต่รับค่าเป็นไฟล์แทน
- print(...) แสดงผลข้อความออกหน้าจอโดยรับค่า argument ได้หลายตัวคั่นด้วย " , " โดยจะแปลงข้อมูลใน argument เป็นข้อความ เช่นข้อมูลประเภท table ก็จะแสดงเป็น table 0xXXXXXX
- next(t[,i]) เป็นฟังก์ชัน iterater คืนค่าคีย์และสมาชิกใน table t ทีละคู่ในแต่ละรอบโดยจะเอาค่าคีย์ที่คืนออกมาส่งกลับไปเป็น argument i ในรอบถัดไปแล้วจะได้ค่าลำดับถัดมา
a = {2,4,6} -- มีค่าเท่ากับ {[1]=2, [2]=4, [3]=6} print(next(a)) -- ได้ 1 2 print(next(a,2)) -- ได้ 3 6 print(next(a,3)) -- ได้ nil print(next(a,1)) -- ได้ 2 4 b = {a=2,b=4,c=6} -- เนื่องจากคีย์ที่ไม่ใช่เลขลำดับจะไม่เรียง -- ในการสร้างแต่ละครั้งอาจลำดับไม่เหมือนตัวอย่าง print(next(b,"a")) -- ได้ c 6 print(next(b,"c")) -- ได้ nil print(next(b)) -- ได้ b 4 print(next(b,"b")) -- ได้ a 2
- pairs(t) เป็นฟังก์ชัน iterator ส่งค่าคีย์และสมาชิกใน table t ออกมาทีละคู่เหมือน next แต่ไม่ต้องใส่ลำดับคีย์
- ipairs(t) เป็นฟังก์ชัน iterator ส่งค่าคีย์และสมาชิกใน table t ออกมาทีละคู่เหมือน pairs() แต่ใช้กับเฉพาะสมาชิกที่มีคีย์เป็นเลขลำดับที่เรียงต่อเนื่องกันตั้งแต่ 1 เท่านั้น
- rawequal(v1,v2) ตรวจสอบว่าค่า v1 เท่ากับ v2 หรือไม่โดยไม่ได้เรียกใช้ metamethod __eq ( ปกติถ้าใช้ operator == จะไปเรียกใช้งาน __eq ซึ่งเราสามารถใช้ setmetatable() กับ debug.setmetatable() เพื่อจัดการกับวิธีการตรวจสอบค่าได้ เช่นเปลี่ยนให้ใช้ฟังก์ชันที่ตรวจว่า table ที่มีคีย์เหมือนกันถือว่าเท่ากันแทน แต่ถ้าใช้ rawequal() จะใช้การตรวจสอบดั้งเดิมคือจะเท่ากันต่อเมื่อเป็น table เดียวกัน )
- rawlen(v) หาจำนวนความยาวของ v ( table หรือ string ) โดยไม่ได้เรียกใช้ __len ( ถ้าใช้ # จะไปเรียกใช้ __len )
- rawget(t,i) คืนค่าสมาชิกแท้ใน table t ที่ตำแหน่ง index i โดยไม่ได้เรียกใช้ __index ( ถ้าใช้ t[i] หรือ t.i จะไปเรียกใช้ __index )
- rawset(t,i,value) ใส่ค่า value ให้ table t ที่ index i โดยไม่ได้เรียกใช้ __newindex ( ถ้าใช้ t[i]=value หรือ t.i=value จะไปเรียกใช้ __newindex )
- select(index, ...) เคยแสดงตัวอย่างในหัวข้อ Function: variadic arguments มาแล้วคือหา argument เริ่มจากลำดับที่ index จากใน ... เป็นต้นไปถ้าใส่ "#" แทน index จะคืนค่าเป็นจำนวน argument ( ดูตัวอย่างใน ตอนที่แล้ว )
- tonumber(e[,base]) แปลงข้อมูล e ( string ) ฐาน base เป็นตัวเลขฐานสิบ เช่น
print(tonumber("20")) -- ได้ 20 print(tonumber("a")) -- ได้ nil print(tonumber("20",16)) -- ได้ 32 print(tonumber("20",8)) -- ได้ 16 print(tonumber("20",2)) -- ได้ nil print(tonumber("11",2)) -- ได้ 3 print(tonumber("a",16)) -- ได้ 10 print(tonumber("A",16)) -- ได้ 10
- tostring(v) แปลงข้อมูล v เป็นข้อความ ( โดยปกติข้อมูลที่ไม่ใช่ boolean, number, string จะแสดงเป็นประเภทกับ address หน่วยความจำของข้อมูลนั้น ) แต่ถ้า v มี metatable ที่มี __tostring อยู่ก็จะไปเรียกใช้ __tostring
- type(v) แสดงประเภทของข้อมูล
จบแล้วครับเป็นบทที่ยาวมากและก็เขียนนานมากด้วยที่จริงจะพยายามสรุปสั้นๆ แล้วค่อยไปอ่านเพิ่มใน manual หรืออธิบายเพิ่มในตอนที่กล่าวถึงแต่ก็อดไม่ได้กลัวจะงง ( หรือจะงงเพิ่มก็ไม่รู้ ) ไว้ถ้ามีเนื้อหาที่เกี่ยวข้องก็จะอธิบายเพิ่มเติมครับ ตอนหน้าพักเบรกมาลองทำตัวอย่างโปรแกรมง่ายๆ บ้างครับ
บทความถัดไป
ความคิดเห็น
แสดงความคิดเห็น