A late reply but it's worth addressing one way of doing this. First, your concern about object not being a valid function or macro isn't relevant at read time. Second, note that Lisp already has similar syntax: '(1 . 2) is essentially (cons 1 2). Implementing this type of syntax is not a privilege of the implementation alone. You're allowed to redefine your own reader for left paren. In SBCL:
CL-USER> (get-macro-character #\()
SB-IMPL::READ-LIST
You can write `(set-macro-character #\( 'sb-impl::read-list)` and everything continues to work just fine. You can also jump-to-source and modify it if you want -- though it's cleaner to just copy it out to your own project, that's what I did for a quick hack/proof of concept. Essentially I added before the existing (when...) which handles the special dot syntax:
(when (and (eq firstchar #\-)
(eq (peek-char t stream t nil t) #\>))
(read-char stream t) ; actually read the nextchar > to discard it
(let ((next-obj (read stream)))
(sb-impl::flush-whitespace stream rt)
(return `(slot-value ,@listtail ',next-obj))))
I won't claim this is good or proper, but it shows that it's quite feasible. We've turned (foo -> bar) into (slot-value foo 'bar).
CL-USER> (defclass vec2 ()
((x :initarg :x)
(y :initarg :y)))
#<STANDARD-CLASS COMMON-LISP-USER::VEC2>
CL-USER> (defparameter vec (make-instance 'vec2 :x 3 :y 4))
VEC
CL-USER> (vec -> y)
4
CL-USER> (read-from-string "(print (vec -> x))")
(PRINT (SLOT-VALUE VEC 'X))
18
Personally I wouldn't use this even if it was more properly/carefully implemented. (There's really no reason to replace the default left-paren reader, and no reason we have to have a space surrounding the "->". One thing I like about the infix reader macro package
https://github.com/quil-lang/cmu-infix is that it doesn't care about spaces, I can write #I(1+1 + 4) and get 6.) I'm quite happy putting my class in its own package, and thus getting the primary tab-completion behavior I care about. e.g. "(ma:<tab>" could complete to "(math:" and then "(math:v<tab>" could complete to a list of options like "vector-x" "vector-y" or so on. I also like the somewhat unusual approach of naming my accessors with a dot prefix, e.g. (.x vec) and (.y vec), or even (math:.x vec) if I haven't imported the symbol.