The best I can come up with is a variant of ? : that checks for existence instead of truth:
a[b] ?? "exists" : "does not exist"
One could extend it by making the middle expression optional. If it's left out then the value of the expression is the value of the test. E.g.
a[b] ??: "does not exist"
would either produce the result from the lookup of b in a or the string "does not exist".
But it seems a bit ad hoc to me to introduce another operator for this case, i.e. one that would either catch a very specific exception or look for the UNDEFINED value.
The Icon language has taken an interesting approach to this. It implements a sort of lightweight exceptions based on that every expression can either produce a value or fail. Such a failure is propagated much like an exception but only out of the expression. Then it simply becomes the value false for it. E.g. what in Pike would be written
mixed x; if (zero_type (x = a[b])) return -1; else return sizeof (x);
could be condensed to
return sizeof (a[b]) || -1;
If the lookup succeeds, its result would be fed to sizeof(), which always would succeed (given the type is correct). The || operator would then have a successful evaluation in its first operand and would return the its value. But if the lookup fails then sizeof() would never be called since a function with a failed argument will fail itself. || would then have failure in its first operand and continue to its second instead, and -1 would be returned.
It's apparent that this allows considerably more compact code. Many "silly" variables such as x above can be avoided. Perhaps it gets too compact; some experience is probably required to say whether programs become hard to understand or not.
See http://www.cs.arizona.edu/icon/ for info about Icon. The Overview page explains the idea about expression failure pretty well. Maybe it's possible to use this idea in Pike 8 or so. I suspect it'd take the language quite a bit from the current C-like operator behavior, but that's not necessarily a bad thing in my view.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-01-23 17:42: Subject: Re: zero_type() & UNDEFINED and _typeof()
I think the exception thing would work if there was some syntax sugar and a decent exception hierarchy.
try { mixed x = foo(); werror("The value is %O\n", x); } except { no_value: werror("No value\n"); }
One would also want some syntax sugar to make m[foo] | "bar" work (and do the right thing, with "bar" used iff m[foo] doesn't exist). It's hard to cook up a good syntax. Perhaps a trinary or n-ary !: could work (by a stretch analogy with trinary ?):
m[foo] ! no_value : "bar"
/ Niels Möller ()