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"... 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ố.. who > pri
Trang 1LUA INTRODUCTION 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 :
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
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
Trang 2Bạ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
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: www.lua.org
Hướng dẫn người mới học http://lua-users.org/wiki/TutorialDirectory
Sổ tay Lua (Tiếng Anh): http://www.lua.org/manual/5.1/
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
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"
Trang 3Chú ý 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
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" }
Trang 4> y = { const={ name="Pi", value=3.1415927 }, const2={ name="light speed", value=3e8 } }
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ụ:
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
Đâ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
Trang 5Truy 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 paste 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:
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
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ụ
Trang 61 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
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
Để đơ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:
Trang 7Cá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 ở : http://www.webopedia.com/TERM/p/precision.html
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
> 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:
Trang 8math.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.cosh , math.sinh , math.tanh
Trả về giá trị cos, sin và tang hyperbolic từ giá trị đưa vào
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
Trang 9math.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()
0.0012512588885159
> = math.random()
Trang 10upper 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
Trang 11> = 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ố
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
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
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."
Trang 12Its [[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
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 best ', '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
Trang 13Chú ý: 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ị
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
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
= string.format("%s %q", "Hello", "Lua user!") chuỗi và chuỗi được đóng ngoặc
Hello "Lua user!"
Trang 14> = string.format("%d, %i, %u", -100,-100,-100) số nguyên có dấu, có dấu, không dấu
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
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
> = 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
Chuyển chữ hoa thành chữ thường
> = string.lower("Hello, Lua user!")
hello, lua user!
Trang 15string.match (s, pattern [, init])
Chuyển các chữ trong chuỗi s thành chữ hoa
> = string.upper("Hello, Lua user!")
HELLO, LUA USER!
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[index] Ví dụ:
Trang 161,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[2] = { "apple", "pear", "banana" }
> for i,v in ipairs(t) do print(i,v) end
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
Trang 17Chú ý 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
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", 8,10,12, web="www.lua.org" }
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) 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