70

It might be a strange question, but why there is no implication as a logical operator in many languages (Java, C, C++, Python Haskell - although as last one have user defined operators its trivial to add it)? I find logical implication much clearer to write (particularly in asserts or assert-like expressions) then negation with or:

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
}
yoozer8
  • 693
  • 31
    Because it wasn't put in C; if it have been put then C++, Java and C# would have had it. – Random42 Jan 18 '13 at 13:17
  • 4
    But C doesn't have it, in turn, because it's not a common part of assembly language. Whereas as all instruction sets I know of include and, or and not, I know of none that include implies - no doubt someone will be along to tell me of some obscure instruction set that does shortly... – Jack Aidley Jan 18 '13 at 14:30
  • 2
    @JackAidley: Not exactly implies but Intel's MMX have and not which is inverse of the implies. If ISA in general constitute something obscure nowadays is of course matter of debate. – Maja Piechotka Jan 18 '13 at 14:50
  • 4
    Maybe it was considered redundant because (1) it is less primitive than "^", "v", "~", (2) it saves very little typing since "A => B" is equivalent to "~A v B". – Giorgio Jan 18 '13 at 14:50
  • 5
    Languages that deal with logical constructions are more likely to have it. Chiefly among these is prolog –  Jan 18 '13 at 15:22
  • 3
    BTW Imp and Eqv were in VB6, but did not survive the .NET transition. – Mark Hurd Jan 18 '13 at 18:31
  • b.t.w Cobra has an implies operator which fits its design-by-contract philosophy. (Though your example isn't good, since you don't want implication, you want equivalence, since ECB can't take an IV) – CodesInChaos Jan 19 '13 at 16:47
  • 1
    back in the day, Tandy BASIC had IMP – warren Jan 21 '13 at 18:49
  • 10
    I'm surprised that you think assert #1 is clearer than #2. I have stared at #1 for some time and still can't see how it's behaviour could be considered intuitive. (especially with the extra != flipping the logic) – Chris Burt-Brown Feb 14 '13 at 16:07
  • 1
    @ChrisBurt-Brown: Possibly it's result of too much logic and type systems but I'm surprised second may be clearer - first one clearly says "whenever mode is not ECB iv must not be null" while second states "either mode is ECB or iv is not null". They are logically equivalent but first one IMHO conveys the intent better (although I admit that it looks like the believe is not exactly widely shared). – Maja Piechotka Feb 15 '13 at 10:39
  • 1
    troll Because --> is already taken by the "goes to operator" (http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator) – WebMonster May 01 '14 at 10:23
  • 1
    Seems implication is possible in Haskell : "Logical implication is a common enough operator, usually written "a => b" for a implies b. Haskell doesn't feature a => operator, it would be a syntax error because that symbol is reserved for class constraints. Both QuickCheck and SmallCheck feature incompatible ==> operators for implication. But Haskell does provide a boolean implication operator, namely (<=)! Yes, by writing the implication symbol backwards, you get standard forward implication!" Taken from http://neilmitchell.blogspot.com/2007/02/logical-implication-in-haskell.html – blue-sky May 01 '14 at 09:44
  • 1
    I guess whether the implies operator is intuitive or not is 90% training and habit. To me the first assert is by far better. Nobody would use such an operator because nobody is trained to. – usr Jul 15 '14 at 18:15
  • 1
    As I recall PL/I had both IMP and EQV. Also Coldfusion and many dialects of Basic. In some languages x<=Y and x==y for booleans serve the same purpose. Not rare at all. – david.pfx Jul 28 '14 at 11:01
  • 1
    You might be interested by expert systems and their inference engines. You should have a look into Prolog and proof assistants like Coq – Basile Starynkevitch Jul 30 '14 at 07:03
  • 2
    @Giorgio: Were I designing a language, I would make "andnot" a primitive. Just as one doesn't typically arithmetically subtract Y from X by writing X+= -Y, nor should one bitwise-subtract Y from X by writing "X &= ~Y". Not all forms of logic can synthesize a "not" operator or a "true" value, but even many that can't could still support "and not". For example, given two sets of strings X=["Moe", "Larry", "Curly"] and Y=["Homer", "Moe", "Lenny"], computing the set "X andnot Y" should not require producing the set of all strings which are not present in Y. – supercat Sep 12 '14 at 19:04

9 Answers9

63

It could be useful to have sometimes, no doubt. Several points argue against such an operator:

  • The characters - and > are valuable, both in isolation and combined. Many languages already use them to mean other things. (And many can't use unicode character sets for their syntax.)
  • Implication is very counter-intuitive, even to logic-minded people such as programmers. The fact that three out of the four truth table entries are true surprises many people.
  • All other logical operators are symmetrical, which would make -> an exception to orthogonality.
  • At the same time, there is an easy workaround: use operators ! and ||.
  • Implication is used vastly less often than logical and/or.

This is probably why the operator is rare today. Certainly it could become more common, as new dynamic languages use Unicode for everything and operator overloading becomes more fashionable again.

Kilian Foth
  • 109,273
  • 23
    Your first point only argues against using '-->' as the symbol for the operator, not against actually having the operator. The others are good points. – AShelly Jan 18 '13 at 14:21
  • 16
    "At the same time, there is an easy workaround: use ! and &&.": In fact, the simplest way of simulating "->" (or "=>", as it is more common in Math), is to use ! and ||, not ! and &&: A -> B is equivalent to !A || B which is equivalent to !(A && !B). – Giorgio Jan 18 '13 at 14:53
  • 27
    "The fact that three out of the four truth table entries are true surprises many people." Wat. I know another operator with the same feature which is used rather often... – l0b0 Jan 18 '13 at 18:09
  • 1
    @l0b0 Yeah, but for or, that's what everyone expects. The same doesn't apply to implication. – svick Jan 20 '13 at 01:16
  • 2
    @svick: These blanket statements about other developers is a bit strange. I'd expect people who have studied CS to think something like "anything can follow from a false premise, while a true premise can only lead to a true result." – l0b0 Jan 20 '13 at 09:06
  • 1
    @l0b0 Not every developer has studied computer science. And I think understanding a simple condition shouldn't require a CS degree. – svick Jan 20 '13 at 12:34
  • 10
    @l0b0, I'm a programmer who studied CS, but it was a long time ago. I had forgotten that "implies" is a formal operation with two operands that returns a truth value, so at first I was confused at the nature of this question. In everyday speech, I only ever use "implies" when the first operand is already known to be true ("X is true, so Y must be true"). After a minute, I remembered how formal "implies" works, but the fact remains -- even for someone who once did study formal logic, the intent was not clear to me. And if I had never studied it, it wouldn't have even eventually made sense. – Ben Lee Jan 22 '13 at 20:54
  • 8
    (a) In C -> is used as an operator. No one complains about that. I would use => anyway. (b) Counter-intuitive to whom? The definition of implication is just that, a definition. (c) subtraction is not commutative. No one complains about that. (d) I think you mean ! and ||. Because of precedence ( and ) are often also needed. The same argument could be used against && or ||; take your pick. (e) Perhaps that is because it is not in most languages. Many uses of || could be concisely and (to me at least) intuitively replaced by implication. – Theodore Norvell Sep 15 '13 at 20:30
  • After rereading @TheodoreNorvell reply - I'd start to think how many people would find surprising that or is inclusive in programming if the usage having been long established. – Maja Piechotka Oct 17 '13 at 01:15
  • @TheodoreNorvell Subtraction (and division) are not logical operators. They are mathematical operators. – Izkata Oct 26 '13 at 01:29
  • @Izkata I was making an analogy between logical operations and arithmetic operations. Also, on this point, the objection is that the lack of symmetry somehow makes implication "an exception to orthogonality". I don't see what symmetry and orthogonality have to do with each other. Not begin symmetric makes implication an exception among the set of binary logical operations commonly offered in programming languages; but what could be an "exception to orthogonality"? Of course being exceptional is hardly an objection, especially if, like implication, the construct is exceptionally useful. – Theodore Norvell Oct 26 '13 at 23:38
  • @TheodoreNorvell It's probably a reference to the "simplicity" part of the meaning used here, since it would be the only non-symmetrical logical operator – Izkata Oct 27 '13 at 00:05
  • 1
    These arguments all sound like coming from someone who desperately wants to justify not brushing his teeth. But then again, even Erlang doesn't have it and in Prolog it basically indicates the search tree branch. – David Tonhofer Nov 18 '13 at 16:22
  • my guess is because it's not commutative (a -> b) != (b -> a) whereas other popular boolean operators are in fact commutative. Commutative operators you can rearrange freely without worry or concern. I would like to think that implication would be useful, but I guess it's often easier to spell out the !a || b since there isn't any room for confusion. – BeardedO Jun 27 '22 at 18:07
55

I believe the answer lies in the mathematical foundations. Implication is usually considered and defined as a derived, not elementary, operation of boolean algebras. Programming languages follow this convention.

This is Proposition I of Chapter II from George Boole's An Investigation of the Laws of Thought (1854):

All the operations of Language, as an instrument of reasoning, may be conducted by a system of signs composed of the following elements, viz.:

1st. Literal symbols, as x, y, &c., representing things as subjects of our conceptions.

2nd. Signs of operation, as +, −, ×, standing for those operations of the mind by which the conceptions of things are combined or resolved so as to form new conceptions involving the same elements.

3rd. The sign of identity, =.

And these symbols of Logic are in their use subject to definite laws, partly agreeing with and partly differing from the laws of the corresponding symbols in the science of Algebra.

Boole's sign + represents the same "operation of the mind" we today recognize as both the boolean ´or´ and the union of sets. Similarly the signs − and × correspond to our boolean negation, complement of a set, boolean ´and´ and intersection of sets.

COME FROM
  • 2,696
  • +1 - solid answer. Boolean algebra and the simplifications in logic that it allows drives a lot of programming methodology. Using an "implies ..." would potentially interfere with "don't care" conditions. –  Jan 18 '13 at 14:34
  • 3
  • That depend on definition. It is possible to define or as a || b = !(!a && !b) (I met or as derived operator in logic). 2. The reason why it is done is usually to simplify induction proves I believe (we know that derived operators are just short-cuts so we don't need to have separate case for them). @GlenH7: What "don't care" conditions? a --> b is the same as !a || b.
  • – Maja Piechotka Jan 18 '13 at 14:55
  • 4
    Also - we have other derived operators like xor (!=) nxor (==)... – Maja Piechotka Jan 18 '13 at 14:57
  • 6
    Actually, you can derive everything from either NAND !(a && b) or NOR !(a || b). For example, NOT a == a NAND a, a AND b == NOT(a NAND b), a OR b == (NOT a) NAND (NOT b). But providing only a NAND operator puts you in the realm of esoteric languages (which fits surprisingly well, given the answerer's username ;-) ). – Stefan Majewsky Jan 18 '13 at 22:17
  • @MaciejPiechotka: True, this depends on definition. Just about everything in mathematics depends on definitions. And sure, (!=) and (==) could be interpreted as xor and xnor (though I wouldn't consider them boolean operators at all). What I wanted to point out is that there are conventions about definitions and specifically about definitions of Boolean algebras. Furthermore, there are reasons and history behind these conventions, and that history goes way beyond the scope of modern programming languages. – COME FROM Jan 22 '13 at 11:13
  • @MaciejPiechotka Due to short-circuiting, a || b and !(!a && !b) are not equivalent. The first will evaluate b in situations where the second will not, and vice-versa. – Izkata Oct 26 '13 at 01:32
  • @Izkata: It depends on language. In C/C++/Java/... you're right but there are languages which does not have it specified (Haskell for example IIRC). – Maja Piechotka Oct 26 '13 at 09:48
  • @Izkata: First one will evaluate b iff a is false and second will evaluate b iff !a is true. In other words second will evaluate b iff a is false. So they should be equivalent unless I missed something. – Maja Piechotka Feb 21 '14 at 00:55
  • 1
    @Stefan: You can also derive everything from an IMPL. – Mason Wheeler May 01 '14 at 15:15
  • Good answer. I would add that think about this as a compression scheme. What operators are widely used? then support them as atomic operation which means you don't have to have long encoding to express it. Sometimes even composite operators like XOR are compressed into a seemingly elementary operator because people use it a lot. – InformedA Jul 15 '14 at 08:56
  • @StefanMajewsky: Some contexts support primitives X or Y and X andnot Y, but cannot support nand nor nor. For example, if X and Y were sets of names, one could produce a list of names that appear in exactly one list, or that appear only in the first, but one cannot produce a list of names that don't appear in either. Note that the aformentioned primitives are sufficient to derive X and Y and X xor Y. Although one could derive X andnot Y from X and Y and X xor Y [(X xor Y) and X], I think andnot is more commonly useful. – supercat Sep 12 '14 at 19:15
  • After a thought - programming probably have a lot more in common constructive logic then classical one (the operation symbols and derive rules including Hoare Logic, Curry–Howard correspondence etc.). In the former the negation (and everything else) is defined in terms of implication rather then other way round. – Maja Piechotka Aug 21 '15 at 16:53
  • @MaciejPiechotka - fyi, Haskell does have clearly defined order of evaluation for the arguments to boolean operations. It may seem counter-intuitive for a pure language, but it is important in the case that either one argument throws an exception or is infinitely recursive. – Jules Dec 08 '15 at 10:51