Tại sao không có toán tử gán gán cho các toán tử logic (như | |, && vv)?


20

Theo ECMA-262, phần 11.13, sau đây là danh sách đầy đủ các toán tử gán ghép : *= /= %= += -= <<= >>= >>>= &= ^= |=.

Theo phần 11.11, var c = a || bsẽ đưa agiá trị vào cnếu ToBoolean(a)đúng và sẽ đưa bgiá trị vào mặt ckhác. Do đó, OR logic thường được sử dụng làm toán tử hợp nhất, vd

function (options) {
    options = options || {};
}

Thường xuyên, kết hợp được sử dụng để chỉ định giá trị mặc định cho biến, như được hiển thị ở trên : a = a || b.

Có vẻ như toán tử gán gán ||=sẽ thực sự hữu ích, cho phép viết mã ở trên một cách ngắn gọn và gọn gàng hơn : a ||= b. Tuy nhiên, nó không phải là ở đó (mặc dù *=, +=và toán tử gán phức hợp khác).

Câu hỏi là tại sao?


2
Tôi vô cùng bối rối khi toán tử% = thậm chí còn tồn tại. Ai quyết định điều đó là cần thiết? Một số các nhà khai thác có vẻ như quyết định thiết kế ngôn ngữ xấu.
Jonathan Rich

2
@JonathanRich: tại sao không có% =? Nếu bạn sắp có bất kỳ toán tử gán nào, sớm hay muộn một số nhà phát triển (như penartur) sẽ tự hỏi tại sao các toán tử lại "bằng nhau" hơn các toán tử khác.
kevin cline

4
@JonathanRich Crypto sử dụng mô đun đáng kể. Furthemore, có một trực giao mong muốn với phần còn lại của số học toán tử gán số học (nếu ai hy vọng +=, *=, -=, /=, tại sao không %=làm việc?).

4
@JonathanRich: Toán tử có ích khi bạn có một cái gì đó hình tròn và muốn bình thường hóa nó, ví dụ angle %= 360hoặc vertexIndex %= numberOfVertices(cho danh sách đỉnh của một đa giác khép kín).
Sebastian Negraszus

Câu trả lời:


12

Một lý do có thể là các toán tử logic &&||có hành vi "đoản mạch". Toán hạng bên phải của &&||không được đánh giá trừ khi cần thiết. Có lẽ vì lý do này, các nhà thiết kế ngôn ngữ đã quyết định rằng ý nghĩa của một biểu thức như a ||= f()là không rõ ràng, và vì vậy các toán tử như vậy tốt hơn nên bỏ đi.


2
Vâng. Ví dụ, nhiều người tin rằng a ||= bnên được hiểu là a = a || b, nhưng thực tế nó có thể a || a = b(như trong Ruby ). Chúng có thể khác nhau nếu setter có tác dụng phụ. Chọn một cái có thể không tốt cho người dùng ở trại khác. Cá nhân tôi thích a || a = bcách này (cách của Ruby), nhưng tôi không chắc liệu mọi người có hài lòng với điều đó không.
Franklin Yu

8

Câu trả lời chung cho tất cả các câu hỏi về "tại sao tính năng ngôn ngữ này không được triển khai" là nhóm thiết kế ngôn ngữ đã quyết định rằng lợi ích không vượt quá chi phí.

Chi phí có thể có nhiều hình thức. Mất nhiều thời gian và công sức để thực hiện một tính năng ngôn ngữ, nhưng cũng có chi phí nội tại phức tạp: tính năng này có làm cho ngôn ngữ trở nên phức tạp hoặc mơ hồ hơn, không tương xứng với lợi ích tiềm năng của nó không?

||=Toán tử giả định làm một cái gì đó khác biệt cơ bản với các toán tử gán gán khác. Trong khi các toán tử khác hoàn toàn là toán học về bản chất, thì toán tử này lại khác: nó thay thế một giá trị này cho một giá trị khác (trong bối cảnh bạn mô tả).

Do sự không rõ ràng này (toán tử thực hiện hai chức năng khác nhau, tùy thuộc vào ngữ cảnh), không khó để hiểu tại sao nó không được bao gồm trong ngôn ngữ. Mặc dù bạn nói rằng thay đổi

function (options) {
    options = options || {};
}

đến

function (options) {
    options ||= {};
}

để thực hiện hợp nhất null là một tính năng có giá trị, lợi ích đối với tôi không rõ ràng lắm. Nếu thay thế giá trị xảy ra, có vẻ hợp lý (và rõ ràng hơn) để có cả hai giá trị ở phía bên phải của dấu bằng, để cung cấp một dấu hiệu trực quan rằng sự thay thế đó có thể xảy ra.

C # đã chọn một đường dẫn khác và sử dụng một toán tử cụ thể để kết hợp null.


1
Khi đọc mã, ví dụ đầu tiên ở đó đọc tự nhiên hơn - "tùy chọn bằng với tùy chọn hoặc không có gì" - so với thứ hai - "tùy chọn hoặc bằng không có gì". Tôi nghĩ rằng đây chỉ là một lý do khác để không bao gồm toán tử "hoặc bằng"
Andy Hunt

Tuyệt vời mở đầu cho câu trả lời của bạn. Và tôi nghĩ rằng bắt đầu câu trả lời của bạn thuộc về wiki cho thẻ.

3
@AndyBursh Logic tương tự có thể được áp dụng cho bất kỳ toán tử gán ghép nào. "X bằng X lần 2" đọc tự nhiên hơn so với "X lần bằng 2".
Penartur

2
Lưu ý rằng gõ foo = foo || baryêu cầu bạn gõ foohai lần. Điều này vừa cồng kềnh vừa có xu hướng tái cấu trúc lỗi chính tả.
Phrogz

1
Tôi nghĩ rằng bạn hiểu sai ý nghĩa của "toán học", có lẽ bạn đã nghe nói về đại số boolean. Tôi đồng ý việc ép buộc một người không phải là boolean để sử dụng ||=như một toán tử liên kết null là không trực quan và trên thực tế có vẻ khó hiểu ở dạng mã. Nơi nó trở nên hữu ích là khi bạn đang cố gắng làm toán boolean. function fulfill(inValue) { if(resolved || rejected) return false; /* Do stuff here */ return true; } resolved ||= fulfill(value)
joshperry

3

Bạn đúng đó ||=là một cấu trúc hữu ích. Nó tồn tại trong Perl.

Trong thực tế Perl làm cho tất cả những thứ này có sẵn:

**=    +=    *=    &=    <<=    &&=   -=    /=    
|=     >>=   ||=   .=    %=     ^=    //=   x=

Một số trong số này là tuyệt vời ( .=thêm một cái gì đó vào cuối chuỗi), một số khác thì ít hơn ( &&=??? Tôi cho rằng biến sẽ được đặt ở phía bên phải nếu cả nó và biến đều đúng. Nhưng tại sao bạn lại làm điều này ?)

Những gì được bao gồm trong một ngôn ngữ thực sự là một tính năng của triết lý thiết kế của nó.


3
stackoverflow.com/questions/12589467/ cấp cho những gì &&=có nghĩa là / không.
Mat
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.