8.1 – The require Function(Chức năng yêu cầu)


Lua cung cấp một chức năng cấp cao hơn để tải và chạy các thư viện, được gọi là request. Về cơ bản, request thực hiện công việc tương tự như dofile, nhưng có hai điểm khác biệt quan trọng. Đầu tiên, yêu cầu tìm kiếm tệp trong một đường dẫn; thứ hai, yêu cầu kiểm soát xem một tệp đã được chạy hay chưa để tránh sao chép tác phẩm. Do các tính năng này, request là chức năng ưa thích trong Lua để tải các thư viện.

Đường dẫn được yêu cầu sử dụng hơi khác một chút so với các đường dẫn điển hình. Hầu hết các chương trình sử dụng đường dẫn như một danh sách các thư mục trong đó để tìm kiếm một tệp nhất định. Tuy nhiên, ANSI C (nền tảng trừu tượng nơi Lua chạy) không có khái niệm về thư mục. Do đó, đường dẫn được dùng bởi request là một danh sách các mẫu, mỗi mẫu chỉ định một cách thay thế để chuyển đổi tên tệp ảo (đối số để yêu cầu) thành tên tệp thực. Cụ thể hơn, mỗi thành phần trong đường dẫn là một tên tệp chứa các dấu thẩm vấn tùy chọn. Đối với mỗi thành phần, yêu cầu thay thế mỗi ‘?’ bằng tên tệp ảo và kiểm tra xem có tệp nào có tên đó không; nếu không, nó sẽ chuyển đến thành phần tiếp theo. Các thành phần trong đường dẫn được phân tách bằng dấu chấm phẩy (một ký tự hiếm khi được sử dụng cho tên tệp trong hầu hết các hệ điều hành). Ví dụ, nếu đường dẫn là

?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

thì lệnh gọi request “lili” sẽ cố gắng mở các tệp sau:

    lili
    lili.lua
    c:\windows\lili
    /usr/local/lua/lili/lili.lua

Những thứ duy nhất yêu cầu sửa lỗi là dấu chấm phẩy (làm dấu phân cách thành phần) và dấu hỏi; mọi thứ khác (chẳng hạn như dấu phân tách thư mục hoặc phần mở rộng tệp) được xác định trong đường dẫn.

Để xác định đường dẫn của nó, trước tiên yêu cầu kiểm tra biến toàn cục LUA_PATH. Nếu giá trị của LUA_PATH là một chuỗi thì chuỗi đó là đường dẫn. Nếu không, yêu cầu kiểm tra biến môi trường LUA_PATH. Cuối cùng, nếu cả hai lần kiểm tra đều không thành công, yêu cầu sử dụng một đường dẫn cố định (thường là “?;?. Lua”, mặc dù có thể dễ dàng thay đổi điều đó khi bạn biên dịch Lua).

Công việc chính khác của yêu cầu là tránh tải hai lần cùng một tệp. Với mục đích đó, nó giữ một bảng với tên của tất cả các tệp được tải. Nếu một tệp được yêu cầu đã có trong bảng, chỉ cần trả về. Bảng giữ tên ảo của các tệp được tải, không phải tên thật của chúng. Do đó, nếu bạn tải cùng một tệp với hai tên ảo khác nhau, nó sẽ được tải hai lần. Ví dụ: lệnh request “foo” theo sau là “foo.lua”, với đường dẫn như “?;?. Lua”, sẽ tải tệp foo.lua hai lần. Bạn có thể truy cập bảng điều khiển này thông qua biến toàn cục _LOADED. Sử dụng bảng này, bạn có thể kiểm tra tệp nào đã được tải; bạn cũng có thể đánh lừa yêu cầu chạy một tệp hai lần. Ví dụ: sau khi yêu cầu thành công “foo”, _LOADED [“foo”] sẽ không phải là con số không. Sau đó, nếu bạn gán nil cho _LOADED [“foo”], một yêu cầu tiếp theo là “foo” sẽ chạy lại tệp.

Một thành phần không cần phải có dấu hỏi; nó có thể là một tên tệp cố định, chẳng hạn như thành phần cuối cùng trong đường dẫn sau:

?;?.lua;/usr/local/default.lua

Trong trường hợp này, bất cứ khi nào yêu cầu không thể tìm thấy tùy chọn khác, nó sẽ chạy tệp cố định này. (Tất nhiên, chỉ có ý nghĩa khi có một thành phần cố định là thành phần cuối cùng trong một đường dẫn.) Trước khi request chạy một đoạn, nó xác định một biến toàn cục _REQUIREDNAME chứa tên ảo của tệp được yêu cầu. Chúng tôi có thể sử dụng các cơ sở này để mở rộng chức năng của request. Trong một ví dụ đặc biệt, chúng tôi có thể đặt đường dẫn thành một cái gì đó như “/usr/local/lua/newrequire.lua”, để mọi lệnh gọi yêu cầu chạy newrequire.lua, sau đó có thể sử dụng giá trị của _REQUIREDNAME để thực sự tải yêu cầu tập tin.

Leave a comment