2012-07-02 28 views
5

Thay vì sử dụng danh sách dài các đối số trong định nghĩa chức năng của tôi, tôi thích để vượt qua một vài thông số cố định và một bảng 'params thêm' như thế này:LUA: Tìm kiếm phương tiện hiệu quả và không bị lỗi gán đối số mặc định

function:doit(text, params) 
end 

Điều này thật tuyệt vì nó cho phép tôi thêm các thông số mới có tên sau mà không vi phạm các cuộc gọi cũ.

Vấn đề tôi đang trải qua xảy ra khi tôi cố gắng để buộc giá trị mặc định cho một số các params:

function:doit(text, params) 
    local font  = params.font or native.systemBold 
    local fontSize = params.fontSize or 24 
    local emboss = params.emboss or true 

    -- ... 

end 

Đoạn mã trên hoạt động tốt trong mọi trường hợp, trừ trường hợp tôi đã trôi qua trong 'false' cho chạm khắc :

doit("Test text", { fontSize = 32, emboss = false }) 

Mã trên sẽ cho kết quả hiển thị là đúng khi tôi thực sự muốn sai.

Để rõ ràng, điều tôi muốn là cho giá trị không phải NIL đầu tiên được gán cho hình chữ nhật, thay vào đó tôi nhận được giá trị không sai và không phải là NIL đầu tiên.

Để chống lại vấn đề này tôi đã viết một đoạn mã nhỏ để tìm giá trị phi NIL đầu tiên trong một bảng và trả lại rằng:

function firstNotNil(...) 
    for i = 1, #arg do 
     local theArg = arg[i] 
     if(theArg ~= nil) then return theArg end 
    end 
    return nil 
end 

Sử dụng chức năng này, tôi sẽ viết lại sự phân công chạm khắc như sau:

local emboss = firstNotNil(params.emboss, true) 

Bây giờ, điều này chắc chắn hoạt động, nhưng có vẻ như không hiệu quả và trên đầu. Tôi hy vọng có một cách nhỏ gọn hơn để làm điều này.

Xin lưu ý: Tôi tìm thấy cấu trúc ruby ​​này trông đầy hứa hẹn và tôi hy vọng lua có một cái gì đó giống như nó:

[c,b,a].detect { |i| i > 0 } -- Assign first non-zero in order: c,b,a 
+0

Bạn đã xem [câu hỏi trước này] (http://stackoverflow.com/questions/6022519/define-default-values-for-function-arguments) về một chủ đề tương tự chưa? – hugomg

+0

"có vẻ như không hiệu quả" Bạn có dữ liệu lược tả thực tế để sao lưu điều này hay đây chỉ là một trong những điều ruột mà bạn không nên lo lắng? –

Trả lời

8

Lua của đánh giá giá trị của một trong các toán hạng (tức là giá trị được không bị ép buộc để boolean), do đó bạn có thể nhận được tương đương với toán tử bậc ba của C bằng cách nói a and b or c. Trong trường hợp của bạn, bạn muốn sử dụng a nếu nó không nilb khác, vì vậy a == nil and b or a:

local emboss = (params.emboss == nil) and true or params.emboss 

Không xinh đẹp như trước đây, nhưng bạn chỉ muốn cần phải làm điều đó cho thông số boolean.


[snip - Lua code]

Bây giờ, điều này chắc chắn hoạt động, nhưng nó dường như không hiệu quả và trên đầu trang.

Xin lưu ý: Tôi tìm thấy cấu trúc ruby ​​này trông đầy hứa hẹn và tôi hy vọng lua có một cái gì đó giống như nó:

[c, b, a] .detect {| i | i> 0} - Gán đầu tiên khác 0 theo thứ tự: c, b, a

Hàm Lua của bạn không vượt quá đầu hoặc không hiệu quả. Cấu trúc Ruby là nhiều hơn gọn gàng, về văn bản nguồn, nhưng ngữ nghĩa không thực sự khác với firstNotNil(c,b,a). Cả hai cấu trúc cuối cùng tạo ra một đối tượng danh sách, khởi tạo nó với một tập hợp các giá trị, chạy thông qua một hàm tìm kiếm danh sách tuyến tính.

Trong Lua bạn có thể bỏ qua việc tạo ra các đối tượng danh sách bằng cách sử dụng biểu vararg với select:

function firstNotNil(...) 
    for i = 1, select('#',...) do 
     local theArg = select(i,...) 
     if theArg ~= nil then return theArg end 
    end 
    return nil 
end 

Tôi hy vọng có một cách nhỏ gọn hơn để làm điều này.

Cách duy nhất để làm điều đó là rút ngắn tên hàm. ;)

+0

+1 cho việc sử dụng lựa chọn. Tôi thậm chí không biết về chức năng đó. –

+0

@Mud, giải pháp đầu tiên 'local emboss = (params.emboss ~ = nil) và params.emboss hoặc true' sẽ không hoạt động nếu' params.emboss' là 'false'. Giá trị 'emboss' sẽ được đặt thành' true', không phải là những gì Ed muốn. Giải pháp của @ brando sẽ hoạt động. –

+0

@PaulKulchenko, bạn nói đúng ... nó không [làm việc] (http://ideone.com/JaOWN). – user46874

4

Nếu bạn thực sự muốn làm điều đó trong một dòng duy nhất, bạn sẽ cần một cái gì đó như này cho một giá trị mặc định của đúng:

local emboss = params.emboss or (params.emboss == nil) 

đó là không phải là rất có thể đọc được, nhưng nó hoạt động. (params.emboss == nil) đánh giá là true khi params.emboss không được thiết lập (khi bạn cần một giá trị mặc định), nếu không nó sẽ sai. Vì vậy, khi params.emboss là false, câu lệnh là false, và khi nó là true, câu lệnh là true (true hoặc false = true).

Đối với một mặc định của sai, những gì bạn đã cố gắng ban đầu sẽ làm việc: nhà khai thác quan hệ

local emboss = params.emboss or false 
Các vấn đề liên quan