Programming language idiom for "if object.value == some_value then object.value = some_other_value" - programming-languages

I've been wondering myself multiple times if, and if not, why not, there is an idiom/shortcut for the following pseudocode:
if object.value == some_value then object.value = some_other_value
For example, in JavaScript I sometimes write:
if (document.getElementById("toggledDiv").style.display == "block") {
document.getElementById("toggledDiv").style.display = "none";
}
This seems to be rather tedious. Is there a name for this idiom, and is there a more concise syntax for this in common programming languages?
Thank you!
Edit: To be more precise, I don't care about the braces, but about that you have to reference the attribute at least to times. I'd like to have something like that (pseudocode):
test ( object.value ):
if (it > 0) it = 0;
else it -= 1;
e. g.:
test (document.getElementById("toggledDiv").style.display):
if (it == "block") it = "none";
where it is a keyword that references the tested property. I'm just wondering no programming language seems to have implemented that.
Upate:
Okay, in the meantime I have found something which is a little bit short, but only works in JavaScript:
(function(s){
if(s.display=='block')
s.display="none";
else
s.display='block';
})(document.getElementById("toggledDiv").style)

Well, in Haskell, and other FP languages, conditionals, like ternary operators, are first-class expressions, so you can float the assignment out,
a = if x == y then x else z
Making the code a lot cleaner.

I don't know of any languages that support it out of the box, but there are a number that support defining new operators. In theory, you could write something like the following (in psuedo-code)
operator <T> T toggle(T value, T[] values) {
for(int i=0; i<values.size(); i++) {
if(value == values[i]) {
if(values.size() > (i+1)) {
return values[i+1]
} else {
return values[0]
}
}
}
error "value $value not found in value list $values"
}
Assuming my psuedo-code is correct, this would allow you to do the following:
v = true;
v = v toggle [true, false] ; // v == false
v = v toggle [true, false] ; // v == true (loops to beginning of list
v = v toggle [false, true, true] ; // v == true, since true is both the 2nd and 3rd elements of the list
You could also two versions:
One that, if the values isn't in the list, returns the original value
One that, if the values isn't in the list, throws an error (what my version did)
The former would be less of a toggle and more of... what you asked for, I guess. I was basing the code off the toggle use case from the previous note about css/block/none, where toggle is the more common behavior.
Assuming the language supports it, you could write a toggle= operator too:
v toggle= ['none', 'block']

In JavaScript you can do:
var d = document.getElementById("toggledDiv");
if (d.style.display == "block") d.style.display = "none";

Related

What is the "?:" operator used for in Groovy?

Trying to understand this line of Groovy code:
return strat?.descriptor?.displayName ?: "null"
Is the ?: a shorthand if/else? Does this mean if strat?.descriptor?.displayName is not null, print it, or else print null ?
I'm confused because there isn't anything between the ? and : like I would normally expect in an if/else statement.
Just to add some more insight, the "?:" operator is known as the binary operator or commonly referred to as the elvis operator. The following code examples all produce the same results where x evaluates to true according to Groovy Truth
// These three code snippets mean the same thing.
// If x is true according to groovy truth return x else return y
x ?: y
x ? x : y // Standard ternary operator.
if (x) {
return x
} else {
return y
}
Click here for more info on Elvis Operator
Yes, the "?:" operator will return the value to the left, if it is not null. Else, return the value to the right.
The ? operator is the one you're asking about. That is the safe navigation operator. It is used to avoid null exception and return null value instead.
You can read more about it here:
https://groovy-lang.org/operators.html#_safe_navigation_operator

Problems overloading Groovy comparison operators

I am building an analytic application using Groovy and require very forgiving math operators regardless of data format. I achieve this through operator overloading, in many cases improving (in my case) on the default Groovy type flexibility. As an example, I need 123.45f + "05" to equal 128.45f. By default Groovy downgrades to String and I get 123.4505.
In most cases my overloading works very well, but not for comparison operators. I've followed a couple of discussions on this, but I'm not getting to an answer and I'm looking for ideas. I recognize that the goal is to overload compareTo() (vs. something like lessThan), but Groovy seems to ignore this and instead attempts its own smart comparison - e.g. DefaultTypeTransformation.compareTo(Object left, Object right), which fails on mixed types.
Unfortunately this is a must have for me, because improperly comparing two values compromises the whole solution and I don't have control over some of the data types being analyzed (e.g. vendor data structures).
For example, I need the following to work:
Float f = 123.45f;
String s = "0300";
Assert.assertTrue( f < s );
I have many permutations of these, but my attempt to overload includes (let's just assume my JavaTypeUtil does what I need if I can get Groovy to call it):
// overloads on startup, trying to catch all cases
Float.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
Float.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
When I try the above test, none of these are called and instead I get:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Float
at java.lang.Float.compareTo(Float.java:50)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareToWithEqualityCheck(DefaultTypeTransformation.java:585)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareTo(DefaultTypeTransformation.java:540)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareTo(ScriptBytecodeAdapter.java:690)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThan(ScriptBytecodeAdapter.java:710)
at com.modelshop.datacore.generator.GroovyMathTests.testMath(GroovyMathTests.groovy:32)
Debugging through I see that the < operator goes right to ScriptBytecodeAdapter.compareLessThan(), and the implementation of that seems to ignore the overloaded compareTo() here:
In DefaultTypeTransformations.java:584 (2.4.3)
if (!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
|| (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
|| (left instanceof GString && right instanceof String)) {
Comparable comparable = (Comparable) left;
return comparable.compareTo(right); // <--- ***
}
In a desperate attempt, I've also tried to overload compareLessThan, but I'm grasping now, I don't know that there's any way to jump in front of the < mapping in Groovy.
Float.metaClass.compareLessThan << {
Object right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
Float.metaClass.compareLessThan << {
String right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
Any thoughts on a work-around? Thanks!
Part of it is you need to include static, like this
Float.metaClass.static.compareTo = { String s -> 0 }
This makes f.compareTo(s) work, but the < operator still won't work. This is a known limitation. The only operators that can be overloaded are mentioned in the documentation. Possibly you could do a custom AST to change all those operators to a compareTo().
But this isn't the whole story. f <=> s also doesn't work, despite <=> delegating to compareTo(). I believe this is because Float doesn't implement Comparable<Object> or Comparable<String>, only Comparable<Float>. Although I'm not sure where exactly in the chain Groovy makes the decision not to use that method, you can see it's not limited to Groovy's math classes. This also doesn't work
Foo.metaClass.compareTo = { String s -> 99 }
new Foo() <=> ''
class Foo implements Comparable<Foo> {
int compareTo(Foo o) {
0
}
}
I think Groovy is doing some pre-parsing validation that's preventing the metaclass stuff from working. Whatever validation it's doing definitely inspects the interfaces implemented, because this fails for a different reason
Foo.metaClass.compareTo = { String s -> 99 }
new Foo() <=> ''
class Foo {
int compareTo(Foo o) {
0
}
}
In both of these examples, replacing <=> with compareTo() works.
This question has been asked a couple times before, but I haven't seen a good explanation for why. You might try asking on the user mailing list. I'm sure Jochen or Cedric would be able to explain why.
I guess the point is that your compareTo closure is expecting an Object; so when you invoke compareTo with a String, your closure doesn't get called at all.
I can only think of the following; being precise when specifying closure input parameter type:
Float.metaClass.compareTo = { Integer n -> aStaticHelperMethod(n) }
Float.metaClass.compareTo = { String s -> aStaticHelperMethod(s) }
Float.metaClass.compareTo = { SomeOtherType o -> aStaticHelperMethod(o) }

Why does a hashCode() returning zero cause List.minus() to return an empty list?

Given class Foo with this decidedly poor hashCode() implementation:
class Foo {
String name
public int hashCode() {
0
}
public boolean equals(Object obj) {
if (obj == null) {
return false
}
if (!(obj instanceof Foo)) {
return false
}
Foo foo = (Foo) obj
return this.name.equals(foo.name)
}
}
Why does the following assertion fail?
Foo f1 = new Foo(name: 'Name 1')
Foo f2 = new Foo(name: 'Name 2')
Foo f3 = new Foo(name: 'Name 2')
assert ([f1, f2] - [f3]).size() == 1
The result of the minus() is an empty list. If I switch the hashCode() implementaion toreturn name.hashCode(), the assertion passes. With either implementation, methods like contains() work as expected.
My question is not how to implement a better hashCode(), but why minus() behaves this way.
this would be exactly the behaviour described in the docs for minus:
Create a List composed of the elements of the first list minus every occurrence of elements of the given Collection.
assert [1, "a", true, true, false, 5.3] - [true, 5.3] == [1, "a", false]
You remove each element, that is in the second list. In your case remove all f3 from [f1,f2], where all are the same, hence the empty list.
The finer details are in DefaultGroovyMethods.minus and then in NumberAwareComperator, which uses the hashCode. as you have already found, there are open tickets regarding this (https://jira.codehaus.org/browse/GROOVY-7158). So under the eyes, that hashCode is used there, the behaviour is perfectly consistent... should it be used there? maybe not, because there are cases, where it really gets odd (e.g. [[x:0,y:0]]-[[x:1,y:1]]==[]).
The case [f1,f2]-f3 takes another route in code and therefor behaves differently.
For now my best guess would be, that you use minus for immutable types (like above example), where it works quite well. Beside that, rather work with sets.
The java Collections use the implementation of hashCode/equals to determine object equality. Your implementation of hashCode indicates that that f1, f2, and f3 are all "the same". Loosely speaking:
[f1, f2] - [f3]
could be read as
Remove from the list all objects that are the same as f3
so it removes all objects.
You seem to already be aware that this is a terrible way to implement hashCode, so it's really just a case of "garbage in, garbage out".

Use literal operators (eg "and", "or") in Groovy expressions?

My current work project allows user-provided expressions to be evaluated in specific contexts, as a way for them to extend and influence the workflow. These expressions the usual logical ones f. To make it a bit palatable for non-programmers, I'd like to give them the option of using literal operators (e.g. and, or, not instead of &, |, !).
A simple search & replace is not sufficient, as the data might contains those words within quotes and building a parser, while doable, may not be the most elegant and efficient solution.
To make the question clear: is there a way in Groovy to allow the users to write
x > 10 and y = 20 or not z
but have Groovy evaluate it as if it were:
x > 10 && y == 20 || !z
Thank you.
Recent versions of Groovy support Command chains, so it's indeed possible to write this:
compute x > 10 and y == 20 or not(z)
The word "compute" here is arbitrary, but it cannot be omitted, because it's the first "verb" in the command chain. Everything that follows alternates between verb and noun:
compute x > 10 and y == 20 or not(z)
───┬─── ──┬─── ─┬─ ───┬─── ─┬─ ──┬───
verb noun verb noun verb noun
A command chain is compiled like this:
verb(noun).verb(noun).verb(noun)...
so the example above is compiled to:
compute(x > 10).and(y == 20).or(not(z))
There are many ways to implement this. Here is just a quick & dirty proof of concept, that doesn't implement operator precedence, among other things:
class Compute {
private value
Compute(boolean v) { value = v }
def or (boolean w) { value = value || w; this }
def and(boolean w) { value = value && w; this }
String toString() { value }
}
def compute(v) { new Compute(v) }
def not(boolean v) { !v }
You can use command chains by themselves (as top-level statements) or to the right-hand side of an assignment operator (local variable or property assignment), but not inside other expressions.
If you can swap operators like > and = for the facelets-like gt and eq, respectively, i THINK your case may be doable, though it will require a lot of effort:
x gt 10 and y eq 20 or not z
resolves to:
x(gt).10(and).y(eq).20(or).not(z)
And this will be hell to parse.
The way #Brian Henry suggested is the easiest way, though not user-friendly, since it needs the parens and dots.
Well, considering we can swap the operators, you could try to intercept the Integer.call to start expressions. Having the missing properties in a script being resolved to operations can solve your new keywords problem. Then you can build expressions and save them to a list, executing them in the end of the script. It's not finished, but i came along with this:
// the operators that can be used in the script
enum Operation { eq, and, gt, not }
// every unresolved variable here will try to be resolved as an Operation
def propertyMissing(String property) { Operation.find { it.name() == property} }
// a class to contain what should be executed in the end of the script
#groovy.transform.ToString
class Instruction { def left; Operation operation; def right }
// a class to handle the next allowed tokens
class Expression {
Closure handler; Instruction instruction
def methodMissing(String method, args) {
println "method=$method, args=$args"
handler method, args
}
}
// a list to contain the instructions that will need to be parsed
def instructions = []
// the start of the whole mess: an integer will get this called
Integer.metaClass {
call = { Operation op ->
instruction = new Instruction(operation: op, left: delegate)
instructions << instruction
new Expression(
instruction: instruction,
handler:{ String method, args ->
instruction.right = method.toInteger()
println instructions
this
})
}
}
x = 12
y = 19
z = false
x gt 10 and y eq 20 or not z
Which will give an exception, due the not() part not being implemented, but it can build two Instruction objects before failing:
[Instruction(12, gt, 10), Instruction(19, eq, 20)]
Not sure if it is worth it.
The GDK tacks on and() and or() methods to Boolean. If you supplied a method like
Boolean not(Boolean b) {return !b}
you could write something like
(x > 10).and(y == 20).or(not(4 == 1))
I'm not sure that's particularly easy to write, though.

To ternary or not to ternary? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm personally an advocate of the ternary operator: () ? :
I do realize that it has its place, but I have come across many programmers that are completely against ever using it, and some that use it too often.
What are your feelings on it? What interesting code have you seen using it?
Use it for simple expressions only:
int a = (b > 10) ? c : d;
Don't chain or nest ternary operators as it hard to read and confusing:
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;
Moreover, when using ternary operator, consider formatting the code in a way that improves readability:
int a = (b > 10) ? some_value
: another_value;
It makes debugging slightly more difficult since you can not place breakpoints on each of the sub expressions. I use it rarely.
I love them, especially in type-safe languages.
I don't see how this:
int count = (condition) ? 1 : 0;
is any harder than this:
int count;
if (condition)
{
count = 1;
}
else
{
count = 0;
}
I'd argue that ternary operators make everything less complex and more neat than the alternative.
Chained I'm fine with - nested, not so much.
I tend to use them more in C simply because they're an if statement that has value, so it cuts down on unnecessary repetition or variables:
x = (y < 100) ? "dog" :
(y < 150) ? "cat" :
(y < 300) ? "bar" : "baz";
rather than
if (y < 100) { x = "dog"; }
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; }
else { x = "baz"; }
In assignments like this, I find it's less to refactor, and clearer.
When I'm working in ruby on the other hand, I'm more likely to use if...else...end because it's an expression too.
x = if (y < 100) then "dog"
elif (y < 150) then "cat"
elif (y < 300) then "bar"
else "baz"
end
(Although, admittedly, for something this simple, I might just use the ternary operator anyway.)
The ternary ?: operator is merely a functional equivalent of the procedural if construct. So as long as you are not using nested ?: expressions, the arguments for/against the functional representation of any operation applies here. But nesting ternary operations can result in code that is downright confusing (exercise for the reader: try writing a parser that will handle nested ternary conditionals and you will appreciate their complexity).
But there are plenty of situations where conservative use of the ?: operator can result in code that is actually easier to read than otherwise. For example:
int compareTo(Object object) {
if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
return 1;
if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
return -1;
else
return 0;
}
Now compare that with this:
int compareTo(Object object) {
if(isLessThan(object))
return reverseOrder ? 1 : -1;
else(isGreaterThan(object))
return reverseOrder ? -1 : 1;
else
return 0;
}
As the code is more compact, there is less syntactic noise, and by using the ternary operator judiciously (that is only in relation with the reverseOrder property) the end result isn't particularly terse.
It's a question of style, really; the subconscious rules I tend to follow are:
Only evaluate 1 expression - so foo = (bar > baz) ? true : false, but NOT foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
If I'm using it for display logic, e.g. <%= (foo) ? "Yes" : "No" %>
Only really use it for assignment; never flow logic (so never (foo) ? FooIsTrue(foo) : FooIsALie(foo) ) Flow logic in ternary is itself a lie, ignore that last point.
I like it because it's concise and elegant for simple assignment operations.
Like so many opinion questions, the answer is inevitably: it depends
For something like:
return x ? "Yes" : "No";
I think that is much more concise (and quicker for me to parse) than:
if (x) {
return "Yes";
} else {
return "No";
}
Now if your conditional expression is complex, then the ternary operation is not a good choice. Something like:
x && y && z >= 10 && s.Length == 0 || !foo
is not a good candidate for the ternary operator.
As an aside, if you are a C programmer, GCC actually has an extension that allows you to exclude the if-true portion of the ternary, like this:
/* 'y' is a char * */
const char *x = y ? : "Not set";
Which will set x to y assuming y is not NULL. Good stuff.
In my mind, it only makes sense to use the ternary operator in cases where an expression is needed.
In other cases, it seems like the ternary operator decreases clarity.
I use the ternary operator wherever I can, unless it makes the code extremely hard to read, but then that's usually just an indication that my code could use a little refactoring.
It always puzzles me how some people think the ternary operator is a "hidden" feature or is somewhat mysterious. It's one of the first things I learnt when I start programming in C, and I don't think it decreases readability at all. It's a natural part of the language.
By the measure of cyclomatic complexity, the use of if statements or the ternary operator are equivalent. So by that measure, the answer is no, the complexity would be exactly the same as before.
By other measures such as readability, maintainability, and DRY (don't repeat yourself), either choice may prove better than the other.
I use it quite often in places where I'm constrained to work in a constructor - for example, the new .NET 3.5 LINQ to XML constructs - to define default values when an optional parameter is null.
Contrived example:
var e = new XElement("Something",
param == null ? new XElement("Value", "Default")
: new XElement("Value", param.ToString())
);
or (thanks asterite)
var e = new XElement("Something",
new XElement("Value",
param == null ? "Default"
: param.ToString()
)
);
No matter whether you use the ternary operator or not, making sure your code is readable is the important thing. Any construct can be made unreadable.
I agree with jmulder: it shouldn't be used in place of a if, but it has its place for return expression or inside an expression:
echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;
The former is just an example, and better internationalisation and localisation support of plural should be used!
If you're using the ternary operator for a simple conditional assignment I think it's fine. I've seen it (ab)used to control program flow without even making an assignment, and I think that should be avoided. Use an if statement in these cases.
(Hack of the day)
#define IF(x) x ?
#define ELSE :
Then you can do if-then-else as expression:
int b = IF(condition1) res1
ELSE IF(condition2) res2
ELSE IF(conditions3) res3
ELSE res4;
I think the ternary operator should be used when needed. It is obviously a very subjective choice, but I find that a simple expression (specially as a return expression) is much clearer than a full test. Example in C/C++:
return (a>0)?a:0;
Compared to:
if(a>0) return a;
else return 0;
You also have the case where the solution is between the ternary operator and creating a function. For example in Python:
l = [ i if i > 0 else 0 for i in lst ]
The alternative is:
def cap(value):
if value > 0:
return value
return 0
l = [ cap(i) for i in lst ]
It is needed enough that in Python (as an example), such an idiom could be seen regularly:
l = [ ((i>0 and [i]) or [0])[0] for i in lst ]
this line uses properties of the logical operators in Python: they are lazy and returns the last value computed if it is equal to the final state.
I've seen such beasts like (it was actually much worse since it was isValidDate and checked month and day as well, but I couldn't be bothered trying to remember the whole thing):
isLeapYear =
((yyyy % 400) == 0)
? 1
: ((yyyy % 100) == 0)
? 0
: ((yyyy % 4) == 0)
? 1
: 0;
where, plainly, a series of if-statements would have been better (although this one's still better than the macro version I once saw).
I don't mind it for small things like:
reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;
or even slightly tricky things like:
printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");
I like using the operator in debug code to print error values so I don't have to look them up all the time. Usually I do this for debug prints that aren't going to remain once I'm done developing.
int result = do_something();
if( result != 0 )
{
debug_printf("Error while doing something, code %x (%s)\n", result,
result == 7 ? "ERROR_YES" :
result == 8 ? "ERROR_NO" :
result == 9 ? "ERROR_FILE_NOT_FOUND" :
"Unknown");
}
I almost never use the ternary operator, because whenever I do use it, it always makes me think a lot more than I have to later when I try to maintain it.
I like to avoid verbosity, but when it makes the code a lot easier to pick up, I will go for the verbosity.
Consider:
String name = firstName;
if (middleName != null) {
name += " " + middleName;
}
name += " " + lastName;
Now, that is a bit verbose, but I find it a lot more readable than:
String name = firstName + (middleName == null ? "" : " " + middleName)
+ " " + lastName;
Or:
String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;
It just seems to compress too much information into too little space, without making it clear what's going on. Every time I saw the ternary operator used, I have always found an alternative that seemed much easier to read... then again, that is an extremely subjective opinion, so if you and your colleagues find ternary very readable, go for it.
I like them. I don't know why, but I feel very cool when I use the ternary expression.
I treat ternary operators a lot like GOTO. They have their place, but they are something which you should usually avoid to make the code easier to understand.
Well, the syntax for it is horrid. I find functional ifs very useful, and they often makes code more readable.
I would suggest making a macro to make it more readable, but I'm sure someone can come up with a horrible edge case (as there always is with C++).
I typically use it in things like this:
before:
if(isheader)
drawtext(x, y, WHITE, string);
else
drawtext(x, y, BLUE, string);
after:
drawtext(x, y, isheader == true ? WHITE : BLUE, string);
As others have pointed out they are nice for short simple conditions. I especially like them for defaults (kind of like the || and or usage in JavaScript and Python), e.g.
int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;
Another common use is to initialize a reference in C++. Since references have to be declared and initialized in the same statement you can't use an if statement.
SomeType& ref = pInput ? *pInput : somethingElse;
I like Groovy's special case of the ternary operator, called the Elvis operator: ?:
expr ?: default
This code evaluates to expr if it's not null, and default if it is. Technically it's not really a ternary operator, but it's definitely related to it and saves a lot of time/typing.
I recently saw a variation on ternary operators (well, sort of) that make the standard "() ? :" variant seem to be a paragon of clarity:
var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]
or, to give a more tangible example:
var Name = ['Jane', 'John'][Gender == 'm'];
Mind you, this is JavaScript, so things like that might not be possible in other languages (thankfully).
Only when:
$var = (simple > test ? simple_result_1 : simple_result_2);
KISS.
For simple if cases, I like to use it. Actually it's much easier to read/code for instance as parameters for functions or things like that. Also to avoid the new line I like to keep with all my if/else.
Nesting it would be a big no-no in my book.
So, resuming, for a single if/else I'll use the ternary operator. For other cases, a regular if/else if/else (or switch).
For simple tasks, like assigning a different value depending on a condition, they're great. I wouldn't use them when there are longer expressions depending on the condition though.
If you and your workmates understand what they do and they aren't created in massive groups I think they make the code less complex and easier to read because there is simply less code.
The only time I think ternary operators make code harder to understand is when you have more than three or foyr in one line. Most people don't remember that they are right based precedence and when you have a stack of them it makes reading the code a nightmare.
As so many answers have said, it depends. I find that if the ternary comparison is not visible in a quick scan down the code, then it should not be used.
As a side issue, I might also note that its very existence is actually a bit of an anomaly due to the fact that in C, comparison testing is a statement. In Icon, the if construct (like most of Icon) is actually an expression. So you can do things like:
x[if y > 5 then 5 else y] := "Y"
... which I find much more readable than a ternary comparison operator. :-)
There was a discussion recently about the possibility of adding the ?: operator to Icon, but several people correctly pointed out that there was absolutely no need because of the way if works.
Which means that if you could do that in C (or any of the other languages that have the ternary operator), then you wouldn't, in fact, need the ternary operator at all.

Resources