Extension:Scribunto/Lua reference manual/vi

Giới thiệu
Cẩm nang này cung cấp tài liệu về Lua theo cách sử dụng trong MediaWiki qua phần mở rộng Scribunto. Một số phần bắt nguồn từ cẩm nang tra cứu Lua 5.1, cẩm nang này được phát hành theo một giấy phép kiểu MIT.

Cẩm nang dẫn xuất này cũng có thể được sao chép theo các điều kiện của cùng giấy phép.

Bắt đầu
Trên một wiki chạy MediaWiki có kích hoạt Lua, hãy tạo ra trang mới có tên bắt đầu với “Module:”, thí dụ “Module:Xôi gấc”. Hãy sao chép văn bản sau vào mô đun mới:

Hãy lưu nội dung đó. Tại một trang khác (không phải mô đun), viết:

Thay thế “Xôi gấc” bằng tên gọi của mô đun. Đoạn mã này sẽ gọi hàm “hello” được xuất phát từ mô đun và sẽ được tự động thay thế bằng văn bản mà hàm  cho ra, tức “Xin chào thế giới!” trong thí dụ này.

Vì cú pháp bình thường để định rõ hàm không cho phép bỏ dấu, bạn cũng có thể sử dụng cú pháp sau để định rõ một hàm có tên tiếng Việt:

Và gọi hàm dùng đoạn mã sau:

Khuyến khích bạn gọi đến mã nguồn Lua trong bản mẫu thay vì trang nội dung, để cho các trang nội dung chỉ cần gọi bản mẫu với cú pháp bản mẫu bình thường, không cần phân biệt Lua và mã wiki. Kiểu này cũng tránh đưa cú pháp phức tạp vào không gian tên nội dung của wiki.

Tài liệu mô đun
Scribunto cho phép cung cấp tài liệu về mô đun dùng trang con trong không gian tên Module. Theo mặc định, trang con là “/tài liệu” và được hiển thị ở trên mã nguồn tại trang mô đun. Thí dụ tài liệu về “Module:Xôi gấc” được viết tại “Module:Xôi gấc/tài liệu”.

Có thể cấu hình hệ thống này dùng các thông điệp trong không gian tên MediaWiki được liệt kê ở dưới:
 * scribunto-doc-subpage-name: Đặt tên của trang con tài liệu. Các trang con với tên này được phân tích như mã wiki, thay vì mã nguồn Lua, và không gọi được dùng cú pháp . Mặc định là “tài liệu”.
 * scribunto-doc-subpage-does-not-exist: Thông điệp được hiển thị khi trang con tài liệu không tồn tại. Tên trang con được cung cấp qua tham số . Mặc định là lời giải thích đơn giản in xiên.
 * scribunto-doc-subpage-show: Thông điệp được hiển thị khi trang con tài liệu có tồn tại. Tên trang con được cung cấp qua tham số . Mặc định là nhúng trang con tài liệu.
 * scribunto-doc-subpage-header: Đầu đề được hiển thị khi xem trang con tài liệu riêng. Tên mô đun được cung cấp qua tham số . Thông điệp mặc định là lời giải thích đơn giản in đậm.

Lưu ý không thể xếp các mô đun trực tiếp vào thể loại hoặc đặt liên kết liên wiki trực tiếp vào mô đun. Tuy nhiên, bạn có thể đưa các thể loại và liên kết này vào trang con tài liệu ở trong khối thẻ, khối này chỉ hiển thị khi được tự động nhúng vào trang mô đun.

Các dấu hiệu
Tên gọi (còn được gọi định danh) trong Lua là bất cứ loạt chữ tiếng Anh, con số, và dấu gạch dưới, miễn là không bắt đầu với con số. Lua phân biệt chữ hoa/thường trong các tên gọi: “foo”, “Foo”, và “FOO” đều khác nhau.

Các từ khóa sau được bảo lưu và không được phép sử dụng làm tên gọi:  Các tên gọi bắt đầu với dấu gạch dưới và một loạt chữ hoa dẫn sau được bảo lưu để Lua dùng làm biến số toàn cầu.
 * and
 * break
 * do
 * else
 * elseif
 * end
 * false
 * for
 * function
 * if
 * in
 * local
 * nil
 * not
 * or
 * repeat
 * return
 * then
 * true
 * until
 * while

Các dấu hiệu khác là: 
 * &#x25;
 * &#x3a;
 * &#x3b;
 * ]
 * }
 * &#x3a;
 * &#x3b;
 * ]
 * }
 * &#x3a;
 * &#x3b;
 * ]
 * }
 * &#x3b;
 * ]
 * }
 * ]
 * }
 * ]
 * }
 * ]
 * }
 * }
 * }
 * }

Chú thích
Một lời chú thích bắt đầu với  ở bất cứ phần nào bên ngoài chuỗi. Nếu ngay đằng sau  có dấu ngoặc dài bên trái, lời chú thích tiếp tục cho đến dấu ngoặc dài bên phải; nếu không, lời chú thích tiếp tục cho đến cuối dòng hiện tại.

Kiểu dữ liệu
Lua là một ngôn ngữ tạo kiểu động, có nghĩa rằng các biến số và đối số hàm không có kiểu, chỉ có các giá trị được chỉ định. Mọi giá trị có kiểu.

Lua có tám kiểu dữ liệu cơ bản; trong số này chỉ có sáu được sử dụng đối với phần mở rộng Scribunto. Hàm  cho ra kiểu của một giá trị.

Hàm  chuyển đổi một giá trị thành chuỗi. Hàm  chuyển đổi một giá trị thành số nếu có thể; nếu không thì cho ra vô-giá-trị. Không có hàm đặc biệt để chuyển đổi một giá trị thành các kiểu dữ liệu kia.

Các số được tự động chuyển đổi thành chuỗi khi được sử dụng như một chuỗi, chẳng hạn khi là một toán tử của phép nối chuỗi. Các chuỗi được  chấp nhận được tự động chuyển đổi thành số khi được sử dụng làm toán tử của một phép tính số học. Ở những chỗ cần giá trị luận lý,  và   là sai, còn   và bất cứ giá trị khác là thực.

Vô-giá-trị (nil)
Kiểu dữ liệu của  là vô-giá-trị (nil). Không có thể sử dụng vô-giá-trị là một chìa khóa trong bảng, và một chìa khóa không được chỉ định là bằng với một chìa khóa được chỉ định vô-giá-trị.

Vô-giá-trị được chuyển đổi thành chuỗi là “nil”. Vô-giá-trị được chuyển đổi thành giá trị luận lý là giá trị sai.

Luận lý (boolean)
Các giá trị luận lý (giá trị Boole, boolean) là  (thực) và   (sai).

được chuyển đổi thành chuỗi là “true”, còn  là “false”. Không giống nhiều ngôn ngữ khác, Lua không cho phép chuyển đổi giá trị luận lý trực tiếp thành số. Hơn nữa, không giống nhiều ngôn ngữ, chỉ có giá trị sai và vô-giá-trị được coi là sai đối với luận lý; số 0 và chuỗi rỗng đều được coi là thực.

Chuỗi (string)
Các chuỗi Lua được coi là loạt các byte có 8 bit; ứng dụng có trách nhiệm phải giải bảng mã.

Các chuỗi trực tiếp được phân cách bằng dấu ngoặc kép đơn hoặc đúp ( hoặc  ); giống JavaScript và khác với PHP, Lua không phân biệt dấu ngoặc kép đơn với dấu ngoặc kép đúp. Các trình tự thoát sau được chấp nhận:  (chuông),   (xóa trái),   (tiếp mẫu),   (dòng mới),   (về đầu dòng),   (lập bảng ngang),   (lập bảng đứng),   (chéo ngược),   (ngoặc kép đúp), và   (ngoặc kép đơn). Để đưa dòng mới trực tiếp vào chuỗi, chèn dấu chéo ngược đằng trước dòng mới. Để định rõ ký tự theo giá trị byte, sử dụng trình tự thoát, với ddd là giá trị thập phân của byte từ 0 đến 255. Để chèn ký tự Unicode dùng các trình tự thoát, phải định rõ các byte riêng theo bảng mã UTF-8; nhập các ký tự Unicode trực tiếp đáng lẽ tiện hơn.

Có thể định rõ các chuỗi trực tiếp dài dùng khối dấu ngoặc dài. Dấu ngoặc dài bên trái có hai dấu ngoặc vuông bên trái liền nhau hoặc bất cứ số dấu bằng ở giữa hai dấu ngoặc vuông này, chẳng hạn   hoặc. Dấu ngoặc dài bên trái phải có dấu ngoặc dài bên phải tương ứng để đóng khối, chẳng hạn,  , hoặc. Trong các chuỗi sử dụng dấu ngoặc dài, các trình tự thoát không có ý nghĩa đặc biệt được miêu tả ở trên. Một dòng mới ở đầu chuỗi trực tiếp, ngay đằng sau dấu ngoặc dài bên trái, không được bao gồm trong chuỗi.

Lưu ý rằng bất cứ mọi chuỗi là thực khi chuyển đổi thành giá trị luận lý. (Điều này khác với phần nhiều ngôn ngữ kịch bản khác đánh giá chuỗi rỗng là sai.

Số (number)
Lua chỉ có một kiểu số, kiểu này được lưu giữ nội bộ theo định dạng số thực dấu phẩy động có độ chính xác kép. Theo định dạng này, các số nguyên từ &minus;9.007.199.254.740.992 đến 9.007.199.254.740.992 có thể được lưu giữ chính xác, trong khi các số cao hoặc thấp hơn chịu lỗi do làm tròn.

Các số trực tiếp có dấu chấm là dấu thập phân và không có dấu phân cách hàng ngàn, chẳng hạn   (tức 123.456,78). Có thể viết số theo ký hiệu E không có khoảng cách, chẳng hạn  (tức 1,23&times;10&minus;10),   (123,45&times;1020), hoặc   (1,23&times;105). Cũng có thể viết số nguyên theo ký hiệu thập lục phân với tiền tố, chẳng hạn   (tức 58).

Tuy NaN, dương vô cực, và âm vô cực được lưu trữ và xử lý chính xác, Lua không có cách viết trực tiếp các số lượng này. Hằng số, cũng như phép chia cho không (chẳng hạn  ), có giá trị dương vô cực, và NaN được tính dễ dàng qua phép chia.

Lưu ý rằng tất cả các số là thực khi chuyển đổi thành giá trị luận lý. Điều này khác với phần nhiều ngôn ngữ khác cho 0 là sai. Khi được chuyển đổi thành chuỗi, các số hữu hạn được trình bày dạng thập phân, có thể theo ký hiệu E. NaN được trình bày là “nan” hoặc “-nan”, và vô cực là “inf” hoặc “-inf”.

Bảng (table)
Các bảng trong Lua là mảng kết hợp (associative array), giống như mảng trong PHP và đối tượng trong JavaScript.

Các bảng được tạo bằng dấu ngoặc xoắn. Bảng rỗng là. Để đưa các giá trị vào các trường vào lúc tạo bảng, định rõ các trường trong danh sách được phân tách bằng dấu phẩy và/hoặc dấu chấm phẩy ở giữa các dấu ngoặc xoắn. Có vài cách định rõ các trường:
 * sử dụng giá trị (ban đầu) của bieuThuc1 là chìa khóa và giá trị (ban đầu) của bieuThuc2 là giá trị.
 * tương đương với
 * tương tự với, với i là một số nguyên bắt đầu từ 1 và mỗi định rõ trường kiểu này tăng lên một. Nếu đây là định rõ trường cuối cùng và biểu thức có hơn một giá trị, tất cả các giá trị được sử dụng; nếu không, chỉ có giá trị đầu tiên được giữ.

Các trường bảng được truy cập dùng cú pháp dấu ngoặc kép, chẳng hạn. Nếu một chìa khóa chuỗi cũng là tên gọi hợp lệ, có thể truy cập nó qua cú pháp dấu chấm, chẳng hạn  tương đương với. Gọi giá trị hàm của một trường bảng thì có thể sử dụng cú pháp dấu hai chấm, chẳng hạn  tương đương với.

Dãy là bảng có giá trị (không phải vô-giá-trị) cho các số nguyên dương từ 1 đến N và không có giá trị (có vô-giá-trị) cho các số nguyên dương hơn N. Nhiều hàm Lua chỉ sử dụng các dãy và bỏ qua các chìa khóa không phải số nguyên dương, chẳng hạn 0 hoặc &minus;2,5.

Tuy nhiên, khác với PHP và JavaScript, có thể sử dụng bất cứ giá trị nào, trừ vô-giá-trị và NaN, làm chìa khóa, và chìa khóa không được chuyển đổi kiểu. Các thí dụ sau đều hợp lệ và khác nhau:

Có thể sử dụng bất cứ giá trị trừ vô-giá-trị làm giá trị trong bảng. Đưa vô-giá-trị vào một trường bảng là tương đương với việc xóa chìa khóa khỏi bảng, và vô-giá-trị là kết quả truy cập một chìa khóa không được chỉ định trong bảng.

Lưu ý rằng các bảng không bao giờ được sao chép ngầm trong Lua; nếu một bảng được cho vào hàm qua tham số và hàm thay đổi những chìa khóa hoặc giá trị trong bảng, bảng gốc trong đoạn mã gọi hàm sẽ cũng được thay đổi.

Một bảng được chuyển đổi thành chuỗi thường là chuỗi “table”, nhưng có thể ghi đè kết quả này bằng cách định rõ siêu phương pháp. Ngay cả bảng rỗng là thực khi được chuyển đổi thành giá trị luận lý.

Hàm (function)
Các hàm trong Lua là giá trị hạng nhất (first-class value): có thể tạo vô danh, cho vào hàm qua tham số, chỉ định cho biến số, v.v.

Hàm được tạo dùng từ khóa  và được gọi dùng dấu ngoặc đơn. Có sẵn cú pháp đặc biệt để định rõ các hàm có tên, hàm địa phương, và hàm làm phương pháp của bảng. Xem các chi tiết trong các phần “Tuyên bố hàm” và “Gọi hàm” ở dưới.

Các hàm Lua là hàm đóng (closure), tức là nó giữ một tham chiếu đến phạm vi tuyên bố nó và có thể truy cập và thay đổi các biến số trong phạm vi đó.

Tương tự với bảng, nếu một hàm được chỉ định cho biến số khác hoặc cho vào hàm khác qua tham số, nó vẫn tương đương với “đối tượng hàm” ban đầu.

Hàm được chuyển đổi thành chuỗi là chuỗi “function”.

Các kiểu không hỗ trợ
Kiểu dữ liệu người dùng (userdata) chứa các giá trị mờ đục dành cho những phần mở rộng Lua được viết trong ngôn ngữ khác, chẳng hạn có thể sử dụng dữ liệu người dùng để chứa con trỏ hoặc cấu trúc struct C. Vì nhiều môi trường host không cho phép chạy trình biên dịch tùy biến, Scribunto không cho phép sử dụng các phần mở rộng.

Kiểu luồng (thread) đại diện cho các đặc tả thường trình phụ (coroutine handle), nhưng các thường trình phụ không hoạt động trong hộp cát của Scribunto.

Siêu bảng
Mọi bảng có thể có bảng đính kèm gọi là siêu bảng (metatable). Các trường trong siêu bảng được một số phép tính và hàm sử dụng để định rõ cách xử lý khác hoặc dự trữ cho bảng. Có thể truy cập siêu bảng của một bảng qua hàm  và đặt siêu bảng dùng hàm.

Khi truy cập siêu hàm trong trường siêu bảng, giống như thể trường siêu bảng được truy cập qua.

Các trường siêu bảng ảnh hưởng đến chính bảng là:
 * __index : Được sử dụng khi việc truy cập trường bảng dùng  sẽ cho ra vô-giá-trị. Nếu giá trị của trường này là bảng, việc truy cập được lặp lại trong bảng đó, chẳng hạn   (có thể gọi cho   của siêu bảng của bảng đó). Nếu giá trị của trường này là hàm, hàm sẽ được gọi như  . Hàm   đi vòng siêu phương pháp này.
 * __newindex : Được sử dụng khi chỉ định chìa khóa của bảng dùng  với   cho ra vô-giá-trị. Nếu giá trị của trường là bảng, việc chỉ định được lặp lại trong bảng đó, chẳng hạn   (có thể gọi cho   của siêu bảng của bảng đó). Nếu giá trị của trường là hàm, hàm sẽ được gọi như  . Hàm   đi vòng siêu phương pháp này.
 * __call : Được sử dụng khi gọi hàm trong bảng dùng cú pháp gọi hàm, tức . Giá trị phải là hàm, hàm được gọi giống như.
 * __mode : Được sử dụng để tạo bảng chứa các tham chiếu yếu. Giá trị phải là chuỗi. Theo mặc định, bất cứ giá trị được sử dụng như chìa khóa hoặc giá trị trong bảng sẽ không được dọn rác (garbage collected). Nhưng nếu siêu trường này có chữ “k”, các chìa khóa có thể được dọn rác lúc không còn tham chiếu mạnh, và nếu siêu trường này có chữ “v” thì các giá trị có thể được dọn rác. Trường cả hai trường hợp, cả chìa khóa và giá trị tương ứng đều được gỡ khỏi bảng. Lưu ý rằng cách xử lý không được định rõ nếu trường này bị thay đổi sau khi bảng này được sử dụng như siêu bảng.

Các trường siêu bảng khác bao gồm:
 * __add
 * __sub
 * __mul
 * __div
 * __mod
 * __pow
 * __unm
 * __concat
 * __eq
 * __lt
 * __le
 * __pairs
 * __ipairs
 * __metatable
 * __tostring

Lưu ý: Trong Lua, tất cả các chuỗi cũng nằm trong một siêu bảng, trong siêu bảng này  chỉ đến bảng. Siêu bảng này không truy cập được trong Scribunto, và bảng  được tham chiếu cũng không truy cập được; mô đun chỉ có thể truy cập một bản sao của bảng chuỗi.

Biến số
Biến số là đồ đựng giá trị. Lua có ba loại biến số: biến số toàn cầu, biến số địa phương, và trường bảng.

Một tên gọi đại diện cho một biến số toàn cầu hoặc địa phương (hoặc một tham số hàm, nó chỉ là một loại biến số địa phương). Biến số được cho là toàn cầu nếu không được tuyên bố rõ ràng là biến số địa phương dùng từ khóa. bất cứ biến số không được chỉ định giá trị là vô-giá-trị.

Các biến số toàn cầu được lưu trong bảng Lua chuẩn được gọi là môi trường (environment); bảng này thường có sẵn qua biến số toàn cầu. Có thể đặt một siêu bảng cho bảng biến số toàn cầu này; các siêu phương pháp  và   sẽ được gọi để truy cập hoặc chỉ đinh cho các biến số toàn cầu, không khác biệt với việc truy cập hoặc chỉ định cho trường trong bất cứ bảng khác.

Có thể truy cập môi trường của hàm qua  và thay đổi nó dùng hàm. Trong Scribunto, các hàm này bị hạn chế chặt chẽ hoặc không có sẵn.

Các biến số địa phương có phạm vi từ vựng (lexical scope); xem chi tiết trong phần “Tuyên bố biến số địa phương”.

Biểu thức
Biểu thức là gì đó có giá trị: các giá trị trực tiếp (số, chuỗi,,  ,  ), lệnh tuyên bố hàm vô danh, lệnh tạo bảng, tham chiếu biến số, lệnh gọi hàm, biểu thức tham lượng động (vararg), biểu thức để trong ngoặc đơn, phép tính đơn phân có toán tử là biểu thức, và biểu thức được phép tính nhị phân liên kết.

Phần nhiều biểu thức có một giá trị, nhưng các lệnh gọi hàm và biểu thức tham lượng động có thể có bất cứ số giá trị. Một lệnh gọi hàm hoặc biểu thức tham lượng động để trong ngoặc đơn loại bỏ các giá trị chỉ còn gia trị đầu tiên.

Danh sách biểu thức là danh sách biểu thức phân tách bởi dấu phẩy. Tất cả các biểu thức trừ biểu thức cuối cùng được thu lại thành một giá trị (bằng cách bỏ qua các giá trị còn dư hoặc sử dụng vô-giá-trị nếu biểu thức không có giá trị); các giá trị của danh sách biểu thức sẽ là tất cả các giá trị của biểu thức cuối.

Phép tính số học
Lua hỗ trợ các phép tính thông dụng: cộng, trừ, nhân, chia, mô đun, lũy thừa, và phủ định.

Nếu tất cả các toán tử là số hoặc chuỗi mà  có thể chuyển đổi thành số (không phải vô-giá-trị), các phép tính có ý nghĩa bình thường.

Nếu một toán tử là bảng có siêu phương pháp hợp lý, siêu phương pháp được gọi.

Phép tính quan hệ
Các phép tính quan hệ trong Lua là,  ,  ,  ,  , và. Kết quả của phép tính quan hệ luôn là giá trị luận lý (thực hay sai).

Phép tương đương ban đầu so sánh kiểu của các toán tử; nếu các kiểu khác nhau, kết quả là sai. Sau đó nó so sánh các giá trị: vô-giá-trị, luận lý, số, và chuỗi cũng được so sánh như vậy. Các hàm tương đương với nhau nếu các hàm chỉ đến cùng đối tượng hàm:  có giá trị sai vì hai hàm vô danh khác nhau được so sánh. Các bảng cũng được so sánh như vậy, nhưng có thể thay đổi cách đánh giá này bằng cách định rõ siêu phương pháp.

Phép bất tương đương là phép phủ định phép tương đương.

Đối với các phép tính sắp xếp, nếu cả hai toán tử đều là số hoặc cả hai đều là chuỗi, các toán tử được so sánh trực tiếp. Sau đó, các siêu phương pháp được gọi: Nếu các siêu phương phép hợp lý không được định rõ, phép tính gây lỗi.
 * gọi
 * gọi  nếu có sẵn, hoặc nếu   có sẵn thì phép tính này tương đương với
 * tương đương với
 * tương đương với

Phép tính lôgic
Các phép tính lôgic là  (và),   (hoặc), và   (phủ định). Các phép tính này đều có định nghĩa chuẩn rằng vô-giá-trị và  là sai còn bất cứ giá trị khác là thực.

Đối với, nếu toán tử bên trái là sai thì nó là kết quả và toán tử bên phải không được đánh giá; nếu toán tử bên trái là thực thì toán tử bên phải là kết quả.

Đối với, nếu toán tử bên trái là thực thì nó là kết quả và toán tử bên phải không được đánh giá; nếu toán tử bên trái là sai thì toán tử bên phải là kết quả.

Đối với, kết quả luôn là thực hay sai.

Lưu ý rằng  và   có tính đoản mạch. Thí dụ,  chỉ gọi   nếu   cho ra sau hoặc vô-giá-trị là giá trị đầu tiên.

Phép tính nối
Phép tính nối là hai dấu chấm, chẳng hạn. Nếu cả hai toán tử đều là số hoặc chuỗi, các toán tử được chuyển đổi thành chuỗi và nối liền với nhau. Nếu không và siêu phương pháp  được định rõ, siêu phương pháp này được gọi. Nếu không, phép tính gây lỗi.

Lưu ý rằng các chuỗi Lua không biến đổi và Lua không có chức năng “xây dựng chuỗi”, thành thử một vòng lặp  nhiều lần phải tạo một chuỗi mới mỗi vòng và cuối cùng dọn rác các chuỗi cũ không còn sử dụng. Nếu nhiều chuỗi cần được nối liền với nhau, có lẽ nên sử dụng  hoặc chèn tất cả các chuỗi vào dãy và nối liền dùng table.concat sau cùng để nhanh hơn.

Phép tính độ dài
Phép tính độ dài là, chẳng hạn. Nếu  là chuỗi, phép tính này có giá trị là số byte trong chuỗi. Nếu  là bảng dãy, nó có giá trị là số giá trị trong dãy.

Nếu  là bảng mà không phải là dãy,   có một giá trị N nào đó để cho   không phải vô-giá-trị và   là vô-giá-trị, dù mà có giá trị không phải vô-giá-trị ở các chỉ số cao hơn. Thí dụ:

Thứ tự ưu tiên phép tính
Thứ tự ưu tiên phép tính của Lua, từ mức cao nhất đến thấp nhất:


 * (phủ định)
 * (trừ)
 * (trừ)
 * (trừ)

Trong một mức ưu tiên, phần nhiều phép tính nhị phân kết hợp trái, chẳng hạn  được đánh giá là. Các phép lũy thừa và nối liền là kết hợp phải, chẳng hạn  được đánh giá là.