I agree with all of that. If you are extracting and writing jvm, py, clr, cljs interop as a means to enable portability, then you are effectively writing extensions to the core clojure platform libs.
I.e providing a base, in a similar way that, for example, clojure.string extends common string operations across platforms. It is the capability of the core platform that enables portability. It's a double edged sword though and there are certainly many cases where it does not make sense. I think that there are a couple of areas where core extensions for portability might be useful. I have used this for cljs and jvm with: 1. math, as above 2. string -> numeric parsing, (although the reader can be used too) 3. logging - but only in simple cases for debugging. 4. exceptions - but only in very limited form I find that beyond these - I can pretty much get away with completely generic code. The only challenge then is how to get the platform specific and generic files to the relevant compiler in a clean and standard, rather than ad-hoc manner. (lein cljs-build et al) Dave On Sunday, 15 April 2012 02:42:27 UTC+10, Kevin Lynagh wrote: > > I have no idea what, if anything, Clojure the language(s) *should* do > about this issue, but I can explain the reasoning behind CLJX. > > CLJX uses the reader to statically analyze toplevel forms in a file > and generate new ones according to declarative rewrite rules. > The motivating use case was to make the C2 data visualization library > work on both Clojure and ClojureScript. > > C2's source is spit across > > src/cljx ;;most of the code > src/clj ;;Clojure-specific > src/cljs ;;ClojureScript-specific (i.e., DOM manipulation code) > > and most of the cljx files only have one or two platform metadata > annotations. > Any namespace which uses macros has two ns forms to accomidate > ClojureScript's :use-macros syntax. > > I explicitly wanted a solution where code for different platforms > would be in the same file because it eases the burden on the > maintainer to ensure consistency between implementations. > That makes sense when the differing implementations are very small: > > (defn ^:clj log10 [x] (Math/log10 x)) > (defn ^:cljs log10 [x] (/ (.log js/Math x) > (.-LN10 js/Math))) > > and I agree with Dave in that it could get unwieldy fast if you try to > mix larger implementation-specific functions together. > > If I wanted to write something cross-platform, I'd start by defining > the needed foundation (beyond what is provided by the Clojure > runtimes, e.g., "str"), write those platform-specific functions > completely separate from each other, and then write the shared Clojure > code that implements the bulk of the functionality. > The CLJX solution works nicely with C2 because 90% of C2 code > manipulates Clojure data structures only. > There are relatively few implementation details that need to be > papered over. > > Clojure was designed to be a hosted language, and it's very easy to > reach out to the underlying platform. > If you don't need to do that and can get by with Clojure/core---great, > your code will be portable. > However, if you use libraries and facilites native to the host > platform, then you're not writing Clojure so much as you are writing > Clojure+Java or Clojure+JavaScript. > If that's the case, just have separate projects with a shared spec or > test suite and not worry about mashing it all together with compiler > or pre-processing tricks. > > On Apr 13, 10:06 am, Aaron <aaroncrael...@gmail.com> wrote: > > I posed this question briefly in this post here: > https://groups.google.com/d/msg/clojure/K65Va0rCCls/Ow5bAJ_YTGIJ. In > this > > real world example of porting Korma over to ClojureCLR, I encountered > the > > following things: > > > > - One namespace which handled JDBC interaction needed to be rewritten > > completely to target ADO.NET > > - Another namespace required a few minor changes, only one of these > > (changing .indexOf to IndexOf) was platform specific > > > > Korma is a library that is probably exceptional in its avoidance of > > platform specific features in most namespaces. Porting something like > > swank would not have been so easy. In general, I would say that for > this > > library, I would prefer to use the platform specific folder approach - > i.e > > having two namespaces korma.platform.db and korma.platform.util in > src-jvm/ > > and src-clr/ folders. Then there could be a CLR specific project.clj > > (maybe project.clr.clj) sitting next to the JVM project.clj (and > eventually > > maybe a project.py.clj). Each project.clj would reference the correct > > platform specific folder in addition to the shared src/ folder. Just > off > > the top of my head, the reasons for supporting this approach are: > > > > - It forces the developer to isolate platform specific code into > > manageable units that can be 1) more easily ported to another > platform, 2) > > easily maintained, and 3) tested in isolation for compatibility > > - There is no need for one clojure dialect to know about the > whereabouts > > or contents of code for another dialect. This would seem to be > unnecessary > > overhead. > > > > While I can see why it might be nice to be able to quickly add some > > metadata to distinguish this platform specific code while keeping > > everything in one file, as other have mentioned, I would encourage > people > > to think about the downsides of this. Say, I had just taking korma.db > and > > put some conditionally compiled CLR code alongside the JVM code. The > file > > doubles in size. Would I then want the py team to do the same? Also, > for > > the one .indexOf -> IndexOf change, say there are little changes like > that > > all over the place. Would a team adding a new port want to go through > the > > whole source tree and find every instance of this? Without modifying > the > > clojure compilers we have now, the platform specific directory approach > > will work and is probably cleaner. It just requires team consensus on > > adopting this approach. > > > > One thing, I would propose is adding some build tool awareness of this > so > > that maybe an NLein or PyLein could use the same project.clj and just > see > > :platform-clr, :platform-py, :platform-jvm attributes. Or this could be > > done by having a shared project.shared.clj included by each platform > > specific project file. These types of approaches might be simpler and > more > > maintainable in the long run. > > > > Aaron > > > > > > > > > > > > > > > > On Thursday, April 12, 2012 12:56:59 PM UTC-4, tbc++ wrote: > > > > > I've been thinking lately how to seamlessly merge clojure-py and > > > clojure-jvm code in the same packages. This is something I know has > > > been discussed in the past, but I'm just looking for > > > ideas/brainstorming on how we can solve this problem. > > > > > Let's begin by explaining the problem. Let's assume that my project > > > needs a platform specific way to convert a int to a string: > > > > > On clojure-jvm: > > > > > (defn to-string [i] (.toString Integer i)) > > > > > On clojure-py: > > > > > (defn to-string [i] (py/str i)) > > > > > On Clojurescript: > > > > > (defn to-string [i] (.toString i)) > > > > > We could do this inline (inside a common .clj file): > > > > > (for-platform "jvm" > > > (defn to-string [i] (.toString Integer i)) > > > "python" > > > (defn to-string [i] (py/str i)) > > > "js" > > > (defn to-string [i] (.toString i))) > > > > > But this gets ugly real fast. > > > > > My idea, would be to provide some sort of hook to the compiler, that > > > would be cross-platform. The compiler, when looking for a namespace, > > > would find all files in a given folder that match the required > > > namespace: > > > > > /test/to_string.clj > > > /test/to_string.cljpy > > > /test/to_string.cljs > > > /test/to_string.cljclr > > > > > These function hooks would then pick the best entry based on the > > > extension, defaulting to .clj if no better option exists. Since these > > > functions could be composable it would be possible to also dispatch on > > > platform versions: > > > > > /test/to_string.cljpy26 ; Python 2.6 code > > > /test/to_string.clj7 ; JVM 7 code > > > > > It seems to me that this would be a very clean way to allow clojure > > > programs to be cross-platform. The side-effect is that it would force > > > non-standard code out into separate namespaces where they can be > > > easily maintained. If someone wanted to port the project to a new > > > platform, he would need only to find existing platform overrides, and > > > create new entries. > > > > > Thoughts? > > > > > Timothy Baldridge -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en