Xác định giá trị mặc định cho các đối số của hàm


86

Trong wiki Lua, tôi đã tìm thấy một cách để xác định các giá trị mặc định cho các đối số bị thiếu:

function myfunction(a,b,c)
    b = b or 7
    c = c or 5
    print (a,b,c)
end

Có phải đó là cách duy nhất? Kiểu PHP myfunction (a,b=7,c=5)dường như không hoạt động. Không phải là cách Lua không hiệu quả, tôi chỉ tự hỏi liệu đây có phải là cách duy nhất để làm điều đó hay không.

Câu trả lời:


86

Nếu bạn muốn các đối số được đặt tên và giá trị mặc định như PHP hoặc Python, bạn có thể gọi hàm của mình bằng một phương thức khởi tạo bảng:

myfunction{a,b=3,c=2}

(Điều này được thấy ở nhiều nơi trong Lua, chẳng hạn như các dạng nâng cao của mô-đun giao thức và trình xây dựng của LuaSocket trong IUPLua .)

Bản thân hàm có thể có một chữ ký như sau:

function myfunction(t)
    setmetatable(t,{__index={b=7, c=5}})
    local a, b, c =
      t[1] or t.a, 
      t[2] or t.b,
      t[3] or t.c
    -- function continues down here...
end

Bất kỳ giá trị nào bị thiếu trong bảng tham số sẽ được lấy từ __indexbảng trong khả năng đo được của nó (xem tài liệu về bảng tham số ).

Tất nhiên, các kiểu tham số nâng cao hơn có thể sử dụng các hàm và hàm tạo bảng - bạn có thể viết bất cứ thứ gì bạn cần. Ví dụ, đây là một hàm tạo một hàm lấy bảng đối số có tên hoặc vị trí từ bảng xác định tên tham số và giá trị mặc định và một hàm lấy danh sách đối số thông thường.

Là một tính năng không cấp ngôn ngữ, các lệnh gọi như vậy có thể được thay đổi để cung cấp các hành vi và ngữ nghĩa mới:

  • Các biến có thể được tạo để chấp nhận nhiều hơn một tên
  • Các biến vị trí và biến từ khóa có thể được xen kẽ - và việc xác định cả hai có thể ưu tiên cho một trong hai (hoặc gây ra lỗi)
  • Có thể tạo các biến không có vị trí chỉ từ khóa, cũng như các biến chỉ vị trí không tên
  • Cấu trúc bảng khá dài có thể được thực hiện bằng cách phân tích cú pháp một chuỗi
  • Danh sách đối số có thể được sử dụng nguyên văn nếu hàm được gọi với thứ gì đó không phải là 1 bảng

Một số hàm hữu ích để viết trình dịch đối số là unpack(chuyển sang phiên bản table.unpack5.2), setfenv(không dùng nữa trong phiên bản 5.2 với _ENVcấu trúc mới ) và select(trả về một giá trị duy nhất từ ​​danh sách đối số nhất định hoặc độ dài của danh sách với '#').


AI chỉ mới bắt đầu sử dụng lua Tôi sẽ giữ nó đơn giản cho thời gian nhưng bài đăng của bạn rất nhiều thông tin. Có thể có ích sau này. Cảm ơn.
ripat

1
Trong hầu hết các trường hợp, giữ cho nó đơn giản là cách để đi. Giao diện tham số siêu chỉ thực sự cần thiết cho các đối tượng có một số lượng lớn các thuộc tính tùy chọn (chẳng hạn như các đối tượng UI).
Stuart P. Bentley

Tôi nghĩ câu trả lời này là người giải quyết các câu hỏi, không phải là câu trả lời hiện được đánh dấu là được chấp nhận. Cảm ơn vì sự khai sáng :)
Hoàn tác

1
Cần lưu ý rằng x or defaultbiểu thức cũng được sử dụng trong câu trả lời này không thực sự tương đương với mặc định tham số mà chỉ là một cách giải quyết đơn giản chỉ hoạt động nếu cả hai nilfalseđều là giá trị tham số không hợp lệ. Giả sử mặc định cho tham số boolean xtruevà người gọi chuyển một tham số rõ ràng false. Sau đó x or trueđưa ra true, mặc dù falseđã được thông qua một cách rõ ràng. Một phiên bản tốt hơn sẽ là if x == nil then x = default end, cũng dễ đọc hơn; nó vẫn không thể xử lý các nilđối số rõ ràng .
Jesper

Ồ, này, đây là câu trả lời được chấp nhận ngay bây giờ! Đẹp. (Đối với hồ sơ, và để đặt bình luận của @ Undo trong ngữ cảnh, câu trả lời của jpjacobs dưới đây là câu trả lời được chấp nhận trong một thời gian rất dài: Tôi gần đạt được huy hiệu Dân túy thứ hai nhờ nó.)
Stuart P. Bentley

46

Theo tôi không có cách nào khác. Đó chỉ là tâm lý của Lua: không rườm rà, và ngoại trừ một số đường cú pháp, không có cách thừa để làm những việc đơn giản.


10
Câu trả lời này hoàn toàn bị bác bỏ bởi câu trả lời của Stuart P. Bentley dưới đây, trong đó hàm được gọi với một hàm tạo bảng. Đây là một trong những điểm mạnh của Lua: mặc dù nó không có nhiều thứ rườm rà, nhưng các khối xây dựng cơ bản của Lua cho phép bạn làm những điều vô hạn, thực sự đáng chú ý với kích thước nhỏ và tính đơn giản của ngôn ngữ.
Colin D Bennett

@ColinDBennett Cảm ơn bạn đã lên tiếng: có vẻ như OP đã đọc bình luận của bạn và vào tháng 12 năm đó, đã thay đổi câu trả lời được chấp nhận cho phù hợp. (Và bây giờ là "câu trả lời của Stuart P. Bentley ở trên", vì lợi ích của sự rõ ràng: wink :)
Stuart P. Bentley

21

Về mặt kỹ thuật, có b = b == nil and 7 or b(nên được sử dụng trong trường falsehợp giá trị hợp lệ được false or 7đánh giá là 7), nhưng đó có thể không phải là thứ bạn đang tìm kiếm.


1
Nếu bạn không kiểm tra false, một cách đơn giản hơn là đặt biến trước và biến mặc định cuối cùng. b = b or 7
Rebs

2
Vì OP đã đề cập đến điều đó trong câu hỏi của họ, nên tôi nghĩ rằng sẽ không cần thiết phải đề cập đến (câu hỏi là về các cách xác định các biến mặc định khác b = b or 7 ).
Stuart P. Bentley

6

Cách duy nhất tôi thấy cho đến nay có ý nghĩa là làm điều gì đó như sau:

function new(params)
  params = params or {}
  options = {
    name = "Object name"
  }

  for k,v in pairs(params) do options[k] = v end

  some_var = options.name
end

new({ name = "test" })
new()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.