2012-02-08 33 views
11

Tôi đã nhìn vào một số mã nguồn Lua, và tôi thường thấy những điều như thế này vào lúc bắt đầu của tập tin:Tại sao tạo các hàm Lua toàn cầu cục bộ?

local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc.. 

Họ chỉ làm cho các chức năng địa phương để cho Lua truy cập chúng nhanh hơn khi thường được sử dụng ?

+1

Bạn có thể muốn xem http://stackoverflow.com/questions/4643814/why-would-this-lua-optimization-hack-help –

Trả lời

12

Dữ liệu cục bộ nằm trên ngăn xếp và do đó chúng truy cập chúng nhanh hơn. Tuy nhiên, tôi nghiêm túc nghi ngờ rằng thời gian gọi hàm đến setmetatable thực sự là một vấn đề quan trọng đối với một số chương trình.

Sau đây là các cách giải thích cho việc này:

  1. Phòng ngừa từ ô nhiễm môi trường toàn cầu. Quy ước Lua hiện đại cho các mô-đun là không yêu cầu họ đăng ký trực tiếp vào bảng toàn cầu. Họ nên xây dựng một bảng chức năng địa phương và trả lại chúng. Do đó, chỉ cách cách truy cập chúng là có biến cục bộ. Điều này gây ra một số điều:

    1. Một mô-đun không thể vô tình ghi đè lên các chức năng khác của mô-đun.

    2. Nếu mô-đun vô tình thực hiện việc này, các chức năng ban đầu trong bảng được mô-đun trả về sẽ vẫn có thể truy cập được. Chỉ bằng cách sử dụng local modname = require "modname" bạn sẽ được đảm bảo để có được chính xác và chỉ những gì mà mô-đun tiếp xúc.

    3. Mô-đun bao gồm các mô-đun khác không thể can thiệp lẫn nhau. Bảng bạn lấy lại từ require luôn là những gì mà các mô-đun lưu trữ.

  2. Một sớm tối ưu hóa bởi một người đọc "local biến được truy cập nhanh hơn" và sau đó quyết định làm tất cả mọi thứ local.

Nói chung, đây là phương pháp hay. Vâng, trừ khi đó là vì # 2.

+0

3. Tắt tiếng một linter mà nghĩ rằng gọi được xây dựng trong đó như rawset hoặc ipairs là xấu. – andyn

0

tôi làm điều đó bởi vì nó cho phép tôi để xem các chức năng được sử dụng bởi mỗi mô-đun của tôi

Ngoài ra nó bảo vệ bạn khỏi những người khác thay đổi các chức năng trong môi trường toàn cầu. Đó là một sự tối ưu hóa miễn phí (sớm) là tiền thưởng.

+1

Không có gì để ngăn mô-đun của bạn sử dụng các chức năng không có trong danh sách đó. Vì vậy, nếu bạn có một nhu cầu đột ngột cho một chức năng toàn cầu và quên thêm nó vào danh sách, sau đó bạn đang sử dụng globals. Ngoài ra, nếu ai đó thay đổi các chức năng toàn cầu, thì có thể có lý do * tốt * để họ làm như vậy, chẳng hạn như theo dõi việc sử dụng các chức năng nhất định và vv. –

+0

Thực tế là có; Tôi có một móc trước khi cam kết sử dụng luac để tìm kiếm các opcodes GETGLOBAL và cảnh báo tôi. – daurnimator

+0

Đó là rất nhiều công việc để thực hiện một cái gì đó rất đơn giản. Bạn vừa sử dụng các môi trường để cung cấp một không gian toàn cục cụ thể cho từng chức năng, vì vậy chúng không thể ảnh hưởng đến người khác. Lập trình trong Lua cuốn sách cho bạn biết tất cả về làm thế nào để làm điều này. –

4

Ngoài câu trả lời Nicol Bolas, tôi muốn thêm vào điểm thứ 3:

  • Nó cho phép mã của bạn để được chạy từ bên trong một sandbox sau khi nó được nạp.

Nếu các chức năng đã bị loại trừ khỏi hộp cát và mã được tải từ bên trong hộp cát, thì mã sẽ không hoạt động. Nhưng nếu mã được nạp đầu tiên, thì sandbox có thể gọi mã được nạp và có thể loại trừ setmetatable, vv, khỏi sandbox.

0

Một lợi ích tinh tế khác: Nó nêu rõ các biến (hàm, mô-đun) được mô-đun nhập vào. Và nếu bạn đang sử dụng câu lệnh mô-đun, nó thực thi các khai báo như vậy, bởi vì môi trường toàn cầu được thay thế (vì vậy các hình cầu không có sẵn).

Các vấn đề liên quan