ClojureScript

Simplify the dot access special form.

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Critical Critical
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Currently ClojureScript provides the following dot access syntaxes:

(.p o)           ;=> a property access

(.m o <args>)    ;=> a method call

(. o p)          ;=> a property access

(. o p <args>)   ;=> a method call

(. o (m))        ;=> a method call

(. o (m <args>)) ;=> a method call

This is potentially confusing. Especially considering that Clojure looks as follows:

(.p o)           ;=> a property access if p is a property

(.p o)           ;=> a method call if p is a method

(.m o <args>)    ;=> a method call

(. o p)          ;=> a property access if p is a property

(. o p)          ;=> a method call if p is a method

(. o p <args>)   ;=> a method call

(. o (m))        ;=> a method call

(. o (m <args>)) ;=> a method call

The divergence between the Clojure and ClojureScript way is due to first-class functions. That is, in JavaScript a property can be a field or a function or a method. There is currently no way to distinguish between the desire to call a method and retrieve a function as a property except through syntax. This ticket would shorten the gap between Clojure and ClojureScript in the following way (ClojureScript proposal below):

(.m o)           ;=> a method call

(.m o <args>)    ;=> a method call

(. o m)          ;=> a method call

(. o m <args>)   ;=> a method call

(. o (m))        ;=> a method call

(. o (m <args>)) ;=> a method call

(.-p o)          ;=> a property access

(. o -p)         ;=> a property access

This would be a breaking change, but would shorten the divergence between Clojure and ClojureScript.

Activity

Hide
David Nolen added a comment -

Done

Show
David Nolen added a comment - Done
Hide
David Nolen added a comment -

At this point it's probably water under the bridge. If you're interested in memfn, please submit a patch

Show
David Nolen added a comment - At this point it's probably water under the bridge. If you're interested in memfn, please submit a patch
Hide
Thomas Scheiblauer added a comment -

I would also prefer Stuart's solution due to the reasons he mentioned and because the currently implemented concatenation of sugar characters (.-somefield obj) didn't really make the matter taste more sweet it feels rather clumsy to me.
By the way, I would also propose to implement 'memfn' for staying consistent with Clojure (if it hasn't already been done so).

Show
Thomas Scheiblauer added a comment - I would also prefer Stuart's solution due to the reasons he mentioned and because the currently implemented concatenation of sugar characters (.-somefield obj) didn't really make the matter taste more sweet it feels rather clumsy to me. By the way, I would also propose to implement 'memfn' for staying consistent with Clojure (if it hasn't already been done so).
Hide
Stuart Sierra added a comment - - edited

Back in the dark ages before Clojure 1.0, you always had to write this;

(. o (m))  ; method call
(. o f)    ; field access

Later, but before the introduction of (.m o) syntax, this was shortened to (. o x) for both methods and fields. What if we went back to the original dot operator syntax, but assume that (.m o) always means a method call:

(. o f)     ; always field access
(. o (m))   ; always method call
(.m o)      ; always method call

Raw field access is rare in Java, perhaps less so in JavaScript. But this doesn't require adding any new syntax and is consistent with what Clojure programmers are used to.

The common case for field access in ClojureScript is, I believe, interop which uses JavaScript objects as map-like data structures. My preferred solution for that case would be better conversion between JS objects and real ClojureScript maps.

Show
Stuart Sierra added a comment - - edited Back in the dark ages before Clojure 1.0, you always had to write this;
(. o (m))  ; method call
(. o f)    ; field access
Later, but before the introduction of (.m o) syntax, this was shortened to (. o x) for both methods and fields. What if we went back to the original dot operator syntax, but assume that (.m o) always means a method call:
(. o f)     ; always field access
(. o (m))   ; always method call
(.m o)      ; always method call
Raw field access is rare in Java, perhaps less so in JavaScript. But this doesn't require adding any new syntax and is consistent with what Clojure programmers are used to. The common case for field access in ClojureScript is, I believe, interop which uses JavaScript objects as map-like data structures. My preferred solution for that case would be better conversion between JS objects and real ClojureScript maps.
Hide
Benjamin Conlan added a comment -

I've just given this a quick spin and it works beautifully (at least regarding the property value vs property function syntax).

But after looking at my code I can't help but think that for the non-function case (ie json data) just using the maps symbol operator might be more desirable instead of (.-p o))

so json such as:

var jsonData = {
  "person": {
    "title" : "mr",
    "name" : {
      "firstname" : "Harry",
      "surname" : "Jones"
    }
  }
}

could be accessed like:

(:firstname (:name (:person jsonData)))

But in saying this I haven't put any thought into this statement (and of course the suggested code doesn't work anyway in the master/prop-access branches).

In coming full circle, I'm just appreciative of your work on the prop-access branch.

Show
Benjamin Conlan added a comment - I've just given this a quick spin and it works beautifully (at least regarding the property value vs property function syntax). But after looking at my code I can't help but think that for the non-function case (ie json data) just using the maps symbol operator might be more desirable instead of (.-p o)) so json such as:
var jsonData = {
  "person": {
    "title" : "mr",
    "name" : {
      "firstname" : "Harry",
      "surname" : "Jones"
    }
  }
}
could be accessed like:
(:firstname (:name (:person jsonData)))
But in saying this I haven't put any thought into this statement (and of course the suggested code doesn't work anyway in the master/prop-access branches). In coming full circle, I'm just appreciative of your work on the prop-access branch.
Hide
Fogus added a comment -

The implementation on the prop-lookup branch is functional and has associated tests. Ready for inclusion.

Show
Fogus added a comment - The implementation on the prop-lookup branch is functional and has associated tests. Ready for inclusion.

People

Vote (2)
Watch (4)

Dates

  • Created:
    Updated:
    Resolved: