Tại sao ngôn ngữ không bao gồm hàm ý như một toán tử logic?


60

Nó có thể là một câu hỏi lạ, nhưng tại sao không có hàm ý là toán tử logic trong nhiều ngôn ngữ (Java, C, C ++, Python Haskell - mặc dù như người cuối cùng có người dùng xác định toán tử tầm thường của nó để thêm nó)? Tôi thấy hàm ý logic rõ ràng hơn nhiều để viết (đặc biệt là trong các khẳng định hoặc các biểu thức giống như khẳng định) sau đó phủ định bằng hoặc:

encrypt(buf, key, mode, iv = null) {
    assert (mode != ECB --> iv != null);
    assert (mode == ECB || iv != null);
    assert (implies(mode != ECB, iv != null)); // User-defined function
}

28
Bởi vì nó không được đặt trong C; nếu nó đã được đặt thì C ++, Java và C # sẽ có nó.
m3th0dman

4
Nhưng C không có nó, vì nó không phải là một phần phổ biến của ngôn ngữ lắp ráp. Trong khi tất cả các bộ hướng dẫn mà tôi biết bao gồm và, hoặc không, tôi không biết bất kỳ bộ nào bao gồm ngụ ý - chắc chắn sẽ có người đi cùng để nói với tôi về một số bộ hướng dẫn tối nghĩa không lâu ...
Jack Aidley

4
Có thể nó được coi là dư thừa vì (1) nó ít nguyên thủy hơn "^", "v", "~", (2) nó tiết kiệm rất ít việc gõ vì "A => B" tương đương với "~ A v B" .
Giorgio

4
Các ngôn ngữ liên quan đến các cấu trúc logic có nhiều khả năng có nó. Chủ yếu trong số này là prolog

9
Tôi ngạc nhiên khi bạn nghĩ assert# 1 rõ ràng hơn # 2. Tôi đã nhìn chằm chằm vào # 1 một thời gian và vẫn không thể thấy hành vi của nó có thể được coi là trực quan như thế nào. (đặc biệt là có thêm !=logic lật)
Chris Burt-Brown

Câu trả lời:


61

Nó có thể hữu ích để có đôi khi, không có nghi ngờ. Một số điểm tranh luận chống lại một nhà điều hành như vậy:

  • Các nhân vật ->có giá trị, cả trong sự cô lập và kết hợp. Nhiều ngôn ngữ đã sử dụng chúng để chỉ những thứ khác. (Và nhiều người không thể sử dụng các bộ ký tự unicode cho cú pháp của họ.)
  • Hàm ý rất phản trực giác, ngay cả với những người có đầu óc logic như lập trình viên. Việc ba trong số bốn mục trong bảng chân lý là trueđiều khiến nhiều người ngạc nhiên.
  • Tất cả các toán tử logic khác là đối xứng, sẽ tạo ra ->ngoại lệ cho tính trực giao.
  • Đồng thời, có một cách giải quyết dễ dàng: sử dụng toán tử !||.
  • Hàm ý được sử dụng rất ít thường xuyên hơn logic and/ or.

Đây có lẽ là lý do tại sao các nhà điều hành là hiếm ngày nay. Chắc chắn nó có thể trở nên phổ biến hơn, vì các ngôn ngữ động mới sử dụng Unicode cho mọi thứ và quá tải toán tử trở nên thời trang hơn một lần nữa.


22
Điểm đầu tiên của bạn chỉ lập luận chống lại việc sử dụng '->' làm biểu tượng cho toán tử, chứ không chống lại việc thực sự có toán tử. Những người khác là điểm tốt.
AShelly

14
"Đồng thời, có một cách giải quyết dễ dàng: sử dụng! Và &&.": Trên thực tế, cách mô phỏng đơn giản nhất "->" (hoặc "=>", vì nó phổ biến hơn trong Toán học), là sử dụng !||, không !&&: A -> Btương !A || Bđương với !(A && !B).
Giorgio

22
"Việc ba trong số bốn mục trong bảng sự thật là sự ngạc nhiên thực sự của nhiều người." Wat. Tôi biết một nhà điều hành khác có cùng tính năng được sử dụng khá thường xuyên ...
l0b0

9
@ l0b0, tôi là một lập trình viên đã học CS, nhưng đã lâu rồi. Tôi đã quên rằng "ngụ ý" là một hoạt động chính thức với hai toán hạng trả về giá trị thật, vì vậy ban đầu tôi đã nhầm lẫn về bản chất của câu hỏi này. Trong lời nói hàng ngày, tôi chỉ sử dụng "ngụ ý" khi toán hạng đầu tiên đã được biết là đúng ("X là đúng, vì vậy Y phải đúng"). Sau một phút, tôi nhớ cách "ngụ ý" chính thức hoạt động, nhưng thực tế vẫn còn - ngay cả đối với một người đã từng học logic chính thức, ý định đó không rõ ràng với tôi. Và nếu tôi chưa bao giờ nghiên cứu về nó, nó thậm chí sẽ không có ý nghĩa.
Ben Lee

5
(a) Trong C -> được sử dụng làm toán tử. Không ai phàn nàn về điều đó. Tôi sẽ sử dụng => anyway. (b) Phản trực giác cho ai? Định nghĩa của hàm ý chỉ là, một định nghĩa. (c) phép trừ không giao hoán. Không ai phàn nàn về điều đó. (d) Tôi nghĩ bạn có ý nghĩa! và ||. Bởi vì ưu tiên (và) thường cũng cần thiết. Đối số tương tự có thể được sử dụng đối với && hoặc ||; bạn chọn đi. (e) Có lẽ đó là vì nó không có trong hầu hết các ngôn ngữ. Nhiều công dụng của | | có thể được chính xác và (ít nhất là với tôi) bằng trực giác thay thế bằng hàm ý.
Theodore Norvell

54

Tôi tin rằng câu trả lời nằm trong nền tảng toán học . Hàm ý thường được xem xét và định nghĩa là một hoạt động xuất phát, không phải là cơ bản của đại số boolean. Ngôn ngữ lập trình tuân theo quy ước này.

Đây là Dự luật I của Chương II từ Cuộc điều tra về các định luật của George Boole (1854) :

Tất cả các hoạt động của Ngôn ngữ, như một công cụ lý luận, có thể được thực hiện bởi một hệ thống các dấu hiệu bao gồm các yếu tố sau, viz.:

1 Biểu tượng nghĩa đen, như x, y, & c., Đại diện cho những thứ như là chủ đề của quan niệm của chúng tôi.

lần 2. Các dấu hiệu hoạt động, như +, -, ×, đại diện cho các hoạt động của tâm trí theo đó các khái niệm về sự vật được kết hợp hoặc giải quyết để hình thành các khái niệm mới liên quan đến các yếu tố tương tự.

lần thứ 3. Dấu hiệu nhận dạng, =.

Và những biểu tượng Logic này được sử dụng theo các định luật xác định, một phần đồng ý và một phần khác với định luật của các biểu tượng tương ứng trong khoa học Đại số.

Dấu hiệu của Boole + đại diện cho cùng một "hoạt động của tâm trí" mà ngày nay chúng ta nhận ra là cả hai công cụ boolean ọor và liên hiệp các bộ. Tương tự các dấu - và × tương ứng với phủ định boolean của chúng ta, phần bù của một tập hợp, boolean ooland và giao của các tập hợp.


+1 - câu trả lời chắc chắn. Đại số Boolean và sự đơn giản hóa trong logic mà nó cho phép điều khiển rất nhiều phương pháp lập trình. Sử dụng "ngụ ý ..." sẽ có khả năng can thiệp vào các điều kiện "không quan tâm".

3
1. Điều đó phụ thuộc vào định nghĩa. Có thể định nghĩa hoặc là a || b = !(!a && !b)(Tôi đã gặp hoặc là toán tử dẫn xuất trong logic). 2. Lý do tại sao nó được thực hiện thường là để đơn giản hóa chứng minh cảm ứng mà tôi tin (chúng ta biết rằng các toán tử dẫn xuất chỉ là các đường tắt nên chúng ta không cần phải có trường hợp riêng cho chúng). @ GlenH7: Điều kiện "không quan tâm" là gì? a --> bcũng giống như !a || b.
Maciej Piechotka

3
Ngoài ra - chúng tôi có các toán tử dẫn xuất khác như xor ( !=) nxor ( ==) ...
Maciej Piechotka

5
Trên thực tế, bạn có thể lấy được mọi thứ từ NAND !(a && b)hoặc NOR !(a || b). Ví dụ, NOT a == a NAND a, a AND b == NOT(a NAND b), a OR b == (NOT a) NAND (NOT b). Nhưng việc chỉ cung cấp một toán tử NAND sẽ đưa bạn vào địa hạt của các ngôn ngữ bí truyền (rất phù hợp với điều đáng ngạc nhiên, được cung cấp tên người dùng của người trả lời ;-)).
Stefan Majewsky

1
@Stefan: Bạn cũng có thể lấy được mọi thứ từ IMPL.
Mason Wheeler

37

CẬP NHẬT: Câu hỏi này là chủ đề của blog của tôi vào tháng 11 năm 2015 . Cảm ơn câu hỏi thú vị!


Visual Basic 6 (và VBScript) đã có Impvà các Eqvtoán tử. Không ai sử dụng chúng. Cả hai đều bị xóa trong VB.NET; Theo hiểu biết của tôi, không ai phàn nàn.

Tôi đã làm việc trong nhóm trình biên dịch Visual Basic (với tư cách là một thực tập sinh) trong một năm và chưa bao giờ nhận thấy rằng VB thậm chí có các toán tử đó. Nếu tôi không phải là người viết trình biên dịch VBScript, và do đó phải kiểm tra việc triển khai của họ, có lẽ tôi sẽ không nhận thấy chúng. Nếu anh chàng trong nhóm biên dịch không biết về tính năng này và không sử dụng nó, điều đó sẽ cho bạn biết điều gì đó về tính phổ biến và tính hữu dụng của tính năng này.

Bạn đã đề cập đến các ngôn ngữ giống như C. Tôi không thể nói với C hoặc C ++ hoặc Java nhưng tôi có thể nói với C #. Có một danh sách các tính năng do người dùng đề xuất cho C # dài hơn nghĩa đen của bạn. Theo hiểu biết của tôi, không có người dùng nào từng đề xuất một nhà điều hành như vậy cho nhóm C # và tôi đã đi qua danh sách đó rất nhiều lần.

Các tính năng tồn tại và không được sử dụng trong một ngôn ngữ và không bao giờ được yêu cầu trong một ngôn ngữ khác là những ứng cử viên không thể biến nó thành ngôn ngữ lập trình hiện đại. Đặc biệt là khi không có đủ thời gian và công sức và tiền bạc có sẵn trong ngân sách để thực hiện các tính năng mà người ta muốn.


IMP quay trở lại như một nhà điều hành cho ngày GWBASIC. Tôi nhớ nó từ năm 1979.
zarchasmpgmr

1
Tôi đã đọc rằng IMPL rất hữu ích cho các hợp đồng mã. (Mà VB không có.)
Mason Wheeler

3
Các lập trình viên VBScript có lẽ là nhóm ít có khả năng sử dụng toán tử như vậy. Tôi muốn ngay bây giờ rằng PowerShell có một toán tử ngụ ý để tôi có thể dễ dàng thực hiện & dễ dàng hơn một [switch]số tham số bộ lọc.
brianary

Tôi nhớ IMP từ DEC BASIC. Tôi không nhớ EQV. Toán tử mà tôi thường mong muốn là "và không", sẽ thúc đẩy toán tử bên tay phải trước khi phủ nhận nó. Do đó, 0xABCD12345678ul ~& 0x00200000usẽ mang lại 0xABCD12145678ul chứ không phải 0x12145678ul.
supercat

19

Tôi chỉ có thể đoán, nhưng một lý do có thể là có những cách giải quyết khá đơn giản và dễ đọc. Hãy xem xét ví dụ của bạn:

if (mode != ECB) assert (iv != null);

assert (mode != ECB --> iv != null);  // <-- that's only one character shorter

Nếu bạn cần một biểu thức, toán tử nội tuyến-if có sẵn trong hầu hết các ngôn ngữ (thường được gọi là toán tử ternary) có thể được sử dụng. Cấp, điều này không thanh lịch như A --> B, nhưng số trường hợp sử dụng có thể không biện minh cho việc thêm (và duy trì!) Một toán tử khác:

assert (mode != ECB ? iv != null : true);

2
Như khẳng định - có lý do chính đáng. Cái đầu tiên sẽ tạo ra (trong nhiều lần triển khai) thông báo "lỗi xác nhận: iv! = Null" trong khi thứ hai "lỗi xác nhận: mode! = ECB -> iv! = Null".
Maciej Piechotka

2
+1, tôi đã định hỏi điều tương tự cho câu hỏi này (vì tôi không quen lắm với "hàm ý", nên nó không bao giờ xuất hiện hàng ngày). Các iftuyên bố là xa, xa rõ ràng hơn để chỉ là về tất cả mọi người.
Izkata

12

Eiffel có ý nghĩa

Nó thực sự có nhiều hơn. Nó có một số nhà khai thác bán nghiêm ngặt cũng như nghiêm ngặt.

Lý do các lập trình viên không sử dụng những thứ đó là vì họ không bao giờ được đào tạo để biết chính xác họ là gì, sử dụng chúng như thế nào và khi nào sử dụng chúng - cũng như cách thiết kế với chúng. Bởi vì họ không bao giờ được đào tạo, họ không bao giờ yêu cầu nó từ các trình soạn thảo trình biên dịch, đó là lý do tại sao người biên dịch không bận tâm đưa các cơ chế như vậy vào trình biên dịch. Khi sinh viên Khoa học Máy tính và lập trình viên cây bóng mát bắt đầu có một nền giáo dục toàn diện hơn, thì trình biên dịch sẽ bắt đầu theo kịp.

Nó chỉ ra rằng một khi bạn có một ngôn ngữ với các toán tử Boolean như vậy và bạn biết cách thiết kế với chúng và sử dụng chúng, thì bạn sử dụng chúng.

Ở Eiffel, việc sử dụng từ khóa "ngụ ý" khá nổi bật do Thiết kế theo Hợp đồng do tính chất Boolean nặng nề của các xác nhận hợp đồng. Có một số hợp đồng chỉ có thể được viết đúng và hiệu quả với toán tử "ngụ ý". Điều này sau đó đưa ra nhận xét rằng các ngôn ngữ không có hợp đồng sẽ không có lý do để xem xét, đào tạo và thực hiện việc sử dụng hàm ý.

Thêm vào đó, hầu hết các lập trình viên là "toán-và-logic-yếu" cho chúng ta biết phần còn lại của câu chuyện. Ngay cả khi bạn học toán và logic nặng về giáo dục, khi bạn chọn một ngôn ngữ không triển khai các cấu trúc như hàm ý, thì người ta có xu hướng nghĩ những thứ đó là không cần thiết hoặc không hữu ích. Người ta hiếm khi đặt câu hỏi về ngôn ngữ và đi vào một phòng chứa tiếng vang: "Chà, những người biên dịch không thấy nhu cầu" và "Chà, các lập trình viên không thấy sự cần thiết" - vòng tròn vô tận và luẩn quẩn.

Thay vào đó, người biên dịch cần sao lưu lý thuyết, viết một ký hiệu ngôn ngữ được đề xuất hoặc ngụ ý bởi lý thuyết (ví dụ: Lý thuyết hướng đối tượng) bất kể khối lượng lập trình viên chưa nghĩ gì hoặc yêu cầu. Từ đó, các giáo sư, giáo viên và các chuyên gia khác cần phải đào tạo một cách thành thạo những bộ óc non nớt dựa trên lý thuyết thô và KHÔNG "lý thuyết xuyên thấu kính ngôn ngữ". Khi điều này xảy ra, mọi người sẽ đột nhiên thức dậy và nhận ra những gì họ đã mất và những gì đã được nhấn mạnh trên chúng.

Ngay bây giờ - có rất nhiều lý thuyết ngoài kia đã giả mạo theo Định hướng đối tượng, nhưng chỉ là OO-xuyên-một-ly-tối-của- [chọn ngôn ngữ của bạn]. Người ta không thể đọc hầu hết các cuốn sách "lý thuyết" về OO vì họ muốn diễn giải lý thuyết là gì qua lăng kính của một số ngôn ngữ. Hoàn toàn sai và không chính xác. Nó sẽ giống như dạy toán dựa trên máy tính của tôi hoặc quy tắc trượt của tôi. KHÔNG - người ta cho phép thực tế dạy một người về chính mình và sau đó sử dụng một ký hiệu để mô tả những gì người ta quan sát - đó gọi là "khoa học". Bản mash khác này được gọi là OO dựa trên ngôn ngữ-X bị sai lệch đến mức hầu như không đại diện cho thực tế.

Vì vậy, bước ra khỏi ngôn ngữ, hãy xem lý thuyết thô và bắt đầu lại. Đừng để những hạn chế, ràng buộc và công việc vẽ ngôn ngữ cho bạn biết lý thuyết là gì. Đơn giản chỉ cần để thực tế của lý thuyết ra lệnh cho ký hiệu của chính nó và sau đó chuyển từ đó thành một ngôn ngữ.

Từ đó, bạn sẽ bắt đầu hiểu được hàm ý và "hàm ý" không chỉ hữu ích, mà còn thanh lịch và rất tuyệt vời!

Có một cái tuyệt vời!


7

Python có một toán tử hàm ý theo một cách ẩn.

Toán tử nhỏ hơn hoặc bằng bằng bị quá tải để chấp nhận các giá trị boolean. Kết quả là, người ta có thể sử dụng nó như là một toán tử hàm ý.

Bằng chứng bằng ví dụ (Mã Python):

print (False <= False) # This will print True.
print (False <= True)  # This will print True.
print (True <= False)  # This will print False.
print (True <= True)   # This will print True.

Nhớ lại bảng chân lý của toán tử hàm ý là:

LEFT RIGHT RESULT
F    F     T
F    T     T
T    F     F
T    T     T

2
Điều này là tuyệt vời, nhưng không may có các thuộc tính nghiêm ngặt sai: f() implies g()không nên đánh giá g()nếu f()False, nhưng <=không đánh giá g()trong trường hợp này.
Jon Purdy

2
@Jon Purdy - Nói đúng ra, đánh giá ngắn mạch là một tính năng tùy chọn của các toán tử nhị phân. Vì vậy, về mặt kỹ thuật, đây là một triển khai hoàn toàn hợp pháp của toán tử hàm ý. Điều đó đang được nói, tôi thực sự nghi ngờ rằng Guido van Rossum thậm chí còn dự định đây là một nhà điều hành hàm ý. Đây chỉ là một sự châm biếm so sánh booleans.
Mackenzie

Chắc chắn, tôi đã nói rằng đó là một quan sát thú vị, nhưng không phải là thứ bạn nên sử dụng trong các chương trình thực tế vì nó không bị đoản mạch và điều đó có thể khiến ai đó bất ngờ nếu họ dự kiến ​​sẽ did_all_possible_stuff = x.do_required_stuff() and (x.supports_optional_stuff() <= x.do_optional_stuff())làm việc.
Jon Purdy

2
Điều này cũng hoạt động trong C và C ++.
Ben Voigt

5

Eiffel có một toán tử "ngụ ý" và nó rất hay để viết trước và sau điều kiện. Nó làm cho mã dễ đọc hơn, thật không may, đó chưa bao giờ là một cường độ cơ bản đối với ngôn ngữ C và quá ít người sử dụng eiffel nên vẻ đẹp của "ngụ ý" khi toán tử không được biết đến nhiều.


2

Đối với tôi, vấn đề lớn với ngụ ý xuất hiện khi điều kiện ban đầu là sai; ví dụ: "Nếu mặt trời xanh, thì tôi là dơi ăn quả". Thật!

Trong logic hình thức, nó chỉ hoạt động để gán "True" cho giá trị khi điều kiện hàm ý không được đáp ứng. Nhưng trong lập trình, điều đó có thể dẫn đến kết quả phản trực giác và đáng ngạc nhiên.

Tôi thực sự nghĩ rằng ví dụ @Heinzi đưa ra ở trên:

if (sun.color() == "green") then assert(me.species() == "fruitbat")

Dễ hiểu hơn nhiều và ít bị lỗi do hiểu sai logic.

Trong bối cảnh thử nghiệm, tôi chỉ dừng lại khoảnh khắc giả định của mình trở thành sai:

assert(sun.color() == "green")
assert(me.species() == "fruitbat")

Vì vậy, theo quan điểm của @Eric Lippert, với tư cách là một lập trình viên tôi không biết khi nào tôi sử dụng một toán tử ngụ ý. Hành vi "Sai là đúng" có vẻ hữu ích trong bối cảnh toán học, logic hình thức, nhưng có thể dẫn đến kết quả không mong muốn trong logic chương trình.

...

Không ai đã đề cập đến "?" toán tử, trong đó "A? B: true" giống như "ngụ ý". Nhưng trong khi logic chính thức gán đúng với điều kiện "khác", "?" cho phép nhà phát triển chỉ định rõ ràng

Trong logic hình thức, sử dụng "true" sẽ hiệu quả, nhưng trong lập trình, nếu điều kiện là sai, thì câu trả lời tốt hơn giống như "null" hoặc "void" hoặc "bỏ qua", hoặc thậm chí có thể sai.

Tôi nghĩ rằng ai đó sẽ phải đưa ra trường hợp tại sao "ngụ ý" là một toán tử hữu ích hơn các câu lệnh "?", Hoặc "nếu", hoặc chỉ là luồng chương trình thông thường.


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.