View Full Version : [JX] Ai chưa bit lua thì cùng học nào!
huongphieubat
14-09-08, 02:44 PM
Để cho những ai máu me dev Jx mà chưa bit ji về lua,hum nay xin mạn phép viết bài này để cùng nhau học lua. (Tui cũng đang học :P).
Mỗi ngày 1 bài
Vô bài đầu nhé
1. Giới thiệu Lua. Lệnh gán
Một trong những lí do mà phần lớn ``dân'' kĩ thuật ngại lập trình là vì những ngôn ngữ mới (C#, Java) dựa trên một hệ thống (framework) thư viện rất đồ sộ. Thật vậy, bạn có thể xây dựng những chương trình có giao diện rất đẹp, với hệ thống cơ sở dữ liệu hiện đại, hay dựa trên các công nghệ web mới nhất... Nhưng đó chỉ là những phần thưởng riêng cho ``dân'' ngành IT, những người mà số dòng mã lệnh viết trong một năm cũng nhiều như số dòng trong bản báo cáo thuyết minh nộp cho đối tác vậy. Rõ ràng, việc trang bị cho mình một cặp kính cận > 5 đi-ốp và một quyển sổ tay lập trình ngôn ngữ X. luôn kè kè trên bàn máy tính là rất không khả thi !
Với người dân kĩ thuật (thủy lợi, xây dựng, giao thông ...), tính linh động là quan trọng. Nhiều bài toán kĩ thuật trong thực tế cần được tính toán sơ bộ một cách nhanh nhất, hiệu quả nhất. Lập trình? Tất nhiên là cần thiết rồi. Nhưng lập trình như thế nào cho hiệu quả nhất khi ta phải bắt đầu từ một dòng mã lệnh đầu tiên ? Lua là một giải pháp hứa hẹn.
Ngôn ngữ lập trình Lua (đọc là Lu-a) ra đời năm 1993 tại Đại học PUC-Rio, Rio de Janeiro, Brazil. Hiện nay (chương trình) Lua cũng là một phần mềm tự do: người dùng có quyền tự do download, gửi cho bạn bè, viết phần mềm từ Lua phục vụ cho mục đích bất kì: học tập, nghiên cứu, thương mại, kể cả viết các trò chơi (một trong những thế mạnh của ngôn ngữ này). Lua được đánh giá là một ngôn ngữ thông dịch có tốc độ vào loại nhanh nhất. Một số kết quả so sánh với ngôn ngữ Perl (thuộc vào dạng thông dịch nhanh) có thể được xem tại đây (<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>〈=lua&lang2=perl).
Bạn có thể hình dung mức độ nhỏ gọn của Lua khi download phiên bản chạy trên Windows từ đây (<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>). Một file nén < 600 KB chứa các file exe để chạy chương trình. Không cần phải cài đặt, điều này rất tiện. Chẳng hạn khi ta muốn chạy chương trình viết từ ở nhà, trên một máy tính khác mà ta không được quyền admin.
Trong chớp mắt, bạn đã download được file Lua (lua5_1_3_Win32_bin.zip). Giải nén vào một thư mục như C:\Lua. Click vào file lua5.1.exe. Dấu nhắc lệnh, với hình một kí hiệu lớn hơn, sẽ hiện ra:
CODE
Lua 5.0.3 Copyright (C) 1994-2006 Tecgraf, PUC-Rio
>
Bây giờ hãy thử một số lệnh nhé. Lệnh cơ bản nhất là lệnh gán, nó giống như trong (Visual)BASIC
CODE
> x = 5
>
Như vậy câu lệnh đúng, máy không báo lỗi và giá trị 5 được lưu vào trong biến x.
Khoan đã, hình như ta thiếu một bước gì đó? Khai báo biến, sao lại không khai báo biến x là số nguyên?
Câu trả lời: ngay khi Lua gặp lệnh gán thì nó sẽ căn cứ vào giá trị (ở đây là 5) mà quyết định rằng biến x có kiểu số chứ không phải kiểu chữ. Đặc điểm này tỏ ra rất có lợi: ta sẽ tiết kiệm được công gõ lệnh mà không sợ nhầm lẫn gì, vì trong kĩ thuật ta vẫn quy định mỗi biến có kiểu riêng của nó, không thay đổi được.
Một số lệnh gán tiếp theo tỏ ra rất bình thường:
CODE
> y = 1.4 ^ 2
> z = x + y
Điều gì sẽ xảy ra nếu ta không viết vế trái của lệnh gán? Riêng trong trường hợp ta đang chạy trên dấu nhắc lệnh ( > ... ) thì máy sẽ không báo lỗi. Thay vì vậy, nó sẽ hiểu rằng kết quả tính được ở vế phải không lưu vào biến nào cả mà sẽ in ra màn hình.
CODE
> = z
6.96
Điểm đặc biệt thứ hai là: một loạt các giá trị bạn có thể được gán bằng một lệnh gán duy nhất. Kết quả là các biến vế trái (phân cách bởi dấu phảy) được gán với giá trị lần lượt ở vế phải:
CODE
> m, n = 8, 6
> = m
8
> = n
6
Luyện tập 1. Lệnh gán sau đây có lỗi không? Kết quả chứng tỏ máy thực hiện như thế nào?
CODE
> a, b, c = 1, 2, 3, 4
Luyện tập 2. Tựa như các lệnh ở trên ta đã viết, liệu ta có thể viết một lệnh gói gọn như sau không? Tại sao?
CODE
> xx, yy, zz = 5 , 1.4^2 , xx + yy
Bạn tự thực hiện các phép tính trên dấu nhắc lệnh Lua. Cuối cùng hãy thử làm Qu!z sau đây:
Qu!z 1. Để tính lưu lượng trong sông các kĩ sư vẫn thường dùng công thức
<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>
Tự chọn một giá trị độ nhám từ 0.02 đến 0.04, độ sâu (bán kính thủy lực) từ 2 đến 3, độ dốc từ 0.0001 đến 0.0003. Tính ra Q. Hãy reply lại quá trình bạn đã làm trên Lua (câu lệnh + kết quả) !
Trang chủ của Lua: <b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b> (<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>).
Hướng dẫn người mới học <b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b> (<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>)
Sổ tay Lua (Tiếng Anh): <b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b> (<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>).
manhtuyen
14-09-08, 05:21 PM
bài viết rất hay
tiện thể nói luôn cái về table của Lua nhé
mình nghĩ nó sẽ dùng đến nhiều đấy
Thanks
huongphieubat
14-09-08, 09:25 PM
Bài Viết Về Các Kiểu Trong Lua
Đây là phần giới thiệu về 8 kiểu giá trị cơ bản trong Lua: number, string, boolean, table, function, nil, userdata, thread. Mỗi phần giới thiệu 1 kiểu khác nhau.
Chúng ta sẽ sử dụng hàm print() để xuất ra các giá trị hoặc các tính toán trên các giá trị đó. Dấu ngoặc () quanh các trị số rất quan trọng, nếu thiếu sẽ gây ra lỗi.
> print(2) -- xuất ra số 2.
2
> print("hello") -- xuất ra chuỗi hello.
hello
Các số (numbers)
Lua cho phép các phép tính đơn giản trên các số thông qua việc sử dụng các toán tử thông dụng để cộng, trừ, nhân và chia.
> print(2+2)
4
>print(2-7)
-5
> print(7*8)
56
> print(7/8)
0.875
Chú ý rằng các số không được làm tròn thành số nguyên, đó là các số thực. Chúng ta có thể gán các giá trị cho các biến nhờ dùng toán tử =.
> x = 7
> print(x)
7
Biến x được tạo khi được gán số 7. Dùng hàm print() để xuất giá trị của x. Giờ chúng ta có thể sử dụng giá trị trong x cho các tính toán khác.
> x = x * 9
> print(x)
63
> print(x*2) –- sẽ không thay đổi giá trị của x
126
> print(x)
63
Chú ý cách mà print(x*2) không thay đổi giá trị của x vì x không được gán qua toán tử = trong khi x = x * 9 là nhân giá trị hiện tại của x (là 7) cho 9 và lưu giá trị mới vào x 1 lần nữa.
Để biết thêm thông tin về kiểu số trong Lua, hãy đón xem các bài viết sau.
Các chuỗi (Strings)
Lua cũng sử dụng các kiểu chuỗi (ví dụ text):
> print("hello")
hello
Chúng ta có thể gán các chuỗi cho các biến giống như cách làm với các số:
> who = "Lua user"
> print(who)
Lua user
Chúng ta có thề nối các chuỗi lại với nhau qua toán tử .. giữa 2 chuỗi.
> print("hello ")
hello
> print("hello " .. who) – biến “who” được gán ở trên
hello
Lua user
> print(who)
Lua user
Chú ý rằng toán tử .. không thay đổi giá trị của mẩu tin nếu không sử dụng toán tử = (cũng như các số).
> message = "hello " .. who
> print(message)
hello Lua user
Không như 1 số ngôn ngữ khác, bạn không thể sử dụng toán tử cộng để nối các chuỗi. Ví dụ như lỗi trong dòng lệnh dưới đây:
> message = "hello " + who
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
stdin:1: in main chunk [C]: ?
Để biết thêm thông tin về kiểu chuỗi trong Lua, hãy đón xem các bài viết sau.
Luận lý (Boolean)
Các giá trị luận lý có 1 trong 2 giá trị là true hoặc false. Nếu 1 giá trị không phải là true thì nó sẽ phải là false và ngược lại. Toán tử not có thể được đặt trước 1 giá trị luận lý để phủ định (hay đảo ngược) nó. Ví dụ not true đồng nghĩa với false.
> x = true
> print(x)
true
> print(not x)
false
> print(notfalse)
true
Các giá trị luận lý được sử dụng để thể hiện kết quả các kiểm tra logic. Các toán tử bằng == và không bằng ~= sẽ trả lại các giá trị luận lý phụ thuộc vào các giá trị được cấp.
> print(1 == 0) –- kiểm tra 2 số có bằng nhau không
false
> print(1 == 1)
true
> print(1 ~= 0) –- kiểm tra 2 số không bằng nhau hay không
true
> print(true ~= false) –- true không bằng false?
true
Để biết thêm thông tin về kiểu luận lý trong Lua, hãy đón xem các bài viết sau.
Các bảng (Tables)
Lua có 1 kiểu dữ liệu tổng thể đa dụng (general-purpose aggregate) gọi là 1 Table. Các kiểu dữ liệu tổng thể được sử dụng cho việc lưu trữ các tập hợp (như các danh sách, các mảng, các thiết đặt, các mảng liên kết). Lua là một ngôn ngữ đơn trong đó các bảng được sử dụng để thể hiện hầu hết các kiểu tổng thể khác.
Các bảng được tạo sử dụng cặp ngoặc nhọn { } . Chúng ta hãy tạo 1 bảng rỗng:
> x = {}
> print(x)
table: 0035C910
(sẽ là bình thường nếu bảng của bạn không có cùng định danh như trong ví dụ trên.)
Khi chúng ta thể hiện giá trị bảng dùng cách built trong hàm print, Lua chỉ biều diễn đó là 1 bảng và định danh cho bảng đó (ví dụ địa chỉ của nó trong bộ nhớ). Chúng ta có thể xuất ra nội dung của bảng nhưng sẽ tìm hiểu trong các bài sắp tới.
Chúng ta có thể xây dựng bảng chứa các đối tượng khác, chẳng hạn như các số và các chuỗi được mô tả trong ví dụ dưới đây
> x = { value = 123, text = "hello" }
> print(x.value)
123
> print(x.text)
hello
Chúng ta có thể xuất các giá trị thông qua cú pháp: table.item. Chúng ta cũng có thể đặt các bảng trong các bảng khác.
> y = { const={ name="Pi", value=3.1415927 }, const2={ name="light speed", value=3e8 } }
> print(y.const.name)
Pi
> print(y.const2.value)
300000000
Để biết thêm thông tin về kiểu bảng trong Lua, hãy đón xem các bài viết sau..
Các hàm (Functions)
Trong lua, các hàm được gán vào các biến, giống như số và chuỗi. Các hàm được tạo thông qua từ khóa function. Ở đây chúng ta tạo 1 hàm đơn giản để xuất ra 1 lời chào.
> function foo() print("hello") end –- khai báo hàm
> foo() –- Gọi hàm
hello
> print(foo) –- nhận giá trị của biến "foo"
function: 0035D6E8
Chú ý rằng chúng ta có thể xuất giá trị của biến foo và nó biểu diễn (như các bảng) giá trị là 1 hàm, và có định dạng cho hàm đó. Vậy, là 1 giá trị như mọi giá trị khác, chúng ta có thể gán các hàm cho các biến.
> x = function() print("hello") end
> x()
hello
> print(x)
function: 0035EA20
Khả năng để làm điều này là vì Lua có các giá trị lớp đầu tiên (first class values). Điều này có nghĩa là tất cả các giá trị được xử lý cùng cách. Đây chính là 1 đặc điểm rất hữu dụng và mạnh của Lua.
Để thêm thông tin về kiểu hàm trong Lua, hãy đón xem các bài viết sau.
Các giá trị rỗng (nil values)
nil là 1 giá trị đặc biệt chỉ ra “không giá trị” (no value). Nếu 1 biến có giá trị rỗng là nó không có giá trị gán vào, vì thế sẽ không còn tồn tại (hoặc chưa tồn tại). Bằng việc đặt 1 biến thành rỗng, bạn có thể delete biến. Ví dụ.
> x = 2.5
> print(x)
2.5
> x = nil
> print(x)
nil
Bạn cũng có thể kiểm tra 1 biến có tồn tại hay không thông qua việc kiểm tra giá trị của nó có phải nil hay không.
> print(x == nil)
true
> x = 7
> print(x == nil)
false
> print(x)
7
Dữ liệu tự tạo (Userdata)
Các giá trị dữ liệu tự tạo là các đối tượng bên ngoài Lua, như các đối tượng được thực hiện trong C. Xảy ra khi một đối tượng trong 1 thư viện C được đặt vào Lua. 1 ví dụ của 1 giá trị userdata là 1 xử lý file (file handle). 1 userdata thường được xem như 1 bảng, và bạn có thể loại bỏ phần lớn sự khác biệt nếu trừ phi đang sử dụng. Muốn tham khảo thêm phần này, đón xem các bài viết sau.
Xâu chuỗi (Thread)
1 giá trị xâu chuỗi thể hiện 1 xâu chuỗi độc lập với việc thực thi. Sẽ bàn sâu hơn trong bài sau.
Dynamic typing
Bạn có thể chú ý khi chúng ta tạo các biến trong các ví dụ trên, chúng ta đã không chỉ ra kiểu biến đang tạo. Ví dụ
a = 1
b = "hello"
c = { item1="abc" }
Trong các ngôn ngữ khác, như C, chúng ta phải chỉ ra kiểu của 1 biến khi tạo ra nó. Trong Lua, chúng ta có thể gán nhiều kiểu giá trị khác nhau cho cùng 1 biến, ví dụ
a = 1
a = "hello"
a = { item1="abc" }
Đây được gọi là dynamic typing. Có nghĩa là bạn không phải chỉ ra biến đang thuộc kiểu nào. Biến nhận dạng được kiểu thông qua giá trị, hoặc đối tượng được gán vào.
Truy vấn kiểu (Querying type)
Vì Lua là 1 ngôn ngữ nội suy, chúng ta có thể dùng hàm type() để lấy ra kiểu của 1 đối tượng cụ thể.
> x = "123" -- 1 chuỗi
> print(x, type(x)) –- cho ra giá trị của x và kiểu của nó
123 string
> x = x + 7 -- cộng 1 số vào chuỗi 1 các cưỡng bức
> print(x, type(x)) –- lại cho ra giá trị và kiểu
130 number
Dòng lệnh lua (Lua command line)
Nếu chúng ta chạy thi hành Lua không có các thông số, chúng ta sẽ nhận được mẩu tin và 1 dấu nhắc lệnh >
Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio
>
Tất cả các ví dụ trong bài được đánh tại dấu nhắc lệnh > và được copy past vào bài.
> print("hello Lua user")
hello Lua user
> print(10*10)
100
Nếu 1 dòng bắt đầu với dấu =, Lua sẽ hiểu dòng đó là 1 diễn đạt. Đây là 1 cách thay thế cho hàm print().
> = "hello Lua user"
hello Lua user
> = 10*10
100
Mục đa dòng (Multiline entry)
Chúng ta có thể gõ các dòng lệnh trên nhiều dòng. Lua sẽ thử ước chừng những gì bạn gõ trên 1 dòng và xác định xem lệnh đó có hoàn tất chưa. Nếu chưa, một dấu nhắc đôi xuất hiện >> và bạn có thể tiếp tục gõ. Ví dụ.
> print(
>> "Hello lua user"
>> )
Hello lua user
Trong ví dụ trên, print( chưa hoàn tất vì thiếu dấu ngoặc đóng ). Dòng lệnh Lua giả thiết bạn phải gõ thêm nữa nên dấu >> được hiển thị. Điều này tiếp tục cho đến khi hoàn tất statement. Nếu bạn làm 1 lỗi, kết quả sẽ sai. Như dưới đây:
> = 10 *
>> 10 +
>> 5
105
Các Chú thích (Comments)
Chỗ nào bạn thấy "--", theo sau là text, đây là các comment (bình luận, chú thích). Mọi thứ theo sau -- sẽ bị bỏ qua khi chạy chương trình.
> = 1+1 -- cái này bỏ qua
> = 1+1 no comment
stdin:1: <eof> expected near `no'
Chú thích: Dòng báo lỗi trên, bạn không được gõ comment vào! Các comment chủ yếu làm cho chương trình rõ ràng hơn.
Còn tiếp..
huongphieubat
15-09-08, 12:30 PM
Bài tiếp theo đây, cùng xem nào
Gán Giá Trị
Gán các giá trị (Assigning values)
Việc đặt giá trị của 1 biến được gọi là gán giá trị: (assignment):
> x = 1
> y = "hello"
> print(x,y)
1 hello
Đa Gán, Gán bội (Multiple assignment)
Trong Lua, chúng ta có thể tiến hành gán nhiều giá trị trong 1 phát biểu (statement). Ví dụ
> x, y = 2, "there"
> print(x,y)
2 there
Danh sách các giá trị bên phải được gán cho danh sách các biến bên trái dấu =. Chúng ta có thể gán bao nhiêu giá trị tùy thích và chúng không nhất thiết phải cùng kiểu, ví dụ
> a,b,c,d,e,f = 1,"two",3,3.14159,"foo",{ this="a table" }
> print(a,b,c,d,e,f)
1 two 3 3.14159 foo table: 0035BED8
Các giá trị bên phải của dấu = có thể là những biểu thức như i+1, nhưng những giá trị bên trái thì không thể.
Đa gán có 1 số hình thức sau:
Tính toán trước khi gán (Evaluation occurs before assignment)
Mọi biểu thức được tính toán trước, sau đó mới được gán.
> i = 7
> i, x = i+1, i
> print(i, x)
8 7
Khi Lua chạy đến dòng thứ 2, nó tính toán biểu thức i + 1 và i trước những cái khác. Sau khi tính toán, dòng thứ 2 sẽ thành i, x = 8, 7. Sau đó nó tiến hành gán giá trị từ phải qua trái. (xem phía dưới về thứ tự gán)
Hoán chuyển các giá trị (Swapping values)
Vì các giá trị được gán gần như đồng thời, nên bạn có thể sử dụng đa gán để hoán đổi các giá trị biến với nhau.
> a,b = 1,2 -- đặt giá trị ban đầu
> print(a,b)
1 2
> a,b = b,a -- hoán đổi lẫn nhau
> print(a,b)
2 1
> a,b = b,a -- và làm lần nữa
> print(a,b)
1 2
Chú ý rằng không cần đến 1 biến tạm thời (như là bold = b; b =a; a = bold;) như trong ngôn ngữ C.
Thứ tự gán (Assignment order)
Thứ tự trong đa gán là không xác định. Có nghĩa là bạn không nên cho rằng các phép gán được tiến hành từ trái qua phải; nếu cùng biến hoặc bảng tham chiếu xuất hiện 2 lần trong danh sách gán, bạn có thể sẽ ngạc nhiên về kết quả.
> a, a = 1, 2
> print(a)
1
Trong ví dụ trên, Lua đã gán từ phải qua trái, a = 2 và sau đó a =1, nhưng chúng ta không nên phụ thuộc vào dạng này trong các phiên bản tiếp theo của Lua. Nếu thứ tự gán là quan trọng thì bạn nên sử dụng các phát biểu gán riêng biệt.
Trường hợp đặc biệt, xem các phát biểu sau. Nếu i == j, 2 phát biểu này có thể làm khác nhau:
> table[i], table[j] = table[j], table[k]
> table[j], table[i] = table[k], table[j]
Nên viết thành 2 phát biểu riêng. Điều này luôn hoán chuyển 2 giá trị, qua:
> table[i], table[j] = table[j], table[i]
Kích thước danh sách không trùng khớp (Mismatched list sizes)
Nếu 1 danh sách giá trị dài hơn danh sách biến thì những giá trị dư sẽ bị bỏ qua.
> a,b,c = 1,2,3,4,5,6
> print(a,b,c)
1 2 3
Nếu 1 danh sách giá trị ngắn hơn danh sách biến, Lua sẽ gán giá trị rỗng (nil) cho các biến không có giá trị.
> a,b,c,d = 1,2
> print(a,b,c,d)
1 2 nil nil
Còn tiếp ...
Mún tóm gọn bài cho đỡ cực nhưng nghĩ lại nếu chưa bit ji mà học lướt sẽ khó hiểu, thui thì coi như tài liệu tra cứu vậy, viết kỹ chút, hy vọng anh em đọc ko mệt :big_smile:
giangleloi
15-09-08, 05:50 PM
tuyệt đấy bác,phiền bác pm yahoo em chút
huongphieubat
15-09-08, 09:05 PM
Bài viết về các số
Giới thiệu
Một số ngôn ngữ hỗ trợ 1 hoặc nhiều các kiểu số mặc định sau:
Số nguyên (Integer )
Số nguyên chính xác vô hạn (Unlimited precision integer )
Chấm động có độ chính xác đơn (Single precision floating point)
Chấm động có độ chính xác đôi (Double precision floating point)
Các số phức (Complex numbers)
Để đơn giản, Lua chỉ hỗ trợ chỉ 1 kiểu số đó là các số chấm động (floating point numbers). Mặc định là các số chấm động có độ chính xác đôi (Double precision floating point numbers – Double) nhưng Lua có thể dễ dàng biên dịch lại để hỗ trợ các số chấm động có độ chính xác đơn (single precision floating point numbers – Single) như bạn mong muốn. Nếu bạn xa lạ với các số chấm động, tui xin giải thích sơ như thế này:
Các số thực là các số có chứa phần thập phân, giữa phần thập phân và phần nguyên ngăn cách bởi dấu chấm (decimal point – US).Thuật ngữ dấu chấm động bắt nguồn từ thực tế là không có số con số cố định trước hoặc sau dấu chấm phân cách thập phân, nên dấu chấm có thể động. (do người Mỹ dùng dấu chấm phân cách thập phân nên mới gọi chấm động, người VN chắc sẽ dùng phẩy động). Nó khác với số nguyên là các số chấm cố định (fixed point numbers) do số chữ số sau dấu chấm luôn = 0.
Còn Single và Double? Khi biểu diễn các số chấm động người ta dùng số lượng bit để giữ phần thập phân, càng nhìu bit dc sử dụng thì kết quả biểu diễn càng chính xác. Double là sử dụng số bit gấp đôi so với single vì thế nên phạm vi biểu diễn rộng hơn và độ chính xác cao hơn single.
Muốn coi kỹ hơn về cái này các bạn có thể tham khảo thêm ở <b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>
Lỡ nói nói luôn, số phức (complex numbers) là phần mở rộng của số thực thu được qua việc nối một đơn vị ảo (imaginary unit) ký hiệu là i và thỏa mãn : i^2 = -1. Mọi số phức được biểu diễn dưới dạng a + bi trong đó a, b là các số thực được gọi là phần thực và i là phần ảo.
Số nguyên (Integer) thì chắc ai cũng bit rùi, là tập hợp các số tự nhiên bao gồm số 0 và phần âm của chúng. Số nguyên khi viết sẽ không có phần thập phân.
Sử dụng các số
Chúng ta có thể sử dụng dòng lệnh Lua để tính toán thông qua các biểu thức ví dụ
Lua 5.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio
> = 1
1
> = 1 + 2
3
> = 3.1415927
3.1415927
> = 5 / 6
0.83333333333333
Chúng ta có thể nhập số và thực hiện các phép tính đơn giản. Lua cũng có thể hiểu các kiểu số mũ trong các số biểu diễn dưới dạng <giá trị> * 10^ <số mũ>
> = 1.2345e6
1234500
> = 543.21E8
54321000000
> = 2.56e-4
0.000256
Chúng ta có thể gán các số cho các biến và thực hiện phép tính:
> width = 7.5
> height = 12.7
> = width * height
95.25
> depth = 2.8
> area = width * height
> volume = area * depth
> print(area, volume)
95.25 266.7
Thư viện toán học (The math library)
Lua được trang bị 1 thư viện Toán học với các hàm được cung cấp như sau:
math.abs
Trả về giá trị tuyệt đối hoặc giá trị không âm của giá trị nhận vào.
> = math.abs(-100)
100
> = math.abs(25.67)
25.67
> = math.abs(0)
0
math.acos , math.asin
Trả về nghịch đảo cos và sin của giá trị đưa vào.
> = math.acos(1)
0
> = math.acos(0)
1.5707963267949
> = math.asin(0)
0
> = math.asin(1)
1.5707963267949
math.atan , math.atan2
Trả về nghịch đảo tang. Chúng ta có thể được bằng cách cung cấp y/x sử dụng math.atan hoặc có thể truyền y và x vào math.atan2
> c, s = math.cos(0.8), math.sin(0.8)
> = math.atan(s/c)
0.8
> = math.atan2(s,c)
0.8
math.atan2 được ưa chuộng hơn, đặc biệt khi chuyển tọa độ vuông góc sang tọa độ có cực. math.atan2 sử dụng dấu của cả hai tham số để đặt kết quả vào đúng góc phần tư và cũng tạo ra các giá trị đúng khi 1 trong 2 tham số là 0 hoặc rât gần 0.
> = math.atan2(1, 0), math.atan2(-1, 0), math.atan2(0, 1), math.atan2(0, -1)
1.5707963267949 -1.5707963267949 0 3.1415926535898
math.ceil , math.floor
Trả về số nguyên lớn hơn hoặc nhỏ hơn gần nhất giá trị đưa vào.
> = math.floor(0.5)
0
> = math.ceil(0.5)
1
math.cos , math.sin , math.tan
Trả về giá trị cos, sin và tang của giá trị đưa vào dưới dạng radian.
> = math.cos(math.pi / 4)
0.70710678118655
> = math.sin(0.123)
0.12269009002432
> = math.tan(5/4)
3.0095696738628
> = math.tan(.77)
0.96966832796149
math.cosh , math.sinh , math.tanh
Trả về giá trị cos, sin và tang hyperbolic từ giá trị đưa vào.
> = math.sinh(1)
1.1752011936438
math.deg , math.rad
Chuyển từ radian sang độ và ngược lại.
> = math.deg(math.pi)
180
> = math.deg(math.pi / 2)
90
> = math.rad(180)
3.1415926535898
> = math.rad(1)
0.017453292519943
math.exp , math.log
math.exp() trả về giá trị của e mũ giá trị nhập.
math.log() trả về giá trị logarithm cơ số e của giá trị nhập vào.
> = math.exp(0)
1
> = math.exp(1)
2.718281828459
> = math.exp(27)
532048240601.8
> = math.log(532048240601)
26.999999999998
> = math.log(3)
1.0986122886681
math.log10
Trả về logarithm bậc 10 của 1 số. Số nhập vào phải dương.
> = math.log10(100)
2
> = math.log10(256)
2.4082399653118
> = math.log10(-1)
-1.#IND
math.pow , x^y
math.pow() trả về giá trị của x mũ y, tương tự với toán tử ^. math.pow(x,y) == x^y.
> = math.pow(100,0)
1
> = math.pow(7,2)
49
> = math.pow(2,8)
256
> = math.pow(3,2.7)
19.419023519771
> = 5 ^ 2
25
> = 2^8
256
math.min , math.max
Trả về giá trị nhỏ nhất hay lớn nhất từ các tham số truyền vào.
> = math.min(1,2)
1
> = math.min(1.2, 7, 3)
1.2
> = math.min(1.2, -7, 3)
-7
> = math.max(1.2, -7, 3)
3
> = math.max(1.2, 7, 3)
7
math.modf
Trả về phần nguyên và phần thập phân của số nhập vào.
> = math.modf(5)
5 0
> = math.modf(5.3)
5 0.3
> = math.modf(-5.3)
-5 -0.3
math.sqrt
Trả về giá trị căn bậc 2 của số nhập vào. Chỉ cho phép số không âm.
> = math.sqrt(100)
10
> = math.sqrt(1234)
35.128336140501
> = math.sqrt(-7)
-1.#IND
math.random , math.randomseed
math.random() tạo ra những số ngẫu nhiên. Những tham số truyền vào sẽ thay đổi giá trị xuất:
math.random() không có tham số sẽ tạo ra 1 số thực nằm trong khoảng 0 và 1.
math.random(upper) tạo ra các số nguyên lớn hơn 1.
math.random(lower, upper) tạo ra các số nguyên nằm trong khoảng giữa lower và upper.
> = math.random()
0.0012512588885159
> = math.random()
0.56358531449324
> = math.random(100)
20
> = math.random(100)
81
> = math.random(70,80)
76
> = math.random(70,80)
75
upper và lower phải là số nguyên.
Hàm math.randomseed() đặt một seed cho việc tạo số ngẫu nhiên. Các seed bằng nhau sẽ cho các chuỗi số bằng nhau.
> math.randomseed(1234)
> = math.random(), math.random(), math.random()
0.12414929654836 0.0065004425183874 0.3894466994232
> math.randomseed(1234)
> = math.random(), math.random(), math.random()
0.12414929654836 0.0065004425183874 0.3894466994232
Một seed tốt là os.time(), nhưng phải chờ 1 giây trước khi gọi hàm để thu được 1 trình từ khác! Để lấy được số ngẫu nhiên đẹp dùng:
math.randomseed( os.time() )
math.frexp , math.ldexp
Đây là những hàm chuẩn hóa. Hàm math.frexp() được sử dụng để tách giá trị số thành 1 phần nguyên chuẩn và 1 số mũ. 2 giá trị được trả về: giá trị đầu nằm trong khoảng ½ đến 1 và giá trị thứ 2 là một số mũ. Hàm math.ldexp() lấy 1 giá trị chuẩn và trả về biểu hiện chấm động. đây là giá trị được nhân cho 2 mũ số mũ.
> = math.frexp(2)
0.5 2
> = math.frexp(3)
0.75 2
> = math.frexp(128)
0.5 8
> = math.frexp(3.1415927)
0.785398175 2
> = math.ldexp(0.785,2)
3.14
> = math.ldexp(0.5,8)
128
math.huge
math.huge là 1 hằng số, biểu diễn +vô cực.
> = math.huge
inf
> = math.huge / 2
inf> = -math.huge
-inf
> = math.huge/math.huge -- indeterminate
nan
> = math.huge * 0 -- indeterminate
nan
> = 1/0
inf
> = (math.huge == math.huge)
true
> = (1/0 == math.huge)
true
Chú ý rằng một số toán tử trên math.huge trả về giá trị đặc biệt không phải là 1 số được biểu diễn là nan. Nan là 1 kiểu số, khác các kiểu số khác:
> = type(math.huge * 0)
number
math.pi
Đây là hằng số PI.
> = math.pi
3.1415926535898
Chuyển đổi (Conversion)
Bạn có thể chuyển đổi chuỗi ra số sử dụng hàm tonumber(). Nó sẽ lấy 1 tham số chuỗi và trả về 1 số.
> = tonumber("123") + 25
148
> x = tonumber("123.456e5")
> print(x)
12345600
Tính gượng ép (Coercion)
Lua sẽ tự chuyển đổi các kiểu chuỗi và số để tiến hành các tính toán. Ví dụ, nếu bạn thử áp dụng một toán tử cho 1 chuỗi, Lua sẽ cố chuyển chuỗi đó thành số trước, nếu không phép toán sẽ không thực hiện. Nếu chuỗi không thể chuyển thành số, một thông báo lỗi se xuất hiện. Sự tự động chuyển đổi kiểu dữ liệu này được gọi là gượng ép (coercion).
> = 100 + "7"
107
> = "1000" + 234
1234
> = "hello" + 234
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
stdin:1: in main chunk
[C]: ?
> = 234 + "1000"
1234
Bạn có thể thấy chỗ 1 chuỗi chuyển được thành số, tính toán thành công. Chuỗi “hello” không chuyển được thành số nên đã bị lỗi. Trong các ngôn ngữ kiểu thống kê (như C), điều này sẽ bị lỗi do bạn không thể gán 1 giá trị cho 1 biến mà không cùng kiểu. Lua làm được vì nó thuộc kiểu động.
1 ngoại lệ đáng chú ý: Các toán tử so sánh (== ~= < > <= >=) không gượng ép được các tham số của chúng. Toán tử == sẽ xem như 1 số không bằng với số đó biễu diễn dạng chuối ( hay bất kỳ kiểu biểu diễn ko phải kiểu số). Các toán tử so sánh tuần tự sẽ báo lỗi khi bạn nhập cho chúng các kiểu khác nhau.
> = 100 == "100"
false
> = 100 ~= "hello"
true
> = 100 ~= {}
true
> = 100 == tonumber("100")
true
> = 100 <= "100"
stdin:1: attempt to compare number with string
stack traceback:
stdin:1: in main chunk
[C]: ?
Vì các nguyên nhân thi hành, cần tránh sử dụng cưỡng ép tự động quá nhiều. Phải chắc chắn tất cả các số trong các tính toán nhạy cảm (đặc biệt trong các vòng lặp) có kiểu phù hợp.
Còn tiếp ...
huongphieubat
16-09-08, 01:20 PM
Bài Viết Về Chuỗi (Strings)
Các dấu ngoặc (Quotes)
Các chuỗi được xác định qua dấu nháy đơn, đôi, hoặc 2 cặp ngoặc vuông
> = "hello"
hello
> = 'hello'
hello
> = [[hello]]
hello
Tại sao có quá nhiều cách làm 1 chuỗi? Nó cho phép bạn đặt 1 trích dẫn trong những cái khác, ví dụ
> = 'hello "Lua user"'
hello "Lua user"
> = "Its [[content]] hasn't got a substring."
Its [[content]] hasn't got a substring.
> = [[Let's have more "strings" please.]]
Let's have more "strings" please.
Cặp ngoặc vuông cũng có 1 vài tính năng đặc biệt khác, sẽ bàn sau
Các trình tự ngắt (Escape sequences)
Lua cũng có các trình tự thoát giống như C.
> = "hello \"Lua user\""
hello "Lua user"
> = 'hello\nNew line\tTab'
helloNew line Tab
Các trình tự ngắt không được nhận dạng khi sử dụng cặp ngoặc vuông:
> = [[hello\nNew line\tTab]]
hello\nNew line\tTab
Ngoặc đa dòng (Multiline quotes)
2 cặp ngoặc vuông có thể sử dụng để bao các chuỗi trải trên nhiều dòng, ví dụ:
> = [[Multiple lines of text
>> can be enclosed in double square
>> brackets.]]
Multiple lines of textcan be enclosed in double squarebrackets.
Các ngoặc lồng (Nesting quotes)
2 cặp ngoặc vuông cho phép lồng vào nhau nhưng cần phải chèn thêm dấu = vào kế dấu ngoặc ngoài cùng để phân biệt chúng. Có bao nhiêu dấu = chèn vào cũng được miễn là phải đảm bảo có dấu = ở các ngoặc vuông bắt đầu và kết thúc.
> = [[one [[two]] one]] -- ko được
stdin:1: nesting of [[...]] is deprecated near '['
> = [=[one [[two]] one]=] -- ok
one [[two]] one
> = [===[one [[two]] one]===] -- ok lun
one [[two]] one
> = [=[one [ [==[ one]=] -- ok.
one [ [==[ one
Sự liên kết (Concatenation)
Các chuỗi có thể nối với nhau thông qua toán tử liên kết “..” ví dụ
> = "hello" .. " Lua user"
hello Lua user
> who = "Lua user"
> = "hello "..who
hello Lua user
Các số có thể liên kết váo các chuỗi. Trong trường hợp này, số đã bị ép thành chuỗi và sau đó được gắn vào chuỗi.
> = "Green bottles: "..10
Green bottles: 10
> = type("Green bottles: "..10)
string
Chú ý rằng việc liên kế các chuỗi lớn có thể lâu hơn việc thêm các chuỗi vào 1 mảng và truy cập sau đó. Như ví dụ sau (nhưng có thể không phải là ví dụ hay nhất cho việc tăng tốc độ ctrinh):
newtable = {}function insertmany(ttable, ...)
for var i = 1, getn(arg) do
tinsert(ttable, arg)
end
end
insertmany(newtable, 'Hello world! ', 'The first time ', 'is always ', 'the ****. ', 'Never ', ' say ', 'never ', 'again.')
for var i, getn(newtable) do
write(newtable)
end
Thư viện chuỗi (The string library)
Lua cung cấp 1 thư viện hàm rất hữu ich cho việc xử lý và thao tác trên chuỗi.
Chú ý: Trong Lua, chuỗi được đánh số bắt đầu từ 1, không phải 0 như trong C.
string.byte(s [, i [, j]])
s:byte([, i [, j]])
Trả về mã dạng số của chữ thứ i đến thứ j của chuỗi s truyền vào.
> = string.byte("ABCDE") -- không có số thứ tự, nên sẽ lấy chữ đầu
65
> = string.byte("ABCDE",1) -- bắt đầu từ 1
65
> = string.byte("ABCDE",0) -- không có chữ nào
> = string.byte("ABCDE",100) -- ngoài giới hạn nên ko có giá trị
> = string.byte("ABCDE",3,4)
67 68
> s = "ABCDE"
> = s:byte(3,4) -- có thể áp dụng trực tiếp trên biến chuỗi
67 68
string.char(i1, i2, ...)
Tạo ra chuỗi thể hiện từ các mã ký tự được truyền vào trong tham số.
> = string.char(65,66,67)
ABC
> = string.char() -- chuỗi rỗng
string.dump(function)
Trả về dạng nhị thức của hàm nhập vào, chuỗi load trên chuỗi đó sẽ trả về 1 bản sao của hàm. Hàm phải là hàm Lua không trả giá trị. (??????)
string.find(s, pattern [, init [, plain]])
s:find(pattern [, init [, plain]])
Tìm xem có chuỗi thỏa mãn pattern trong chuỗi nhập vào. Nếu tìm thấy, sẽ trả về cặp giá trị biểu diễn cho vị trí bắt đầu và kết thúc của pattern tìm dc trên chuỗi nhập vào. Nếu không sẽ trả về nil.
> = string.find("Hello Lua user", "Lua")
7 9
> = string.find("Hello Lua user", "banana")
nil
Tham số thứ 3 init biểu diễn vị trí bắt đầu tìm trên chuỗi, init có bắt đầu là 1 và có thể là số âm (sẽ đếm ngược từ cuối chuỗi trở lên).
> = string.find("Hello Lua user", "Lua", 1) -- bắt đầu từ chữ đầu tiên
7 9
> = string.find("Hello Lua user", "Lua", 8) -- "Lua" không được tìm thấy sau chữ thứ 8
nil
> = string.find("Hello Lua user", "e", -5) -- "e" đầu tiên tính từ ký tự thứ 5 từ cuối đếm lên
13 13
Tham số patern cũng có thể cho phép những tìm kiếm phức tạp hơn. Chúng ta có thể tắt những đặc tính biểu thức bình thường thông qua tham số thứ 4 plain. Plain nhận giá trị luận lý và phải được dẫn bằng init. Ví dụ
> = string.find("Hello Lua user", "%su") -- tìm 1 ký tự khoảng trắng và có chữ “u” theo sau
10 11
> = string.find("Hello Lua user", "%su", 1, true) –- bật tìm kiếm plain, ko có kết quả nào tìm thấy
nil
string.format(formatstring, e1, e2, ...)
formatstring:format(e1, e2, ...)
Tạo ra chuỗi được định dạng theo định dạng và tham số truyền vào. Nó giống với hàm printf(“format”,…) trong C. %q là để đặt dấu ngoặc kép quanh 1 giá trị của chuỗi tham số.
c, d, E, e, f, g, G, i, o, u, X, và x tất cả cần 1 số làm tham số.
q và s cần 1 chuỗi.
> = string.format("%s %q", "Hello", "Lua user!") -- chuỗi và chuỗi được đóng ngoặc
Hello "Lua user!"
> = string.format("%c%c%c", 76,117,97) -- ký tự
Lua
> = string.format("%e, %E", math.pi,math.pi) -- số mũ
3.141593e+000, 3.141593E+000
> = string.format("%f, %g", math.pi,math.pi) -- động (float) và động rút gọn (compact float)
3.141593, 3.14159
> = string.format("%d, %i, %u", -100,-100,-100) -- số nguyên có dấu, có dấu, không dấu
-100, -100, 4294967196
> = string.format("%o, %x, %X", -100,-100,-100) -- octal, hex, HEX
37777777634, ffffff9c, FFFFFF9C
string.gmatch(s, pat)
s:gmatch(pat)
Trả về 1 chuỗi thỏa pat thông qua vòng lặp. Vòng lặp sẽ tìm hết chuỗi truyền vào theo gợi ý của pat bạn truyền vào.
> for word in string.gmatch("Hello Lua user", "%a+") do
print(word) end
HelloLuauser
Về các pattern (mẫu) và vòng lặp for sẽ nói cụ thể trong các bài sau
string.gsub(s, pattern, replace [, n])
s:gsub(pattern, replace [,n])
Đây là 1 hàm rất mạnh và có thể được sử dụng theo nhiều cách. Đơn giản nó có thể thay 1 gợi ý của pattern đưa vào bằng 1 giá trị khác. 1 cặp giá trị được trả về là chuỗi được sửa đổi và số lần thay thế, tham số n có thể được sử dụng để giới hạn số lần thay thế:
> = string.gsub("Hello banana", "banana", "Lua user")
Hello Lua user 1
> = string.gsub("banana", "a", "A", 2) -- giới hạn số lần thay là 2
bAnAna 2
Như string.find(), chúng ta có thể sử dung các biểu thức thông thường để tìm trong chuỗi. Nếu sử dụng 1 capture có thể tham khảo cách thay chuỗi sử dụng cú pháp %capture_index, ví dụ
> = string.gsub("banana", "(an)", "%1-") -- bắt giữ mọi chữ "an" và thay thế
ban-an-a 2
> = string.gsub("banana", "a(n)", "a(%1)") -- đóng ngoặc quan các ký tự n nào theo sau các ký tự a
ba(n)a(n)a 2
> = string.gsub("banana", "(a)(n)", "%2%1") –- đảo ngược mọi chữ "an"
bnanaa 2
Nếu sự thay thế là 1 hàm, không phải chuỗi, tham số truyền vào hàm là mọi bắt giữ được tạo. Nếu hàm trả về 1 chuỗi thì giá trị được trả về là sự thay thế trở lại chuỗi.
> = string.gsub("Hello Lua user", "(%w+)", print) -- xuất ra mọi từ tìm thấy
HelloLuauser 3
> = string.gsub("Hello Lua user", "(%w+)", function(w) return string.len(w) end) –- trả về độ dài của từ
5 3 4 3
> = string.gsub("banana", "(a)", string.upper) -- biến tất cả các chữ “a” thành chữ hoa
bAnAnA 3
> = string.gsub("banana", "(a)(n)", function(a,b) return b..a end) –- đảo ngược mọi chữ “an”
bnanaa 2
Bắt giữ theo pattern, ta thấy hầu hết pattern bắt giữ đều là (.-), ví dụ {(.-)} nghĩa là bắt giữ mọi ký tự nằm giữa cặp ngoặc {}. 1 pattern khác đôi khi cũng gặp là (.*) nghĩa là bắt giữ mọi thứ bao gồm các dấu ngoặc được tím thấy. Xem thử 2 ví dụ sau:
> = string.gsub("The big {brown} fox jumped {over} the lazy {dog}.","{(.-)}", function(a) print(a) end )
brown over dog
> = string.gsub("The big {brown} fox jumped {over} the lazy {dog}.","{(.*)}", function(a) print(a) end )
brown} fox jumped {over} the lazy {dog
string.len(s)
s:len()
Trả vể độ dài chuỗi.
> = string.len("Lua")
3
> = string.len("")
0
> = string.len("Lua\000user") -- Chuỗi lua là 8 bit nên \000 bị loại bỏ
8
string.lower(s)
s:lower()
Chuyển chữ hoa thành chữ thường.
> = string.lower("Hello, Lua user!")
hello, lua user!
string.match (s, pattern [, init])
s:match(pattern [, init])
Tìm pattern phù hợp đầu tiên của chuỗi s, nếu có sẽ trả ra kết quả theo pattern, ngược lại sẽ là rỗng. Tham số init biểu thị vị trí bắt đầu tìm trên chuỗi s, mặc định là 1
>= string.match("foobarfooo","foo(.*)fooo") –- trả về các chữ nằm giữa foo và fooo
bar
string.rep(s, n)
s:rep(n)
Tạo ra chuỗi từ việc nối n bản sao của chuỗi truyền vào.
> = string.rep("Lua ",5)
Lua Lua Lua Lua Lua
> = string.rep("Lua\n",3)
LuaLuaLua
string.reverse(s)
s:reverse(s)
Đảo ngược chuỗi.
> = string.reverse("lua")
aul
string.sub(s, i [, j])
s:sub(i [,j])
Trả về chuỗi con của chuỗi s truyền vào. Chuỗi con được bắt đầu từ i và kết thúc tại j. Nếu không có tham số j thì chuỗi con sẽ kết thúc tại vị trí kết thúc của chuỗi truyền vào.
> = string.sub("Hello Lua user", 7) -- từ chữ thứ 7 cho đến hết chuỗi
Lua user
> = string.sub("Hello Lua user", 7, 9) -- từ chữ thứ 7 đến chữ thứ 9
Lua
> = string.sub("Hello Lua user", -8) -- chữ thứ 8 tính từ cuối đến hết
Lua user
> = string.sub("Hello Lua user", -8, 9) -- chữ thứ 8 tính từ cuối đến chữ thứ 9 tính từ đầu
Lua
> = string.sub("Hello Lua user", -8, -6) –- chữ thứ 8 tính từ cuối đến chữ thứ 6 tính từ cuối
Lua
string.upper(s)
s:upper()
Chuyển các chữ trong chuỗi s thành chữ hoa.
> = string.upper("Hello, Lua user!")
HELLO, LUA USER!
Còn tiếp ...
manhtuyen
16-09-08, 10:18 PM
bài viết hay thế này mà không ai cho lên chú ý
huongphieubat
17-09-08, 11:55 AM
Cám ơn Tuyen quá khen! Thưa các a e Jx, Hum nay bị stress nên xin phép nghỉ viết bài 1 bữa, mai lại viết tiếp. Hum nay hok dev hok học bài hok choi game lun, chỉ lượn quanh chọc mọi ng thui, lỡ nói ji bậy bạ xin đừng giận nhé!!
huongphieubat
17-09-08, 10:49 PM
Sau 1 giấc ngủ ngon, tinh thần sảng khoái. Lại tiếp tục việc học thôi. Chúng ta lại cùng nghiên cứu tiếp vấn đề hôm nay là ji đây?
Bài viết về các bảng
Tạo bảng (Creating tables)
Các bảng được ta qua các công cụ xây dựng bảng, được xác định qua các dấu ngoặc như {}. Đề định nghĩa 1 bảng rỗng, chúng ta có thể làm như sau.
> t = {} -- xây dựng 1 bảng rỗng và gán giá vào biến “t”
> print(t)
table: 0035AE18
Chú ý khi giá trị của bảng được hiển thị, chỉ có kiểu và đơn vị id của đối tượng được hiển thị. Để xuất ra nội dung của bảng, chúng ta phải làm thật rõ ràng. Chúng ta sẽ cùng học cách làm sau.
Các bảng như các mảng (Tables as arrays)
Các bảng có thể được sử dụng để giữ các mảng thông tin. Các cấu trúc bảng có thể chứa 1 danh sách các đối tượng được phân cách nhau qua dấu phẩy để tạo 1 mảng. Có thể truy cập các phần tử mảng qua việc dùng cặp ngoặc vuông, cú pháp table. Ví dụ:
> t = { 1,1,2,3,5,8,13 }
> print( t[1] )
1
> print( t[0] )
nil
> print( t[4] )
3
Chú ý rằng thứ tự liệt kê trong bảng bắt đầu tại 1, không phải 0. t[0] có giá trị nil vì không có phần tử nào tại vị trí thứ 0. Dòng t = { 1,1,2,3,5,8,13 } tương đương với:
> t = {}
> t[1]=1 t[2]=1 t[3]=2 t[4]=3 t[5]=5 t[6]=8 t[7]=13
Sử dụng các công cụ tạo bảng ít hiệu quả nhưng lại ít lỗi hơn.
Chúng ta có thể tìm ra kích thước của 1 bảng qua hàm thư viện bảng chuẩn như toán tử # (ví dụ lấy số lượng các phần tử)
> = # t
7
Chúng ta có thể gắn các phần tử mới vào mảng bảng qua hàm table.insert(table,value).
> table.insert(t,21)
> = # t
8
> = t[7], t[8]
13 21
Chúng ta cũng có thể chèn các phần tử tại 1 vị trí định trước trong danh sách. Chúng ta có thể dùng thư viện bảng để chèn các phần tử vào mảng mà không cần xáo trộn các phần tử khác xung quanh. Để làm đều này, chúng ta cung cấp 3 tham số cho hàm table.insert(table,position,value). Chúng ta cũng có thể dùng table.remove(table,position) để loại bỏ các phần tử khỏi mảng bảng.
> table.insert(t,4,99)
> = t[3], t[4], t[5]
2 99 3
> table.remove(t,4)
> = t[3], t[4], t[5]
2 3 5
Chúng ta có thể lặp qua các phần tử chứa trong mảng nhờ toán tử ipairs(). Toán tử này sẽ cung cấp khóa liệt kê next, trong sắp xếp tăng dần, mỗi lần được gọi.
> for i,v ini pairs(t) do print(i,v) end
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
Chú ý rằng chúng ta không bị giới hạn phải sử dụng 1 kiểu dữ liệu trong 1 mảng. Chúng ta vẫn có thể chèn các số, chuỗi, hàm hoặc các bảng khác, ví dụ
> t[4] = "three"
> t[6] = "eight"
> t[2] = { "apple", "pear", "banana" }
> for i,v in ipairs(t) do print(i,v) end
1 1
2 table: 0035DFE8
3 2
4 three
5 5
6 eight
7 13
8 21
Các bảng như các từ điển (Tables as dictionaries)
Các bảng cũng có thể được sử dụng để lưu trữ thông tin không được sắp xếp như các số hoặc trình tự như trong các mảng. Những kiểu lưu trữ này đôi khi được gọi là các từ điển, các mảng liên kết, các bảng hash hoặc các kiểu ánh xạ. Chúng ta sẽ sử dụng thuật ngữ từ điển trong đó 1 cặp phần tử pair có 1 khóa key và 1 giá trị value. Khóa key được sử dụng để đặt và nhận 1 giá trị liên kết với nó. Chú ý rằng như các mảng, chúng ta có thể dùng table[key] = value để chèn các phần tử vào bảng. Khóa không nhất thiết là số, nó có thể là chuỗi hoặc bất kỳ đối tượng Lua nào (ngoại trừ nil hoặc 0/0). Chúng ta hãy tạo 1 bảng với 1 vài cặp khóa – giá trị trong đó:
> t = { apple="green", orange="orange", banana="yellow" }
> for k,v in pairs(t) do print(k,v) end
apple green
orange orange
banana yellow
Chú ý rằng chúng ta phải sử dụng pairs(), thay vì ipairs() để xuất giá trị. Đó là vì các khóa key không còn là các số nữa, bên cạnh đó ipairs() chỉ lặp qua các chỉ số trong 1 bảng trong khi pairs() lặp qua các khóa key trong bảng. Chú ý, không có bảo đảm cho thứ tự các khóa sẽ lưu trong bảng khi dùng các từ điển, vì thế nên thứ tự việc lấy các khóa qua pairs() không được bảo đảm. Cảnh báo này thậm chí áp dụng cho cả phần được liệt kê của bảng hoặc cả bảng không phải dạng từ điển mà chỉ có các chỉ số dùng như các khóa key.
> t.melon = "green"
> t["strawberry"] = "red"
>for k,v in pairs(t) do print(k,v) end
melon green
strawberry red
apple green
orange orange
banana yellow
Bạn cũng có thể tham khảo table.foreach()tương tự như pairs(), với tất cả các cảnh báo. Hàm này trong tương lai có thể bị loại bỏ trong các phiên bản Lua sau này.
Dạng table.key = value là dạng rút gọn cho table["key"] = value khi khóa key là 1 chuỗi, ví dụ t.apple khả đọc hơn 1 chút so với t["apple"]. Dạng cú pháp thân thiện này làm Lua dễ đọc hơn. Trong ví dụ:
> t = { apple="green", orange="orange", banana="yellow" }
cũng giống như:
> t = { ["apple"]="green", ["orange"]="orange", ["banana"]="yellow" }
Chú ý, nếu khóa key có chứa khoảng trắng, chúng ta phải dùng dạng ["key"]=value:
> t = { ["keys can contain more than one word"] = "as a string can contain any characters" }
> t["another string"] = 99
Cấu tạo bảng trộn (Mixed table constructors)
Bạn không bị giới hạn trong việc dùng các cấu tạo bảng như danh sách được liệt kê tuần tự hay các từ điển, bạn có thể trộn cả hai lại, ví dụ,
> t = { 2,4,6, language="Lua", version="5.1" }
Ở đây chúng ta có 1 mảng các số, sau đó là một vài giá trị từ điển. Chúng ta có thề dùng các hàm bảng trong thư viện Lua để xuất ra nội dung của bảng.
> for k,v in pairs(t) do print(k,v) end
1 2
version 5.1
3 6
language Lua
2 4
> for i,v in ipairs(t) do print(i,v) end
1 2
2 4
3 6
Chú ý sự khác nhau: ipairs() chỉ xuất nội dung liệt kê dạng số theo thứ tự tăng dần, còn pairs() xuất tất cả nội dung theo thú tự không xác định. Chúng ta có thể chuyển đổi qua lại giữa 2 kiểu cấu trúc bảng
> t = { 2,4,6, language="Lua", version="5.1", 8,10,12, web="<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>" }
Do tính gượng ép số/chuỗi, hãy cẩn thận khi xuất các khóa. Ví dụ:
> t = {}; t[1] = "a"; t["1"] = "b"
> for k,v in pairs(t) do print(k,v) end
1 a
1 b
Tất nhiên, lệnh type(k) sẽ cho các thông tin khác nhau trong cả hai trường hợp.
Lưu ý về các khóa (Notes about table keys)
Lua lưu trữ tất cả các phần tử trong các bảng theo cặp khóa – giá trị (key-value[I]). Lua không phân biệt giữa các mảng và các từ điển. Tất cả các bảng Lua thực chất đều là các từ điển. Trong 1 mảng, các khóa chỉ là các số.
> t = { 3,6,9 } -- nó giống như...
> t = { [1]=3, [2]=6, [3]=9 } -- giống như...
> t = {} t[1]=3 t[2]=6 t[3]=9
Các khóa là các tham vấn (Keys are references)
Chú ý rằng các khóa là các tham vấn đến các đối tượng, vì vậy bạn phải dùng cùng tham vấn để đưa khóa tương ứng vào bảng. Bạn có thể sử dụng bất cứ đối tượng Lua nào làm 1 khóa của 1 bảng. Chúng ta có thể biểu diễn các khóa là các tham vấn đến các đối tượng qua việc dùng 1 bảng như 1 khóa:
> a = { [{1,2,3}]="yadda" } -- xây dựng bảng trong đó phần tử có 1 khóa bảng
> table.foreach(a,print) -- hiển thị nội dung bảng: cặp khóa – giá trị
table: 0035BBC8 yadda
> = a[{1,2,3}] -- hiển thị giá trị phần tử
nil
Lệnh trên không thi hành vì khi chúng ta thử lấy lại giá trị của a[{1,2,3}] chúng ta đã không xây dựng một bảng khác, ví dụ bảng mà chúng ta dùng như 1 khóa trong cấu tạo bảng không giống như bảng mà chúng ta dùng để nhận giá trị. Nếu chúng ta dùng cùng bảng trong cả 2 trường hợp thì mọi việc sẽ diễn ra suông sẻ:
> tablekey = {1,2,3} -- tạo 1 bảng với 1 biến đại diện nó
> a = { [tablekey]="yadda" } -- tạo 1 bảng dùng bảng như là 1 khóa
> table.foreach(a,print) -- hiển thị các phần tử mảng
table: 0035F2F0 yadda
> = a[tablekey] -- nhận 1 giá trị từ bảng
yadda
> print(tablekey) -- giá trị bảng cũn giống với khóa khóa ở trên
table: 0035F2F0
Các chuỗi là các tham vấn (Strings as references)
Chúng ta phải tham chiếu cùng một chuỗi khi nhận và đặt giá trị, nếu hông các khóa dạng chuỗi sẽ không hoạt động! Vì vậy bạn phải tham vấn 1 chuỗi với giá trị cùng với giá trị tham chiếu.
> t = { apple=5 }
> a = "apple"
> b = "apple"
> print(t.apple, t[a], t) -- tất cả cùng giá trị vì chỉ có 1 "apple"!
5 5 5
Gần như mọi thứ đều là khóa (Almost anything as a key)
Chúng ta có thể sử dụng gần như mọi đối tượng Lua (như ở đây là 1 hàm) làm khóa:
> t = { [function(x) print(x) end] = "foo" }
> for key,value in pairs(t) do key(value) end
foo
1 Hàm nhận 1 tham số khi in ra sẽ cho giá trị "foo". Chúng ta lặp duyệt qua bảng để thực hiện khóa key (hàm) và truyển cho nó giá trị của hàm để in ra được "foo".
Thư viện bảng (The table library)
Chú ý: Hầu hết các hàm trong thư viện bảng giả thiết rằng bảng đặ diện cho 1 mảng hoặc 1 danh sách. Đối với các hàm này, khi nói về “độ dài” của 1 bảng có nghĩa là kết quả từ toán tử độ dài bảng (như toán tử #).
table.concat(table [, sep [, i [, j]]])
Nối các phần tử của 1 bảng lại thành 1 chuỗi. Mỗi phần tử đều phải gượng ép được thành chuỗi. Có thể tạo 1 phân cách giữa các phần tử đã được nối. 1 phạm vi có thể được chỉ rõ trong bảng bắt đầu tại phần tử thứ i và kết thúc tại phần tử thứ j..
> = table.concat({ 1, 2, "three", 4, "five" })
12three4five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ")
1, 2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2)
2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2, 4)
2, three, 4
concat sẽ không làm được trên 1 bảng chứa các bảng vì không thể gượng ép được thành chuỗi.
> = table.concat({ 1,2,{} })
stdin:1: bad argument #1 to `concat' (table contains non-strings)
stack traceback: [C]: in function `concat' stdin:1: in main chunk
[C]: ?
table.foreach(table, f)
Dù không còn thông dụng trong phiên bản 5.1 nhưng nó vẫn hữu ích trong việc xuất ra 1 bảng. Bạn nên dùng toán tử pair() thay cho hàm này. Như với pair(), phương pháp table.foreach() không bảo đảm trà lại các khóa được liệt kê theo thứ tự.
Áp dụng hàm f cho các phần tử của bảng table truyền vào. Trên mỗi vòng lặp, hàm f được truyền cặp khóa – giá trị của phần tử trong bảng.
> table.foreach({1,"two",3}, print) –- xuất cặp khóa – giá trị
1 1
2 two
3 3
> table.foreach({1,"two",3,"four"}, function(k,v) print(string.rep(v,k)) end)
1
twotwo
333
fourfourfourfour
Nếu hàm f trả về một giá trị không-rỗng (non-nil), vòng lặp sẽ dừng.
> table.foreach({1,"two",3}, function(k,v) print(k,v) return k<2 and nil end)
1 1
2 two
Các bảng có thể chứa các phần tử trộn khóa – giá trị và thứ tự - giá trị. table.foreach() sẽ hiển thị tất cả các phần tử trong bảng. Để chỉ hiển thị các phần tử thứ tự - giá trị, hãy xem table.foreachi().
> t = { 1,2,"three"; pi=3.14159, banana="yellow" }
> table.foreach(t, print)
1 1
2 2
3 three
pi 3.14159
banana yellow
table.foreachi(table, f)
(Chú ý: hàm này không còn thông dụng trong Lua 5.1 nhưng nó vẫn có thể hữu dụng để xuất ra 1 bảng. Bạn nên dùng toán tử ipairs() thay thế. Như với ipairs(), phương pháp table.foreachi() bảo đảm trả về các khóa được liệt kê theo thứ tự và bỏ qua các khóa không liệt kê.)
Áp dụng hàm f cho các phần tử của bảng truyền vào. Mỗi lần lặp hàm f được truyền vào cặp thứ tự - giá trị của phần tử trong bảng, giống như table.foreach() ngoại trừ cặp truyền vào là thứ tự - giá trị chứ không phải khóa – giá trị. Nếu hàm f trả về 1 giá trị không-rỗng (non-nil) thì vòng lặp sẽ dừng.
> t = { 1,2,"three"; pi=3.14159, banana="yellow" }
> table.foreachi(t, print)
1 12 23 three
Chú ý rằng trong ví dụ chỉ các phần tử liệt kê của bảng được hiển thị.
table.sort(table [, comp])
Sắp xếp các phần tử của 1 bảng theo vị trí
> t = { 3,2,5,1,4 }
> table.sort(t)
> = table.concat(t, ", ") -- hiển thị các giá trị được sắp xếp
1, 2, 3, 4, 5
Nếu bảng có 1 kích thước cụ thể thì chỉ có vùng cụ thể được sắp xếp, ví dụ,
> t = { 3,2,5,1,4; n=3 } -- xây dựng bảng có kích thước là 3
> table.sort(t) -- sắp xếp sẽ bị giới hạn bởi kích thước
> = table.concat(t, ", ") -- chỉ nối trong giới hạn kích thước cho trước
2, 3, 5
1 hàm so sánh có thể được cung cấp vào việc sắp xếp phần tử tùy chọn. Hàm so sánh phải trả về 1 giá trị luận lý chỉ rõ tham số đầu tiên có đứng trước tham số thứ 2 trong trình tự hay không. Mặc định là dạng so sánh <. Ví dụ, các xử lý sau tương tự như khi không có hàm truyền vào:
> t = { 3,2,5,1,4 }
> table.sort(t, function(a,b) return a<b end)
> = table.concat(t, ", ")
1, 2, 3, 4, 5
Chúng ta có thể thấy nếu chúng ta đảo ngược so sánh thì thứ tự trình tự cũng bị đảo ngược.
> table.sort(t, function(a,b) return a>b end)
> = table.concat(t, ", ")
5, 4, 3, 2, 1
table.insert(table, [pos,] value)
Chèn 1 giá trị được cho vào 1 bảng. Nếu 1 vị trí được cho, thì chèn giá trị vào trước phần tử hiện tại ở vị trí đó:
> t = { 1,3,"four" }> table.insert(t, 2, "two") -- chèn "two" tại vị trí trước phần tử 2
> = table.concat(t, ", ")
1, two, 3, four
Nếu không có vị trí được chỉ rõ thì chúng ta gắn giá trị vào cuối bảng:
> table.insert(t, 5) -- không có vị trí đưa vào nên gắn vào cuối
> = table.concat(t, ", ")
1, two, 3, four, 5
Khi 1 bảng có 1 phần tử được chèn vào thì cả kích thước bảng và thứ tự phần tử được cập nhật:
> t = { 1,"two",3 } -- tạo 1 bảng
> = # t -- tìm kích thước hiện tại 3
> table.foreach(t, print) -- hiển thị nội dung bảng
1 1
2 two
3 3
> table.insert(t, 1, "inserted") -- chèn 1 phần tử vào đầu
> = table.concat(t, ", ") -- xem chúng ta có ji
inserted, 1, two, 3
> = # t -- tìm kích thước
4
> table.foreach(t, print) -- thứ tự được cập nhật
1 inserted
2 1
3 two
4 3
Khi không có vị trí được chỉ rõ, phần tử được chèn vào cuối bảng theo kích thước được tính toán. Kích thước của 1 bảng có thể được chỉ rõ và không phản ánh số lượng phần tử, ví dụ,
> t = { 1,"two",3; n=10 } -- tạo 1 bảng với kích thước cho trc
> table.insert(t, "end") -- chèn mà không cho biết vị trí
> table.foreach(t, print) -- hiển thị nội dung bảng
1 1
2 two
3 3
11 end
n 11
table.remove(table [, pos])
Loại bỏ 1 phần tử khỏi bảng. Nếu 1 vị trí đưuợc chỉ rõ, phần tử tại vị trí sẽ bị loại bỏ. Các phần tử còn lại được sắp xếp lại 1 cách tuần tự và kích thước bảng được cập nhật phản ánh sự thay đổi. Phần tử bị loại bỏ được trả về qua hàm này. Ví dụ,
> t = { 1,"two",3,"four" } -- tạo 1 bảng
> = # t -- tìm kích thước
4
> table.foreach(t, print) -- Xem các phần tử
1 1
2 two
3 3
4 four
> = table.remove(t,2) -- loại bỏ phần tử số 2 và hiển thị nó
two
> table.foreach(t, print) -- hiển thị nội dung bảng được cập nhật
1 1
2 3
3 four
> = # t -- tìm kích thước
3
Nếu không có vị trí được đưa vào thì loại bỏ phần tử cuối cùng trong bảng được chỉ rõ qua kích thước bảng. Ví dụ,
> t = { 1,"two","three" }
> = # t -- tìm kích thước bảng (đã loại bỏ)
3
> table.foreach(t, print) -- hiển thị nội dung
1 1
2 two
3 three
> = table.remove(t) -- loại bỏ phần tử tại vị trí “n”
three
> table.foreach(t, print) -- hiển thị nội dung cập nhật
1 1
2 two
> = # t -- hiển thị kích thước mới
2
Nếu kích thước bảng không tương đương số lượng phần tử thì không có gì bị loại bỏ, ví dụ ,
> t = {1,2,3}
> table.setn(t,10) -- đặt kích thước
> table.foreach(t, print) -- thể hiện nội dung bảng, chú ý kích thước “n” được lưu trữ nội tại
1 1
2 2
3 3
> = # t -- tìm kích thước
10
> = table.remove(t) -- Loại bỏ phần tử cuối
nil
> = # t -- tìm kích thước cập nhật
9
> table.foreach(t, print) -- thể hiện các phần tử
1 1
2 2
3 3
Chú ý rằng table.remove chỉ làm việc với các liệt kê dạng số. Đối với các từ điển, bạn có thể chỉ cần không đặt các mục bảng với tablevariable["index"] = nil;
Complain bác Davidhuynhvan đây: bài copy vô đây tự động sửa hết tab cũng như xuống dòng rui kích thước chữ bắt tui viết ở ngoài xong mỗi lần bỏ vào đây lại phải sửa tiếp mấy cái vụ tab xuống dòng, mất thời gian quá!!! Mong bác david xem xét.
huongphieubat
19-09-08, 01:25 AM
Bài viết về các biểu thức (Expressions)
Các biều thức được ước tạo để thi hành các tính toán có thể gán các giá trị cho các biến hoặc truyền các tham số vào các hàm.
Các giá trị có thể được gán vào các biến 1 cách dễ dàng, ví dụ,
> x = 7
> print(x)
7
> = 7
7
Các biểu thức toán học (Arithmetic expressions)
Lua có các toán tử nhị phân thông dụng.
> = 2+3, 5-12, 2*7, 7/8
5 -7 14 0.875
> = 5*(2-8.3)/77.7+99.1
98.694594594595
Phủ định đơn nguyên:
> = -(-10), -(10)
10 -10
Lũy thừa:
> = 7^2, 107^0, 2^8
49 1 256
Các biểu thức tương quan (Relational expressions)
Các biểu thức tương quan được cung cấp để trả về các giá trị luận lý true hoặc false.
== bằng nhau
~= không bằng nhau
< nhỏ hơn
> lớn hơn
<= nhỏ hơn hoặc bằng
>= lớn hơn hoặc bằng
Ví dụ:
> = 1 == 1, 1 == 0
true false
> = 1 ~= 1, 1 ~= 0
false true
> = 2 < 7, 2 > 7
true false
> = 3 <= 7, 7 <= 7, 8 <= 7
true true false
> = 3 >= 7, 7 >= 7, 8 >= 7
false true true
Các biểu thức này cũng làm việc được với các chuỗi và các kiểu khác.
> = "abc" < "def"
true
> = "abc" > "def"
false
> = "abc" == "abc"
true
> = "abc" == "a".."bc"
true
Các đối tượng sẽ không bằng nhau nếu khác kiểu hay khác đối tượng tham chiếu.
> = {} == "table"
false
> = {} == {} -- 2 bảng khác nhau được tao ở đây
false
> t = {}
> t2 = t
> = t == t2 -- chúng ta đang tham chiếu cùng bảng
true
Tính gượng ép không có tác dụng ở đây, các kiểu phải được chuyển đổi phù hợp.
> = "10" == 10
false
> = tonumber("10") == 10
true
Các toán tử logic (Logical operators)
Lua cung cấp các toán tử logic and, or và not. Trong Lua cả nil và giá trị luận lý false đều biểu thị false trong biểu thức logic. Mọi thứ không phải false thì là true.
> = false==nil -- Dù chúng biểu diễn cùng 1 thứ chúng vẫn ko tương đương
false
> = true==false, true~=false
false true
> = 1==0
false
> = does_this_exist -- kiểm tra sự tồn tại của biến “does_this_exist”, không là false.
nil
not
Từ khóa not đảo ngược 1 giá trị biểu thức logic:
> = true, false, not true, not false
true false false true
> = not nil -- nil biểu thị false
true
> = not not true -- true thì không không true!
true
> = not "foo" -- mọi thứ không phải false hoặc nil là true
false
and
Toán tử nhị phân and không nhất thiết trả về 1 giá trị luận lý true hay false cho biểu thức logic x and y. Trong một số ngôn ngữ, toán tử and trả về 1 giá trị luận lý tùy thuộc vào 2 thành phần truyền vào. Lua thì khác, nó trả về tham số đầu nếu giá trị của nó là false hoặc nil và tham số thứ 2 nếu tham số đầu không phải là false hoặc nil. Vì vậy 1 mệnh đề luận lý chỉ được trả về nếu tham số thứ nhất là false hoặc tham số thứ 2 là 1 mệnh đề luận lý.
> = false and true -- trả về false vì nó là tham số thứ nhất
false
> = nil and true -- như trên
nil
> = nil and false
nil
> = nil and "hello", false and "hello"
nil false
Tất cả các biểu thức trên đều trả về tham số thứ nhất. Tất cả các biểu thức sau trả về tham số thứ 2 vì tham số thứ nhất là true.
> = true and false
false
> = true and true
true
> = 1 and "hello", "hello" and "there"
hello there
> = true and nil
nil
or
Toán tử nhị phân or cũng không nhất thiết trả về 1 giá trị luận lý. Nếu tham số thứ nhất không phải false hoặc nil thì nó được trả về, ngược lại tham số thứ 2 được trả về. Vì vậy, 1 mệnh đề luận lý chỉ được trả về nếu tham số thứ nhất là true hoặc tham số thứ 2 là 1 mệnh đề luận lý.
> = true or false
true
> = true or nil
true
> = "hello" or "there", 1 or 0
hello 1
Tất cả các biểu thức trên đều trả về tham số thứ nhất. Tất cả các biểu thức sau sẽ trả về tham số thứ 2 do tham số thứ nhất là false hoặc nil.
> = false or true
true
> = nil or true
true
> = nil or "hello"
hello
Đây là 1 thuộc tính rất hữu ích. Ví dụ, đặt giá trị mặc định trong 1 hàm:
> function foo(x)
>> local value = x or "default" -- Nếu tham số x là false hoặc nil, giá trị trở thành "default"
>> print(value, x)
>> end
>> foo() -- không tham số nên x là nil
default nil
> foo(1)
1 1
> foo(true)
true true
> foo("hello")
hello hello
Những toán tử tam phân (Ternary operators)
Các toán tử tam phân là những toán tử nhận vào 3 tham số là 1 đặc tính hữu ích trong C thường có dạng "điều kiện ? biểu thức1 : biểu thức2" và trả về biểu thức1 nếu điều kiện đúng ngược lại trả về biểu thức2. Nó giống với If điều kiện then bt1 else bt2. Ví dụ
int value = x>3 ? 1 : 0;
Dạng này trong Lua cũng có thể biểu diễn qua 2 toán tử and và or. Dạng trong C:
value = test ? x : y;
được chuyển sang Lua:
value = test and x or y
Ví dụ.
> print( 3>1 and 1 or 0 )
1
> print( 3<1 and 1 or 0 )
0
> print( 3<1 and "True" or "False" )
False
> print( 3>1 and true or "false" )
true
Tuy nhiên, có 1 cảnh báo: Điều này chỉ hoạt động khi phần đầu trả về giá trị không phải nil hay false.
> print( 3>1 and 1 or "False" ) -- hoạt động
1
> print( 3>1 andfalseor"oops" ) -- sai, đáng lý trả về false
oops
> print( 3>1 andnilor"oops" ) -- sai, đáng lý trả về nil
oops
Chú ý về các biểu thức kiểm tra và nil
1 chú ý quan trọng là trong Lua, giá trị 0 không phải là 1 điều kiện kiểm tra false. Trong 1 số ngôn ngữ như C, 1 kiểm tra:
if (0) printf("true"); else printf("false");
sẽ hiển thị "false". Trong Lua,
> if 0 then
>> print("true")
>> else
>> print("false")
>> end
true
xuất ra "true"! Bạn nên dùng false, hay nil thay cho 0:
> if false then print("true") else print("false") end
false
> if nil then print("true") else print("false") end
false
Tại sao?
Lý do cho điều này là lịch sử. Lua đã không hỗ trợ kiểu luận lý (như true và false) trước version 5.0. Trước version 5.0, 1 giá trị của nil được biểu thị là false. Bây giờ, cả nil và false sẽ hoạt động như 1 điều kiện sai trong biểu thức kiểm tra. Ví dụ,
> if nil then print("true") else print("false") end
false
> if 1 then print("true") else print("false") end
true
> if 0 then print("true") else print("false") end
true
> if 1==2 then print("true") else print("false") end
false
1 chú ý khác là true và flse không phải giá trị số như 1 và 0 trong 1 số ngôn ngữ.
> = true, false
true false
> = 1 + true
stdin:1: attempt to perform arithmetic on a boolean valuestack
traceback: stdin:1: in main chunk
[C]: ?
và như thế, nil cũng bị ép thành 1 giá trị luận lý khi được sử dụng với 1 toán tử logic:
> = not nil
true
> = not 1
false
> = not 0
false
Còn tiếp ...
thuyvyetm
19-09-08, 08:45 AM
hix nhìu quá! đọc đui mắt lun, anh cho em Yh đi, giảng cho e cái, đọc ko hỉu
tinhlagi_true
19-09-08, 10:14 AM
hay nhỉ, chắc ông dịch cực lắm, tui từng đọc bài Tiếng Anh quá chaj lun! nản. h có bài TV rùi thanks nhìu!
huongphieubat
19-09-08, 11:51 AM
hix nhìu quá! đọc đui mắt lun, anh cho em Yh đi, giảng cho e cái, đọc ko hỉu
Hix cái này giảng hiểu phải nhờ khả năng truyền đạt nữa, tui dở cái này lắm, và cũng chưa chắc tui đã hiểu hết những ji đã viết. Bạn cứ dùng ctrinh chạy thử thì sẽ từ từ hiểu, chúc thành công!!
hay nhỉ, chắc ông dịch cực lắm, tui từng đọc bài Tiếng Anh quá chaj lun! nản. h có bài TV rùi thanks nhìu!
Cũng ko quá cực, nói chung để cùng nhau học thui, chẳng có ji đáng nói lắm. Vì tui thấy trên mạng gần như ko có tài liệu Lua TV đầy đủ nên post lên cho những ai dev game có thể tham khảo thêm. Dẫu sao cũng cám ơn bạn
GooglePro
19-09-08, 07:54 PM
bài viết rất hay, rất có ý nghĩa, ngôn ngữ thần về bên C,C++ :D
huongphieubat
19-09-08, 10:10 PM
Bài viết về các hàm (Functions)
Xác định hàm (Defining functions)
Các hàm trong Lua được xác định với từ khóa function như sau:
function tên hàm ( các tham số ) phần thân end
Ví dụ sau cho thấy 1 đơn giản được gọi là "foo" nhận 1 tham số và trả về 2 lần giá trị của nó:
> function foo(n) return n*2 end
> = foo(7)
14
Các hàm là các giá trị (Functions are values)
Cấu trúc tương đương cấu trúc sau:
Tên hàm= function( các tham số) phần thân end
Vì thế nên hàm trên được viết lại như sau:
> foo = function(n) return n*2 end
> = foo(4)
8
Cú pháp này cho thấy rõ nhất bản chất thực của các hàm trong Lua. function(n) return n*2 end bản thân nó là 1 biểu thức mà khi thực hiện sẽ ước tính ra 1 giá trị (ở đây là 1 hàm). Chỉ riêng đều này đã đủ tạo thành 1 hàm. Phát biểu này sẽ gán hàm vào biến foo. Tuy nhiên, trước khi hàm được gán vào foo, hàm không có tên, nó là 1 hàm vô danh, dù nó vẫn là 1 hàm sử dụng được, nhưng khi được gán vào biến foo, hàm lấy tên foo and và dùng làm tên của nó.
Đôi khi không cần đặt tên khi dùng hàm. Ví dụ sau tạo ra 1 hàm vô danh và gọi nó trong biểu thức:
> = 1 + (function(n) return n*2 end)(4)
9
Phải thật khéo léo khi truyền 1 hàm (thậm chí 1 hàm vô danh) trực tiếp vào 1 hàm khác, như hàm table.foreach truyền mỗi cặp khóa – giá trị trong bảng truyền vào cho hàm nhập vào:
> table.foreach({'a',2,foo}, function(key, value)
> print(key, value)
> end)
1 a
2 2
3 function: 0x687f10
Điểm quan trọng trên hết là các hàm trong Lua là các giá trị, cũng như chuỗi và số là các giá trị. Khi là các giá trị, chúng có thể được khởi tạo lúc thực hiện, lưu trữ trong các biến, truyền vào các hàm khác cũng như nhận giá trị từ hàm khác. Do các hàm trong Lua có đủ đặc tính để làm mọi thứ mà các giá trị khác có thể làm nên nó không bị đối xử như những thành phần thứ cấp (như trong C), chúng được gọi là các giá trị lớp đầu (first class values)
Các giá trị hàm là các tham chiếu (Function values are references
Khi các hàm trong Lua được truyền như các giá trị, chúng được coi như là các giá trị tham chiếu, như các bảng. Tham chiếu để chỉ ra 1 đối tượng, với 1 đơn vị định danh và thời gian hoạt động, chứa phần thân của hàm (sự thi hàn mã lệnh - code implementation). Vì thế khi 1 biến hàm được gán vào hàm khác, mã lệnh hàm bản thân nó không bị sao chép mà chỉ sao chép tham chiếu.
> foo = function(n) return n*2 end -- tạo hàm và gán vào foo
> bar = foo -- bar và foo giờ tham chiếu cùng 1 hàm
> = foo, bar
function: 0x687d20 function: 0x687d20
> = (foo == bar)
true
> =(function(n) return n*2 end)
function: 0x6870c0
> = (foo == (function(n) return n*2 end)) -- không cùng hàm
false
Các hàm được mô tả động (Functions are dynamically typed)
Các hàm cũng như các giá trị khác trong Lua được mô tả động. Điều này có nhĩa là chúng ta tìm ra 1 giá trị có là 1 hàm hay không chỉ khi chúng ta hỏi nó lúc thực hiện:
> x = "onion"
> = type(x) -- Kiểu của ngươi là ji?
string
> x() -- giờ thử gọi ngươi.
stdin:1: attempt to call global `x' (a string value)
stack traceback:
stdin:1: in main chunk
[C]: ?
> x = foo
> = type(x) -- Kiểu của ngươi là ji?
function
> = x(77) -- giờ thử gọi ngươi.
154
Chú ý rằng chúng ta không thể gọi đối tượng x ở trên do nó là 1 chuỗi nhưng khi chúng ta gán hàm foo vào biến x, chúng ta có thể gọi nó. Đây là sự tương phản đối với các ngôn ngữ mô tả thống kê (như C) – khi biên dịch cần phải biết biến x có phải hàm hay không và trạng thái đó không thể thay đổi lúc chạy chương trình.
Chú ý rằng kiểu của 1 hàm thường đơn thuần là "function", không cần phải thu nhặt số và các kiểu của các thông số hàm và trả về giá trị:
> = type(foo) -- kiểu?
function
Điều này khác với C, trong đó kiểu của 1 hàm chứa tham số và trả về thông tin về kiểu phải được chỉ rõ trước khi sử dụng. Trong Lua bạn không cần mô tả kiểu của các giá trị được trả về từ hàm hoặc cho các tham số truyền vào hàm! Điều này cho phép Lua xử lý các tham số hàm và các giá trị trả về một cách linh hoạt.
Nói riêng, chúng ta không có vấn đề trong việc gán các hàm với các danh sách tham số hay trả về các giá trị cho biến x vì x không có khái niệm gì về các đối tượng gán vào nó:
> x = function(a,b) return a+b, a-b end
> = x(5,6)
11 -1
> function x(a,b,c) return a..b..c end
> = x('a','b','c')
abc
Tất nhiên chúng ta phải cẩn thận đối với đặt tên biến để không bị báo lỗi khi đang biên dịch hoặc lúc chạy chương trình như trong các ngôn ngữ kiểu thống kê. Tuy nhiên, điều này rất hữu dụng cho phép chúng ta viết code linh hoạt và đơn giản.
Sự phá hủy hàm (Function destruction)
Các hàm, như các đối tượng, cũng tiêu thụ tài nguyên (bộ nhớ hệ thống). Functions, as objects, consume resources (system memory). Chúng bị phá hủy dần. Như các đối tượng khác, Lua phá hủy các hàm sau khi chúng không còn dùng đến nữa:
> = foo
function: 0x688af8
> bar = foo -- làm bar tham chiếu đến cùng 1 hàm như foo
> foo = nil -- foo không còn tham chiếu hàm nữa...
> = bar -- nhưng bar vẫn còn.
function: 0x688af8
> bar = nil -- bar cũng ko tham chiếu hàm nữa.
= bar, foo -- không còn ji tham chiếu hàm
nil nil
> foo() -- thử kéo theo hàm
stdin:1: attempt to call global `foo' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
Vì foo chỉ là 1 tham chiếu đến 1 thân của 1 hàm, chúng ta có thể gán các biến khác đến cùng giá trị. Chúng ta cũng có thể xóa tham chiếu đến foo qua việc gán nil cho nó. Điều này hiệu quả để xóa biến foo. Một khi chúng ta xóa tham chiếu từ cả foo và bar, hàm không trở thành mất liên lạc, và Lua sẽ xóa nó.
Truyền tham số (Passing arguments)
Vì Lua được mô tả động và không cần mô tả kiểu hàm, nên việc kiểm tra số và kiểu của các tham số cần thiết cho 1 hàm dường như là thừa. Các tham số hàm hình thức nhận nil làm giá trị mặc định nếu không có giá trị. Chỗ nào quá nhiều tham số được truyền vào, chúng sẽ bị bỏ qua. Không có kiểu nào được chỉ rõ cho tham số vì chúng là dạng mô tả động. Chúng ta hãy xem ví dụ sau:
> function foo(a,b,c) print(a,b,c) end
Và đây là những ji diễn ra khi chúng ta gọi nó mà không có tham số:
> foo()
nil nil nil
Chú ý rằng mỗi tham số được mặc định thành giá trị nil hay ko giá trị, và húng ta cũng ko bị báo lỗi. Còn đây là kết quả khi chúng ta truyền quá nhiều tham số:
> foo(1,2,3,4)
1 2 3
Một lần nữa, không có lỗi và tham số cuối cùng bị bỏ qua. Bởi vì Lua là mô tả động, chúng ta có thể truyền bất cứ kiểu tham số nào. Ví dụ chúng ta có thể truyền các chuỗi vào hàm.
> foo("hello")
hello nil nil
> foo("pi", 3.1415, { comment="this is a table" })
pi 3.1415 table: 002FDBE8
Các tham số biến (Variable arguments)
1 hàm có các tham số biến sẽ rất hữu ích, ví dụ hàm printf(format,...) trong C. 1 cách Lua làm điều này là đặt danh sách biến tham số vào 1 bảng mảng được gọi là arg, có thể được hàm sử dụng, ví dụ,
> function foo(...) print(arg) end
> foo("abc",3,77)
table: 002FD3B8
Trong ví dụ này, chúng ta chỉ thấy 1 bảng. Chúng ta có thể dùng table.foreach(table,function) để xuất ra các giá trị của bảng tham số biến như sau:
> function foo(...) table.foreach(arg,print) end
> foo()
n 0
Từ việc nhìn vào 1 danh sách tham số biến rỗng, dễ dàng nhận ra rằng 1 cặp bảng phụ được thêm vào để cung cấp số lượng các phần tử trong bảng, arg.n. Trong trường hợp này, số lượng tham số là 0. Hãy thử truyền vài tham số biến vào:
> foo(1,2,3)
1 1
2 2
3 3
n 3
> foo("apple",2,"banana",99,3.1415927,foo)
1 apple
2 2
3 banana
4 99
5 3.1415927
6 function: 002FB5C8
n 6
Cách khác là sử dụng ... để thay thế:
> function foo(...) print('x', select(2, ...), 'y', ...) end
> foo("apple",'a',"banana")
x a y apple a banana
Dấu ... có 1 lợi thế trong là nó ngăn hậu quả thực thi trong quá trình xây dựng arg bảng.
unpack
1 hàm hữu dụng cho các tham số biến là unpack(). Hàm này lấy 1 bảng và trả về danh sách các biến, ví dụ:
> = unpack({1,2,3})
1 2 3
Có thể sử dụng với các danh sách tham số biến như sau:
> function listargs(...)
>> return unpack(arg)
>> end
> = listargs(1,2,3)
1 2 3
> = listargs("hello", {1,2,3}, function (x) return x*x end)
hello table: 0035F0B8 function: 00357860
Nhiều giá trị cùng trả về (Multiple return values)
Lua có thể trả hơn 1 giá trị từ 1 hàm. Điều này được thực hiện qua việc trả vế 1 danh sách các giá trị cách nhau bởi dấu “,”:
> function foo(angle)
>> return math.cos(angle), math.sin(angle)
>> end
>> print( foo(1) ) -- trả về 2 giá trị...
0.54030230586814 0.8414709848079
>> c,s = foo(3.142/3) -- gán các giá trị vào các biến
> = math.atan(s/c)
1.0473333333333
> = c,s
0.49988240461137 0.86609328686923
>> function many(x)
>> return x, x*x, x*x*x, x*x*x*x, x*x*x*x*x
>> end> = many(5)
5 25 125 625 3125
> = many(0.9)
0.9 0.81 0.729 0.6561 0.59049
Hàm trên đây có thể có biến số của các giá trị trả về nếu chúng ta tạo 1 bảng chứa các giá trị và sử dụng unpack. Ví dụ.,
> function many2(x,times)
>> local t = { [0]=1 }
>> for i=1,times do t = x*t[i-1] end
>> return unpack(t)
>> end
> = many2(5,10)
5 25 125 625 3125 15625 78125 390625 1953125 9765625
> = many2(0.5,7)
0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125
Các giá trị như 1 bảng (Values as a table)
Chúng ta cũng trả về các giá trị trong 1 bảng. Để làm điều này chúng ta thêm các ngoặc nhọn quanh phần gọi hàm, thứ sẽ tạo ra 1 bảng, ví dụ:
{ function_name ( args ) }
Đây là 1 ví dụ sử dụng ví dụ hàm trước:
> = { foo(1.5) }
table: 0035E088
> t = { foo(1.5) }
> table.foreach(t,print)
1 0.070737201667703
2 0.99749498660405
Giá trị đơn (Single Value)
Nếu 1 hàm trả về nhiều giá trị cùng lúc mà ta chỉ muốn giá trị đầu tiên, chúng ta đặt 1 cặp ngoặc đơn quanh phần gọi hàm, ví dụ:
(function_name ( args ) )
Đây là 1 ví dụ:
> = (foo(1.5))
0.070737201667703
> = foo(1.5)
0.070737201667703 0.99749498660405
Điều tương tự có thể thu được khi trả về 1 bảng và lấy phần tử đầu Ví dụ,
> = ({foo(1.5)}) [1]
0.070737201667703
huongphieubat
20-09-08, 10:55 AM
Bài viết về cấu trúc điều khiển
while
Phát biểu lặp có điều kiện while có dạng:
while biểu thức do khối lệnh end
Ví dụ, 1 vòng lặp đơn giản:
> i = 3
> while i>0 do
>> print(i)
>> i = i-1
>> end
3 2 1
Chúng ta có thể thoát điều khiển của phát biểu while bằng từ khóa break. Chú ý, trong Lua, từ khóa break phải ở phát biểu cuối cùng trong 1 khối lệnh – ví dụ, từ khóa end phải theo sau, nếu không bạn sẽ gặp lỗi biên dịch.
> a,b = 0,1
> while true do -- lặp vô hạn
>> io.write(b, ", ")
>> a,b = b,a+b
>> if a>500 then break end -- thoát vòng lặp nếu điều kiện đúng - true
>> end
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, >
repeat
Phái biểu lặp có điều kiện repeat có dạng:
repeat khối lệnh until biểu thức
Ví dụ, 1 vòng lặp đơn giản:
> i = 3
> repeat
>> print(i)
>> i = i-1
>> until i==0
3 2 1
Như phát biểu while, chúng ta có thể thoát 1 vòng lặp repeat bằng 1 phát biểu break:
> i = 1
> repeat
>> print(i)
>> i = i+1
>> if i>3 then break end
>> until cows_come_home
1 2 3
cows_come_home là 1 biến không xác định. Khi chúng ta truy vấn nó, chúng ta sẽ nhận giá trị nil, nhis a variable whichư vậy đoạn code này có nghĩa là "until false", hay là mãi mãi.
for
Phát biểu lặp for có 2 dạng. Đầu tiên là lặp dạng số, ví dụ,
> for count = 1,3 do print(count) end -- lặp dạng số
1 2 3
Thứ 2 là lặp trình tự, ví dụ xuất nội dung của 1 bảng. Ở đây, for được truyền vào 1 hàm lặp là pairs(), mục đích là cung cấp giá trị cho mỗi lần lặp:
> for key,value in pairs({10, math.pi, "banana"}) do print(key, value) end
1 10
2 3.1415926535898
3 banana
Cấp số dạng số (Numeric progression)
Dạng cấp số dạng số của for có cấu trúc:
for variable = từ_biểu thức, đến_biểu thức [, bước nhảy] do khối lệnh end
Phát biểu đặt giá trị của biến vào từ_biểu thức trước khi đi vào khối lệnh for. Khối lệnh chỉ được truy cập vào nếu biến không vượt quá giá trị cuối, đến_biểu thức. Điều này bam gồm lần đầu vòng lặp được lặp qua. Mỗi lần bước nhảy được thêm vào biến. Việc chỉ rõ biểu thức bước nhảy là tùy biến (có thể có, có thể không). Nếu không chỉ rõ thì sử dụng giá trị là 1. Ví dụ,
> for i = 1,3 do print(i) end -- đếm từ 1 đến 3
1 2 3
> for i = 3,1 do print(i) end – đếm từ 3 về 1 trong bước nhảy 1
zero iterations!
> for i = 3,1, -1 do print(i) end -- đếm ngược từ 3 về 1
3 2 1
> for i=1,0,-0.25 do print(i) end – Chúng ta không bị giới hạn trong các số nguyên
1
0.75
0.5
0.25
0
Chú ý rằng biến i sẽ chỉ có giá trị trong phạm vi của vòng lặp for, ví dụ,
> print(i) -- sau đoạn code trên
nil
for i = e1,e2,e3 do myFunction(i) end tương đương đoạn code Lua sau:
do
local i, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
or 1
if not (i and limit and step) then error() end
while (step>0 and i<=limit) or (step<=0 and i>=limit) do
myFunction(i) i = i + step
end
end
Các công cụ lặp (Iterators)
Dạng lặp for thứ 2 có cấu trúc:
for biến {, biến} in danh sách biểu thức do khối lệnh end
danh sách biểu thức được ước tính 1 lần trước khi đi vào vòng lặp. Kết quả của nó là 1 hàm để lặp (hàm này đặt các giá trị cho biến ), 1 trạng thái (các giá trị có thể được đọc từ đó), và 1 giá trị đầu (từ giá trị này mà lặp tới).
pairs(table)
Lua cung cấp 1 hàm pairs() để tạo ra thông tin danh sách lặp cho chúng ta tặp qua 1 bảng. Hàm pairs() sẽ cho phép lặp qua cặp key-value. Chú ý rằng thứ tự các item được trả về không được xác định, thậm chí đối với bảng đã sắp xếp.
> for key,value in pairs(t) do print(key,value) end
3 10
1 3
4 17
2 7
pi 3.14159
banana yellow
ipairs(table)
Hàm ipairs() sẽ cho phép lặp qua cặp index-value. Thứ tự các phần tử trả về được bảo đảm và các khóa không phải số nguyên bị bỏ qua. Sử dụng cùng bảng trong ví dụ trên cho ví dụ sau:
> for index,value in ipairs(t) do print(index,value) end
1 3
2 7
3 10
4 17
Chú ý cách chỉ phần mảng của bảng được hiển thị vì chi các phần tử này mới có khóa thứ tự.
next()
Hàm next(table [,index]) giúp lặp qua 1 bảng. Khi nhận 1 bảng và 1 liệt kê thứ tự, nó trả về cặp key-value kế tiếp từ bảng, ví dụ,
> = next(t) –- thứ tự sẽ là nil, lấy từ bắt đầu
1 3
> = next(t,4)
pi 3.14159
Như với pairs(), thứ tự các item được trả về không được xác định, các khóa thứ tự có thể được trả về theo bất kỳ thứ tự nào, không chỉ là tăng dần theo dạng số. Hàm pairs() trả về 1 danh sách biểu thức chứa trong next() nên chúng ta có thể lặp qua bảng. Chúng ta có thể truyền danh sách biểu thức của bản thân mình vào phát biểu for như sau:
> for key,value in next,t,nil do print(key,value) end
1 3
2 7
3 10
4 17
pi 3.14159
banana yellow
Chúng ta truyền next,table,nil như danh sách biểu thức vào phát biểu for. Chúng ta đang nói chúng ta muốn sử dụng hàm lặp next(), trên bảng t, bắt đầu tại nil (vị trí bắt đầu). Phát biểu for tiếp tục tiến trình cho đến khi hàm next trả về nil (cuối bảng).
io.lines()
Lua cung cấp các phương thức lặp hữu ích khác như io.lines([filename]) trong thư viện io. Chúng ta có thể biểu diễn hàm này thông qua việc tạo 1 file chứa 1 vài dòng text.
> io.output(io.open("my.txt","w"))
> io.write("This is\nsome sample text\nfor Lua.")
> io.close()
Chúng ta đã tạo ra 1 file gôi là "my.txt", viết 3 dòng vào đó và đóng nó. Giờ chúng ta có thể đọc nó qua vòng lặp io.lines
> for line in io.lines("my.txt") do print(line) end
This is
some sample text
for Lua.
file:lines()
Thư viện io cung cấp cách khác để lặp qua các dòng của 1 file text.
> file = assert(io.open("my.txt", "r"))
> for line in file:lines() do print(line) end
This is
some sample text
for Lua.
> file:close()
Vậy nó khác gì với io.lines()?
Bạn phải mở và đóng file rõ ràng. 1 lợi điểm của điều này là nếu không thể mở file, bạn có thể xử lý thất bại này 1 cách nhẹ nhàng. Ở đây, assert có cùng hiệu quả như io.lines: Công cụ phiên dịch sẽ ngừng với 1 thông báo lỗi chỉ ra dòng bị lỗi, nhưng thêm nữa bạn có thể kiểm tra 1 giá trị nil của file và làm vài chuyện khác.
1 lợi điểm khác là bạn có thể bắt đầu vòng lặp từ bất cứ dòng nào:
file = assert(io.open("list.txt", "r"))
local line = file:read()
if string.sub(line, 1, 1) ~= '#' then ProcessLine(line) -- File không bắt đầu với 1 chú thích, thực hiện dòng đầu
end
-- Chúng ta cũng có thể lặp trên dòng đầu, trong khi chúng là các chú thích
-- Thi hành phần còn lại của file
for line in file:lines() do ProcessLine(line)endfile:close()
Các công cụ lặp tự tạo (Custom iterators)
Chúng ta có thể viết các công cụ lặp cho riêng mình, tương tự như next(), để lặp qua bất cứ chuỗi dữ liệu nào
if ... then ... else ... end
Phát biểu if có dạng:
if biểu thức then khối lệnh { elseif biểu thức then khối lệnh } [ else khối lệnh ] end
Ví dụ, if ... then ... end
> if 10>2 then print("bigger") end
bigger
if ... then ... else ... end
> if 1>10 then print("bigger") else print("smaller") end
smaller
if ... then ... elseif ... else ... end
> number = 3
> if number < 1 then
>> value = "smaller than one"
>> elseif number==1 then
>> value = "one"
>> elseif number==2 then
>> value = "two"
>> elseif number==3 then
>> value = "three"
>> else
>> value = "bigger than three"
>> end
> print(value)
three
manhtuyen
20-09-08, 08:22 PM
huongphieubat chăm chỉ quá
cho hỏi chút nhỉ, Lua có hàm để nhập giá trị vào từ bàn phím ko
giống như pascal có read() ấy
huongphieubat
21-09-08, 11:25 AM
huongphieubat chăm chỉ quá
cho hỏi chút nhỉ, Lua có hàm để nhập giá trị vào từ bàn phím ko
giống như pascal có read() ấy
hi siêng ji đâu, cũng là 1 cách tự học thui ^^ Cái tuyền phải là cái này ko: (io.stdin:read)
> print'enter name:'
>>name = io.stdin:read'*l'
>>print('name',name)
>>print'enter age:'
>>age = io.stdin:read'*l'
>>print('age',age)
enter name:
bill
name bill
enter age:
5
age 5
Hum nay chủ nhật nghỉ xả hơi, hok viết bài nữa ^^
À quên '*l' là format đọc dòng kế tiếp (bỏ phần cuối dòng) là dạng format mặc định. Mình có thể đọc dòng tiếp theo nếu có giá trị nhập vào. Ngoài ra còn '*a" là đọc hết, và '*n' là đọc số. Cái này liên quan đến phần input và output, tui cũng chưa coi kỹ. Đến bài đó viết lại xem sao.
manhtuyen
21-09-08, 01:08 PM
Thanks nhìu
các hàm này hình như là Lua 5, võ lâm dùng lua 4 cơ chắc không được rồi.:(
huongphieubat
21-09-08, 06:09 PM
Tui đã thử coi lại Lua 4.0 rùi ở <b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>.4 hàm này có cả trong Lua 4.0 và Lua 5.0 không thay đổi ji trong phần này. Xem thử nha tuyền^^
Nếu không được thì thử bỏ phần io. đi chỉ xài stdin:read thử xem vì io. là dạng gọi hàm cụ thể (explicit) xác định rõ nhóm io còn cách kia là ko cần io. là dạng hiểu ngầm (implicit)
huongphieubat
23-09-08, 12:43 PM
Phạm vi
Phạm vi biến (Variable scopes)
Các chương trình được hòa nhập vào các đơn vị code, như các hàm và các modules. Trong các đơn vị này chúng ta có thể tạo ra các biến để giữ các giá trị nhằm mục đích xử lý dữ liệu và làm chương trình thực hiện 1 nhiệm vụ định sẵn. Vì 1 số nguyên nhân, chúng ta có thể muốn ẩn các biến trong 1 đơn vị với những cái khác. Chúng ta cũng có thể tạo các biến tạm thời là các biến có thể bỏ đi khi chúng ta đã xong việc với chúng. Thuật ngữ “phạm vi” là mô tả vùng mà tập hợp các biến tồn tại trong đó.
Các biến mà chúng ta truy cập được gọi là thấy được (visible). Phạm vi của 1 biến là khối mã chứa trong vùng thấy được. Các phạm vi được tạo ra khi chương trình thực hiện và phá hủy khi chương trình đi vào và ra khỏi các khối. Các biến được chứa trong các khối này được tạo ra và phá hủy theo các quy tắc được mô tả sau đây. Khi chúng ta nhập 1 khối và 1 phạm vi mới là chúng ta đang nhập vào 1 phạm vi nội (inner scope). Phạm vi ngoại (Outer scopes) là thấy được từ phạm vi nội (không có chiều ngược lại).
Trong Lua, các khối code được chỉ rõ qua các các từ khóa function và do...end. Ví dụ,
> function foo() local x=1 end
> foo()
> do local y=1 end
Ví dụ trên chỉ xác định 1 hàm được gọi là foo có chứa 1 phạm vi. Chúng ta tạo ra biến x trong phạm vi hàm. Khi chúng ta thoát hàm, phạm vi kết thúc, biến x bị xóa và không còn thấy được nữa. Khối do… end chứa chức năng như thế.
Phạm vi toàn cục (Global scope)
Bất kỳ biến nào không nằm trong 1 khối xác định được xem như nằm trong phạm vi toàn cục. Mọi thứ trong phạm vi toàn cục đều có thể truy cập được bởi các phạm vi nội (inner scopes)
> g = "global"
> print(g)global
> function foo() print(g) end
> foo()
global
Trong ví dụ trên, g đang trong phạm vi toàn cục. Hàm foo cũng trong phạm vi toàn cục. Chúng ta nhập phạm vi hàm foo khi foo() được gọi. Chúng ta có thể in giá trị của g vì chúng ta có thể thấy phạm vi ngoại từ phạm vi nội foo.
Từ khóa local (The local keyword)
Chúng ta sử dụng từ khóa local để mô tả mọi biến mà chúng ta muốn giữ phạm vi cục bộ làm phạm vi xác định các biến đó.
Chú ý: Tất cả các biến được khai báo trong Lua mặc định là phạm vi toàn cục nếu không được chỉ rõ là cục bộ. Nó không giống như các cách ta thường dùng. Ví dụ trong C và nhiếu ngôn ngũ khác, các biến được xác định trong phạm vi nội được mặc định là phạm vi nội.
> a = 1 -- phạm vi toàn cục
> function foo() -- Bắt đầu của phạm vi foo
>> b = 2 -- không có từ khóa local nên là phạm vi toàn cục
>> local c = 3 -- phạm vi cục bộ (local scope)
>> end -- kết thúc phạm vi foo
> print(a,b,c) -- trước khi gọi foo
1 nil nil
> foo()
> print(a,b,c) -- sau khi foo được gọi
1 2 nil
Phạm vi cục bộ (Local scope)
Khi chúng ta tạo ra 1 khối là chúng ta đang tạo ra 1 phạm vi tồn tại cho các biến, ví dụ.
> do local seven = 7 print(seven) end
7
> print(seven)
nil
Trong ví dụ trên, do và end đã bao 1 khối chứa khai báo biến cục bộ seven. Khi chúng ta thoát phạm vi tại từ khóa end., chúng ta không còn thấy được các biến cục bộ trong pham vi. Khi xuất giá trị của seven bên ngoài phạm vi chúng ta nhận được nil. Điều này có nghĩa là “không tìm thấy biến” (variable not found). Từ khóa local được đặt trước bất cứ biến nào mà chúng ta muốn chỉ nhìn thấy trong phạm vi đó và phạm vi nội tại của nó.
Trong ví dụ dưới đây, x bắt đầu với giá trị 1. Chúng ta tạo ra 1 khối qua từ khóa do và end. Sử dụng từ khá local để chỉ rõ rằng chúng ta muốn 1 biến mới cũng gọi là x, chỉ được nhìn thấy trong khối hoặc phạm vi này.
> x = 1
> print(x)
1
> do
>> local x
>> x = 2
>> print(x)
>> end
2
> print(x)
1
Bạn có thể thấy rằng mỗi khi phạm vi do … end kết thúc, khai báo thứ 2 của x biến mất và chúng ta trả ngược lại cái cũ.
Local trong phạm vi toàn cục (local in the global scope)
Từ khóa local có thể được sử dụng trong bất cứ phạm vi nào không chỉ trong phạm vi nội và phạm vi hàm. Thậm chí phạm vi toàn cục cũng có thể trở thành 1 phạm vi nội nếu nó được sử dụng như 1 module.
Bất cứ nơi nào có thể, hãy sử dụng biến cục bộ vì nó sẽ hiệu quả hơn. Nguyên nhân là các biến cục bộ được tham chiếu qua 1 số được gán trong khi các biến toàn cục được lưu trữ trong 1 bảng được truy cập thông qua khóa (tên biến). Tìm kiếm trong bảng được thực hiện rất nhanh trong Lua nhưng vẫn không nhanh bằng tìm kiếm đăng ký cục bộ.
Nếu đoạn code sau được biên dịch, chúng ta có thể xem Lua virtual machine instructions được xuất ra.
g = "global"
local l = "local"
print(g,l)
Công cụ lệnh luac (Lua compiler) có thể được sử dụng để biên dịch code, cho ra:
main <1.lua:0,0> (8 instructions, 32 bytes at 0x671420)
0+ params, 4 slots, 0 upvalues, 1 local, 4 constants, 0 functions
1 [1] LOADK 0 -2 ; "global"
2 [1] SETGLOBAL 0 -1 ; g
3 [2] LOADK 0 -3 ; "local"
4 [3] GETGLOBAL 1 -4 ; print
5 [3] GETGLOBAL 2 -1 ; g
6 [3] MOVE 3 0
7 [3] CALL 1 3 1
8 [3] RETURN 0 1
Còn tiếp ...
huongphieubat
08-11-08, 11:02 PM
Học tiếp nà ...
<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>
Còn tiếp ...
lecongphu
16-03-09, 03:34 PM
Còn sao không pót tiếp đi bạn, hay là bạn lập thành 1 ebook share cho ae đi nhé, luôn tiện làm của hồi môn lun hj :big_smile:
giangleloi
12-04-09, 12:31 PM
sau 2 tháng học của chú:\ hiểu dc sơ sơ=))
nhoc1994
11-06-09, 07:56 PM
hjc đọc xong chả hiểu ji hết trơn 8-|
michaelanhvu
25-08-09, 10:45 AM
Giá mà học xong cái nào cũng áp dụng liền cái đó thì hay nhỉ.Đọc qua mà không xài nó thì cũng như không.Nếu học xong được 1 hàm nào đó và sử dụng nó ngay vào dev JX offline thì chẳng có ai quên đâu nhỉ.
thaihoa91
25-08-09, 07:24 PM
Đây là bài học LUA rộng ! Dựa vào các bài học của huongphieubat post thì có thể viết các Script phức tạp !
Còn trong mấy Ebook chỉ là cách viết cơ bản mà thui !
Cách viết phức tạp này đã dc vận dụng trong Server DNTmaster tức là Server Sóng gió trung nguyên (sgtn.cu.to) đã dc đem lên Online ! Server này áp dụng Script để làm droprate (tỷ lệ rơi tiền và Item) bằng hàm thông qua Script chứ ko đơn giản là dùng file NpcS.txt và các droprate.ini để chỉnh ko đâu !
aichangbiet
08-11-09, 09:51 AM
sao tôi học C++ với Java đều thấy hàm nó đơn giản hơn trong Lua vậy ! Chưa thử viết lua phát nào nhưng đọc hướng dẫn hàm cũng loạn! tên hàm dài ngoằng ko quen ^^!
cuongnc2001
26-12-09, 02:26 PM
Mình ghiền lập trình từ những năm 8x,từ đó đến nay k có thời gian và điều kiện tìm hiểu, giờ đọc được bài của pác về LUA,mình thấy rất hay và hữu ích,thanks pác 1 phát.
Những thứ này ai đã từng học qua pascal hay C thì sẽ nhanh chóng nắm bắt thui mà,phải không các pác? ;))
notfile
29-04-10, 04:01 PM
Bài viết hay thế này cho lên đi
30charrrrrrrrrrrrrrrrrrrrrrr
nttuan57
04-05-10, 11:13 AM
Thank nhìu nge pồ. đang tìm hiểu ^^!
savatage91
13-02-11, 06:15 PM
<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>
kotacdaisu
22-04-11, 10:53 AM
Bạn có tài liệu không? Up lên mình tải về xem cho dễ. Nội dung rất hay. Nếu được mình cảm ơn!
raymondle
30-06-12, 07:56 PM
Lua có thể code theo nền C# hay C++ dc hok ?
thaihoa91
30-06-12, 08:05 PM
Lua có thể code theo nền C# hay C++ dc hok ?
Ko bạn à ! LUA là ngôn ngữ cơ bản cao hơn Pascal, nhưng thấp hơn C++ và C#, LUA dùng để load trong Server để thực thi là chính !
raymondle
30-06-12, 10:21 PM
Ko bạn à ! LUA là ngôn ngữ cơ bản cao hơn Pascal, nhưng thấp hơn C++ và C#, LUA dùng để load trong Server để thực thi là chính !
Thế bạn có thể chỉ mình cách xuống dòng trong 1 line hok ? Ví dụ ở C là "\n" còn ở cái này thì sao vậy bạn ?
P/s : à làm dc roài. Thử \n phát nó new line lun :))
thaihoa91
30-06-12, 10:27 PM
Thế bạn có thể chỉ mình cách xuống dòng trong 1 line hok ? Ví dụ ở C là "\n" còn ở cái này thì sao vậy bạn ?
P/s : à làm dc roài. Thử \n phát nó new line lun :))
Nếu dùng hàm print thì có tác dụng, riêng trong code LUA về bảng Say Talk nói chuyện thì cứ ghi <enter> là câu đối thoại tự động xún dòng !
raymondle
01-07-12, 10:58 AM
Nếu dùng hàm print thì có tác dụng, riêng trong code LUA về bảng Say Talk nói chuyện thì cứ ghi <enter> là câu đối thoại tự động xún dòng !
Oh thanks bạn :D
<b><font color=red>[Chỉ có thành viên mới xem link được. <a href="register.php"> Nhấp đây để đăng ký thành viên......</a>]</font></b>
haohaoyeu
19-10-12, 07:18 AM
Sao không còn nữa vậy bạn ... Thư viện liên kết của nó ... Theo Hảo nghĩ là, nó sẽ con nhiều mà.... Bạn bận việc sao...
gakfc1993
12-01-15, 01:07 AM
Bài viết rất hay rất có ích ạ
tk anh nhìu ^^
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.