Hello there,
I'm not quite sure whether is convenient for each method implementation to
possibly shadow previous names, particularly those of clojure.core.
(defprotocol Example
(get [this]))
The previous example redefines get in the current namespace. But is that we
usually mean by "method"? That's more of what one would expect of a *
function* definition. Given a file in a mainstream OOP lang, one can define
N "get" methods in N classes and no bad things will happen, as they are
attached to the classes, not the namespace. In principle, with protocols
and records, Clojure is trying to distil the best of OOP. But this detail,
in my opinion, seriously hampers such a goal.
Maybe get could have clojure.core semantics when the first argument does
not implement Example. I doubt it'd yield clear code though, as it
overloads meaning.
There is actually a way to work around this:
(ns protocols)
(defprotocol Prot
(first [this]))
(ns usage)
(defrecord Rec []
protocols.Prot
(first [this] "A value."))
(first (Rec.)) ; clojure.core/first gets called. This wouldn't happen in
the previous namespace!
(.first (Rec.)) ; protocols.Prot.first gets called.
However, it feels like exploiting implementation details. In fact, *it
won't work in ClojureScript*: one would be only left with the option of
using :refer-clojure. Which in practice means "don't": library authors or
even programmers in a team can't expect their API consumers to unqualify
names from clojure.core.
In my opinion, the problem lies in that the (.method obj) syntax has too
low-level semantics: it seems to mean just "interop call". Shouln't it be
leveled-up to the more general "method call"? It maps well to both Java and
JavaScript, and probably any language.
Thus, I believe that ideally, calls to Clojure *methods* should be
dot-prefixed. It'd allow us to freely/fearlessly choose whatever name we
can come up for a protocol method. Otherwise there would effectively exist
about 500 reserved words (OTOH, one gets a convenient warning when
shadowing an existing name).
Furthermore, this would blur the popular conception that dot-syntax is
"ugly" in lisps. Rich has
written<http://www.reddit.com/r/programming/comments/6jgnp/why_arc_is_bad_for_exploratory_programming/c040ptn>
:
In Clojure I can close a file like this:
(.close file)
That's a 'Java' call. Now, I could write a Clojure 'library' that let me
say:
(close file)
but I really have better things to do, and so do the people that use
Clojure.
(his point doesn't completely map to mine. But it can help changing your
mind)
Finally, I believe that method calls should be visually obvious, as their
output can potentially depend on the fields of the implementing
record/type, however immutable:
(defprotocol Foo (method [this]))
(defrecord Bar [x y z]
Foo
(method [this] "A value."))
If we run (method a-bar-instance), x, y and z are, in a way, "implicit
arguments" that method receives, since it has access to them. How do we
tell function calls from method calls? Is it immediately obvious the
presence of these "implicit arguments"?
Just as Rich warns us against *unlabeled*
mutation<http://www.deftitlenil.com/2011/09/notes-strangeloop-programming-languages.html>,
I feel concerned with unlabeled method calls.
So my proposal would be:
- Acknowledge the dot-calls as a feature of defrecord/deftype methods,
rather than a syntax that happens to work
- Make dot-calls possible in ClojureScript. As a nice side-effect, this
would simplify calling ClojureScript from JavaScript (someone other
than me has had this problem
too<http://stackoverflow.com/questions/9018326/how-do-i-create-an-js-object-with-methods-and-constructor-in-clojurescript>
).
At least from the point of view of someone that isn't too familiar with the
Clojure internals, I see no downsides - although I tried it! For instance,
given that one can call (.first ()), I thought that then one could call (.first
(ARecord.)), which would ruin my whole idea. But fortunately, that isn't
the case.
My question is quite simply - do you agree? Are these semantics
Clojure(Script) should look forward?
Thank you very much for your attention.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en