safe navigation operator

116 views
Skip to first unread message

Stuart Halloway

unread,
Oct 3, 2008, 3:13:13 PM10/3/08
to clo...@googlegroups.com
Groovy has a safe navigation operator. Yes, this probably enables Law
of Demeter violations, but it is darn useful when you are dealing with
existing Java APIs that required lots.of.dotted.notation.

I would like to have this in Clojure. Anybody else like it?

(defmacro ?.
"like .. but drops out on null object"
([x form]
`(. ~x ~form))
([x form & more]
`(if-let x# (. ~x ~form) (.? x# ~@more))))

BTW, my use case was (?. someClass getProtectionDomain getCodeSource
getLocation). This needs to drop out for null whenever someClass comes
from a ClassLoader that cannot report its location.

Stuart

P.S. A cooler name than "save navigation operator" would be welcome,
and I am not wedded to the Groovy syntax. I initially misremembered it
as ".?" which I think I may like better.

Stuart Sierra

unread,
Oct 3, 2008, 9:52:50 PM10/3/08
to Clojure
On Oct 3, 3:13 pm, Stuart Halloway <stuart.hallo...@gmail.com> wrote:
> (defmacro ?.
>    "like .. but drops out on null object"
>    ([x form]
>       `(. ~x ~form))
>    ([x form & more]
>       `(if-let x# (. ~x ~form) (.? x# ~@more))))

Interesting -- I like it. It doesn't seem to be totally compatible
with "..", though:

user=> (?. System (getenv "SHELL") (startsWith "/bin") getClass
getName)
java.lang.Exception: Unable to resolve symbol: startsWith in this
context (NO_SOURCE_FILE:62)

Also, if-let could give the wrong result in the (admittedly unlikely)
situation that one of the methods returns Boolean.FALSE.
Here's another take:

(defmacro ?..
"like .. but stops and returns nil if any method returns nil"
([x form]
`(.. ~x ~form))
([x form & more]
`(let [x# (?. ~x ~form)]
(if (nil? x#) nil
(?. x# ~@more)))))

user=> (?.. System (getenv "SHELL") (startsWith "/bin") getClass
getName)
"java.lang.Boolean"
user=> (?.. System (getenv "FOO") (startsWith "/bin") getClass
getName)
nil

-the other Stuart

Stuart Halloway

unread,
Oct 6, 2008, 9:36:08 AM10/6/08
to clo...@googlegroups.com
Yes, that's better. Glad you like the idea.

Does anybody not named Stuart also want to see this added to
Clojure? ;-)

Stuart

Rich Hickey

unread,
Oct 6, 2008, 10:00:38 AM10/6/08
to Clojure
I'm not opposed, but we'll need to find another name. Leading ? is a
likely candidate for rule syntax, and trailing means predicate.

.?.

?

Rich

Paul Stadig

unread,
Oct 6, 2008, 10:06:07 AM10/6/08
to clo...@googlegroups.com
.? kinda almost works. It's not exactly a predicate, but it means "access this member if not null".

Or perhaps .* which would mean "access as many members as possible in the following list".


Paul

Stuart Halloway

unread,
Oct 6, 2008, 10:24:13 AM10/6/08
to clo...@googlegroups.com
> .?.

OK with me. Needs a dorky name to match. :-)

Stuart Sierra

unread,
Oct 6, 2008, 10:29:15 AM10/6/08
to Clojure
On Oct 6, 10:00 am, Rich Hickey <richhic...@gmail.com> wrote:
> I'm not opposed, but we'll need to find another name. Leading ? is a
> likely candidate for rule syntax, and trailing means predicate.
>
> .?.
>
> ?

Or, more verbosely, "nilsafe.."
-Stuart Sierra

Parth Malwankar

unread,
Oct 6, 2008, 10:37:15 AM10/6/08
to Clojure
This construct will be very useful.

How about the name "maybe" or similar along the lines of Haskell
"Maybe"
http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Maybe.html

Parth

>
> .?.
>
> ?
>
> Rich
Reply all
Reply to author
Forward
0 new messages