15

Trong tất cả các ngôn ngữ lập trình hỗ trợ các tham số tùy chọn mà tôi đã thấy có giả, các thông số tùy chọn phải xuất hiện ở cuối khai báo. Không có thông số bắt buộc nào có thể được bao gồm sau một mục tùy chọn. Lý do cho điều đó là gì? Tôi đoán nó có thể được yêu cầu biên dịch/thông dịch viên.Tại sao tham số tùy chọn phải xuất hiện ở cuối khai báo

Trả lời

16

Vâng, nếu chúng ở phía trước, bạn sẽ phát hiện ra sao khi chúng không được cung cấp? Cách duy nhất sẽ là nếu loại biến khác nhau sau thông số tùy chọn. Bit của một yêu cầu kỳ lạ, do đó, nó có ý nghĩa rằng bạn chỉ buộc họ phải là cuối cùng (lưu các rắc rối của các quy tắc phức tạp để phát hiện các "cuối cùng" tham số tùy chọn).

Bên cạnh đó, đây là cách tự nhiên nhất để thực hiện khi gọi chức năng.

+0

Hiện giờ có vẻ hiển nhiên :). Cảm ơn bạn. – Incognito

+0

@Incognito: nó hoạt động tốt trong Ruby. Nếu có các tham số bắt buộc sau các tham số tùy chọn, thì các đối số bắt buộc được lấy từ cuối danh sách đối số. Mọi thứ còn lại là các đối số tùy chọn. Xem http://StackOverflow.Com/questions/2896106/why-optional-parameters-must-appear-at-the-end-of-the-declaration/2900474/#2900474 để biết ví dụ. –

0

Chỉ cần đoán trong tự nhiên: Có thể có điều gì đó liên quan đến quy ước gọi điện (ví dụ: thông số được đẩy vào ngăn xếp từ trái sang phải, thông số tùy chọn sẽ bị bỏ qua trong trường hợp chúng không được chỉ định).

+1

Tôi nghi ngờ rằng, tôi nghĩ người gọi sẽ chỉ đẩy các giá trị mặc định thay thế. – tstenner

-1

Java và C# không có tên thông số, do đó bạn không thể làm:

myfunction(param1='Meh', optionalParam=2) 

Bạn phải làm:

myfunction('Meh', 2) 

Nếu không

myFunction(2, 'Meh') 

là mơ hồ. Làm thế nào là trình biên dịch phải biết rằng bạn có nghĩa là 2 được trong bộ tham số tùy chọn?

+7

C# 4.0 đã đặt tên cho các tham số. – Incognito

0

Tham số tùy chọn ở cuối cho phép bạn dừng chỉ định thông số tại một số điểm, ví dụ:

void Test(int a, optional int b = 0, optional int c = 0) { ... } 

Test(3); 

Nếu bạn thực hiện c một tham số cần thiết, bạn sẽ phải sử dụng cú pháp như thế này:

Test(3, , 2); 
Test(a := 3, c := 2); 

Ưu điểm của một tham số tùy chọn là nó có thể được coi như nếu nó wasn' t có. Nếu các tham số tùy chọn nằm ở giữa danh sách tham số, điều này là không thể nếu không có "đếm dấu phẩy" hoặc sử dụng một cú pháp quá chi tiết.

+1

Điều này hoạt động tốt trong Ruby. Tham số bắt buộc ở đầu danh sách tham số bị ràng buộc từ trái sang phải từ đầu danh sách đối số. Các tham số bắt buộc ở cuối danh sách tham số bị ràng buộc từ phải sang trái từ cuối danh sách đối số. Các tham số tùy chọn bị ràng buộc từ trái sang phải từ đầu danh sách đối số còn lại. Tất cả các đối số còn lại đều bị ràng buộc với các đối số còn lại. Không cung cấp đối số bắt buộc hoặc cung cấp nhiều hơn đối số 'num_mandatory + num_optional' khi không có tham số còn lại là lỗi. –

2

Xem xét một khai báo như sau:

int foo(float a, int b=0, int c=0, float d); 

(chú ý làm thế nào tôi đã xác định các thông số defult ở giữa của danh sách) mà sau đó được gọi là như

foo(0.0,1,2.0) 

cuộc gọi là gì? Cụ thể có b hoặc c bị bỏ qua?

nhà thiết kế trình biên dịch có thể làm được việc này bằng cách sử dụng tên thông số

foo(a=0,c=0,d=2.0) 

một tính năng có sẵn trong python ví dụ.

+1

Tính năng đó cũng có sẵn trong C#: foo (a: 0, c: 0, d: 2.0). Vấn đề là phải làm gì khi thực hiện các cuộc gọi vị trí. – configurator

+2

Điều này làm việc tốt trong Ruby. Tham số bắt buộc ở đầu danh sách tham số bị ràng buộc từ trái sang phải từ đầu danh sách đối số. Các tham số bắt buộc ở cuối danh sách tham số bị ràng buộc từ phải sang trái từ cuối danh sách đối số. Các tham số tùy chọn bị ràng buộc từ trái sang phải từ đầu danh sách đối số còn lại. Tất cả các đối số còn lại đều bị ràng buộc với các đối số còn lại. Không cung cấp đối số bắt buộc hoặc cung cấp nhiều hơn đối số 'num_mandatory + num_optional' khi không có tham số còn lại là lỗi. –

+0

Trong ví dụ cụ thể của bạn, 'a' sẽ bị ràng buộc với' 0.0', 'd' thành' 2.0', 'b' thành' 1' và 'c' sẽ nhận giá trị mặc định là' 0'. –

5

Đây chỉ là một quy tắc tùy ý mà các nhà thiết kế của những ngôn ngữ cụ thể đó đã thực hiện.Hoàn toàn không có lý do kỹ thuật tại sao hạn chế đó nên ở đó.

Nó hoạt động tốt trong Ruby:

def foo(m1, m2, o1='o1', o2='o2', *rest, m3, m4) 
    return m1, m2, o1, o2, rest, m3, m4 
end 

foo(1, 2, 3, 4) 
# => [1, 2, 'o1', 'o2', [], 3, 4] 

foo(1, 2, 3, 4, 5) 
# => [1, 2, 3, 'o2', [], 4, 5] 

foo(1, 2, 3, 4, 5, 6) 
# => [1, 2, 3, 4, [], 5, 6] 

foo(1, 2, 3, 4, 5, 6, 7) 
# => [1, 2, 3, 4, [5], 6, 7] 

foo(1, 2, 3, 4, 5, 6, 7, 8) 
# => [1, 2, 3, 4, [5, 6], 7, 8] 

Mọi đối số bắt buộc phải được cung cấp:

foo(1, 2, 3) 
# => ArgumentError: wrong number of arguments (3 for 4) 

Nếu không có tham số còn lại, cung cấp hơn number_of_mandatory + lập luận number_of_optional là một lỗi:

def bar(m1, m2, o1='o1', o2='o2', m3, m4) 
    return m1, m2, o1, o2, m3, m4 
end 

bar(1, 2, 3, 4, 5, 6, 7) 
# => ArgumentError: wrong number of arguments (7 for 6) 

Tham số bắt buộc ở đầu trò chơi danh sách ter bị ràng buộc từ trái sang phải từ đầu danh sách đối số. Các tham số bắt buộc ở cuối danh sách tham số bị ràng buộc từ phải sang trái từ cuối danh sách đối số. Các tham số tùy chọn bị ràng buộc từ trái sang phải từ đầu danh sách đối số còn lại. Tất cả các đối số còn lại đều bị ràng buộc với các đối số còn lại.

+0

Rõ ràng là chính xác --- càng nhiều càng tốt khi bạn có một ví dụ làm việc để hiển thị. Nhưng tôi sẽ giải thích mức độ các ngôn ngữ giống như c được xây dựng dựa trên các quy tắc đơn giản, và cách ruby ​​là dài: nó sẽ là một bất ngờ lớn trong c, và ít nhất là một phần nhỏ trong C++. – dmckee

+0

@dmckee: Ngôn ngữ giống C duy nhất mà tôi biết có các đối số tùy chọn sẽ là C#, nhưng các quy tắc của nó phức tạp một cách ồ ạt do các tương tác phức tạp giữa các đối số tùy chọn và quá tải dựa trên phép tính. Tôi tìm thấy cả hai người * ít nhất là * phức tạp tương tự, có lẽ C# thậm chí còn nhiều hơn một chút. –

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