Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Writing code that targets multiple Clojure platforms currently results in large amounts of almost-but-not-quite-the-same code, resulting in  code code duplication.

For example:


;; euclidean-vector.clj 
  (extend-protocol EuclideanVector
     clojure.lang.PersistentVector
     ...
     (magnitude [this]
         (Math/sqrt (reduce + (map #(Math/pow % 2) this))))
     ...)
 
;; euclidean-vector.cljs 
(extend-protocol EuclideanVector
   cljs.core.PersistentVector
   ...
   (magnitude [this]
       (Math/sqrt (reduce + (map #(Math/pow % 2) this))))
   ...)

...

(defn sqrt [x]
  (feature-cond
    :js (Math/sqrt x)
    :jvm (java.lang.Math/sqrt x)
    :clr (System.Math/Sqrt x)))

Benefits:

  • Solves problems 1, 2, 3 & 4
  • No modification to the core language No or conceptual leaps

Tradeoffs:

  • Would break if used inside existing macros that rewrite or inspect their source, since they would see the 'feature-cond' expression rather than the evaluated platform-specific expression.
  • Can't extend code you don't own
Rewriting macro

Put feature data in a global dynamic var.

...

  • No modification to the core language
  • No conceptual leaps

Tradeoffs:

  • Limited to symbol replacement.
Feature expressions

Read-time eval

New macro phase

 Compiler reads metadata

...

Global Source rewriting

Leave it to tools / do nothing

Considerations

Granularity

...

Using the proposal, is it possible to reflect/introspect on the parsed value to see where it came from and verify that it was the result of a feature expression? See Kevin Downey's comment: http://dev.clojure.org/display/design/Feature+Expressions?focusedCommentId=5243068#comment-5243068