views:

368

answers:

8

The "ternary operator" expression is now almost equivalent to the ternary conditional operator:

condition ? trueExpression : falseExpression;

However, "ternary operator" only means that it takes three arguments. I'm just curious, are there any languages with any other built-in ternary operators besides conditional operator and which ones?

+13  A: 

There’s the slice operator in Python:

a = [1, 2, 3]
b = a[1 : 2 : 2]

With the operands meaning start, stop and step.

Konrad Rudolph
/me hugs Python
Oli
I've been wondering about this one. Shouldn't we view the range part of the slice operation as being a second-class value? Python throws the error "Invalid range expression" as well as "Invalid slice expression".
Charles Stewart
@Charles: well, there’s not really a formal definition of ternary operator in programming languages, is there? For me, it simply means an *atomic* part of the language. And while you can extract the `start : stop` syntax from the slice ternary operator to form a *binary* slice operator, you cannot extract the `: step` portion meaningfully. So for me, the `a : b : c` operator is *one* operator and the Python documentation also says that.
Konrad Rudolph
@Konrad: Yes, when you look at it that way, it is clearly ternary.
Charles Stewart
This is not really a ternary operator, but a quaternary one. The operator is not only the values inside the brackets, but the brackets as well and the operand before them. Just `a:b:c` doesn't have meaning in Python, but `a[b:c:d]` has (four operands). `a[b:c]` is a ternary operator (a, b and c are the three operands).
Juliano
+10  A: 

These operators are often called mixfix operators (also, sometimes triadic operators). The Maude rewriting logic language allows user-defined mixfix operators, as does the dependently typed functional programming language, Agda.

In general, they're not common, because they can be tricky to parse and because, if there is no deferred evaluation, you can usually find a nice, readable decomposition into binary infix operators.

Charles Stewart
+5  A: 

Mathematica has the "TagSet" operator

f /: g = h

which associates g to h and differentiate this assignment using f, e.g.

a /: f[a] = 2
b /: f[b] = 8
c f[c] + b f[b] + a f[a]
(* # prints 'c f[c] + 8 b + 2 a' *)
KennyTM
+1  A: 

CLU's element update syntax works on any abstract type that provides a store method. The full syntax is "T$store(primary, e1, e2)", but it has an elegant ternary syntactic sugar:

primary[e1] := e2

What I especially like about this is that any type can participate in this syntax; it's not limited to arrays. So you can define it on hash tables, search trees, basically whatever you like.

Norman Ramsey
+2  A: 

SQL's foo BETWEEN 0 AND 10 is another example.

Michał Marczyk
Doesn't this just take a high and a low?
Daniel DiPaolo
It also takes a `foo`.
Michał Marczyk
+1  A: 

Scala's foldLeft (/:) operator:

val list = List(4, 1, 8, 9)
def add(a: Int, b: Int) = a + b
val sum = (0 /: list)(add)

Takes three parameters: a seed value, a collection and an operation to use for reduction.

It should however be noted that technically Scala doesn't have operators. All the "operators" in Scala are actually just regular methods.

missingfaktor
Operators can be methods: it's a syntactic distinction. But /: is a regular infix operator: (0 :/ List(1,2,3)) evaluates to a third-order function of type "((Int, Int) => Int) => Int".
Charles Stewart
@Charles: Isn't that just an implementation detail?
missingfaktor
@Rahul: Is what an implementation detail? Syntax is normally part of the language spec.
Charles Stewart
@Charles: That `:/` is an infix operator that evaluates to a third-order function of type `((Int, Int) => Int) => Int`. To the user, `/:` looks like something that takes three arguments viz; a seed, an iterable and a reduction operation.
missingfaktor
@Charles: SQL's `BETWEEN-AND` can also be implemented in Scala in a similar manner: http://paste.pocoo.org/show/232686/ Won't you call it a ternary operator?
missingfaktor
@Rahul: Implementation details are choices compiler writers make which aren't constrained by the language spec., and if the user thinks that /: is ternary, they're going to be surprised by expressions like `val fold4 = 0 /: List(1,2,3,4)`. BETWEEN-AND is a great example, thanks aplenty for the link, but I can't give you my answer to your question (yet) because I see I don't understand implicit def as well as I thought. It looks like magic.
Charles Stewart
@Charles: _"if the user thinks that /: is ternary, they're going to be surprised by expressions like val fold4 = 0 /: List(1,2,3,4)."_ Good point, that.
missingfaktor
+2  A: 

Python's a < b < c comes to mind, it's equivalent to a < b and b < c - not to (a < b) < c as someone may think.

I suppose we can say in Python there is whole class of ternary comparison operators of the type expr1 op1 expr2 op2 expr3, where op1 and op2 are binary comparison operators?

Nas Banov
A: 

Just to do my bit for Lisp today, many of the binary operators are actually n-ary operators in Common Lisp,

(< a b c) => a < b and b < c

(+ 1 2 3) => 6

so you can read < as monotonically increasing if it tickles your fancy.

Ukko