--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev...@googlegroups.com.
To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev.
For more options, visit https://groups.google.com/d/optout.
Hi all,
I was a little surprised and unenthused to learn recently from Alex Miller [1] that Feature Expressions [2] are expected in 1.7.I was surprised because I have yet to understand why they're needed, after using Clojure and ClojureScript together for a long time, and after reading the design document. I was unenthused because the only thing clear to me about them is that they introduce syntactic complexity, which is probably the last thing I'd want for my favorite Lisp, and language.My hope for any change to the syntax of Clojure would be that behind it are strong advocates with measured arguments, and I suspect feature expressions have both, I just don't know them yet. With or without feature expressions Clojure is so awesome I will of course defer to Alex and Rich/Cognitect as steward and benefactor, but I like to think that by registering my disagreement I help deliver on the reason Clojure was open-sourced in the first place :-)What I don't understand is: what do feature expressions give us that cljx-like tools don't, when combined with the things - like system properties and macros - that platforms and languages already do? The design page enumerates how various problems can be solved with both cljx and feature expressions, but speaks little to things only solved by the presented design. This leads to my feeling of "they're happening just because, here's exactly how."
The complexity I see them introducing is very large, compared to the benefits I can understand them bringing, which seem small. First, it's another way to mix read and run time. Because feature expressions (like data readers) use syntax instead of S-expr to convey sequence, they also introduce new questions of precedence, like the one Herwig Hochleitner raises [3]. Precedence conundrums - in Lisp. Seems like a bad sign, no?
Colin Fleming explores a additional implications in the next comment [4]. In essence, read-time conditionals make Clojure code more difficult for tools to understand without running. One advantage of cljx-style preprocessing is that tooling doesn't need to care about understanding how to recognize features for other platforms, because none of the code being read is necessarily being run at pre-processing time. Transformations are "by a 3rd party". With feature expressions, tools need to at least recognize the feature/platform boundaries, and it's not clear this is possible in all cases.
As for the runtime *features* component that cljx doesn't offer - are there examples of this being used to solve problems that a combination of system properties and macros can't? While Clojure is now written for multiple platforms, there is little variation per platform - certainly not as much variation as once existed between competing, proprietary Common Lisp implementations in the 80s, which I think was the original use case. Clojure and its family of open, noncompeting implementations, divided between platforms for platform affordances, not competing language feature/implementations, seems like a totally different use case.
I really like that Clojure's relative syntactic and evaluation simplicity give tools and editors a lot of room to innovate. As co-author and maintainer of various build tools and multi-platform projects, I am afraid that feature expressions will ultimately remove flexibility and complicate my life instead of empowering me to go further and faster. I could also be totally wrong and my fear completely unfounded.
It seems like something that most people are comfortable enough with (or unfamiliar enough with the problem) to not object to, but that could have a longer-term, undoable, highly detrimental impact on our emerging ecosystem of tools. This is as strongly as I can put my argument, because my burden - to produce concrete examples of tools that are impossible to make if we do this - is also impossible. I just have a feeling. That, and I don't see anything close to simple about the proposal, but that is an even purer matter of taste.
--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev...@googlegroups.com.
To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev.
For more options, visit https://groups.google.com/d/optout.
I am a little surprised that people want feature expressions instead of either platform-agnostic libraries or more core-blessed abstractions to make code cross platform.
Long before cljx pedestal-app had a "platform" namespace of functions which was simply reimplemented some common functions (e.g., for string manipulation, dates, etc) in both clojure and clojurescript. I think Peter Taoussanis's "encore" library has a similar purpose (but of course it uses cljx and has a lot more extra stuff in it).
However, I don't think that feature expressions are mutually exclusive of language abstractions or library assistance to make code portable.
--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev+unsubscribe@googlegroups.com.
The powerful tooling of the beforetimes leveraged code-is-data and minimized the importance of files. In Clojure we have the opposite: yes, we're stuck with files as the canonical representation but Clojure source files can't even be read by the reader without an evaluation context.
For example `::foo/bar` requires filthy hacks to sniff namespace declarations and the evaluation semantic of collection literals like `#{0 0}` vs `(hash-set 0 0)` and `{:x}` vs `(hash-map :x)` complect reading and evaluation. And don't even get me started on tagged literals :)
Combine these complexities with mutable namespaces and expression-at-a-time evaluation and it's a catch-22 situation for tooling, because it's very difficult to safely evaluate so you can read.
Many good points made by people in this thread. I largely agree with Micha, including gratitude for the people improving Clojure. Let me add my 3 cents.1. IMHO a solution to the problem feature expressions is targeting should only happen if there is a solid design supported by the community. The downsides of getting it wrong are big. The cost of waiting, not that big.
2. Source cool tooling is a bit of a PITA as others have mentioned. While I agree we shouldn't be making the problem worse, a conservative approach to evolving Clojure syntax doesn't address the root problems.
3. The proposed design.Its hard to look at cljx and see something other than a hack. Fine for a library filling a void, glad it exists, but not something I'm happy with in core.
Its putting the construct, and a particular form of programmer convenience, above the artifact. Its certainly not making anything simpler.Even wrt programmer convenience, it has major problems. It sucks to read. The more it is used in a project, the more unreadable it gets. I challenge people look at some cljx heavy code and tell me it looks clean.
Perhaps in tandem with some library abstractions for common areas, we could deliver enough of these to forestall needing feature expressions at all or scale it back significantly. I will do some more analysis.
On 11/15/14 12:39, Alex Miller wrote:
Can you be specific what you are referring to by "Tim's proposal to
divide host-dependent code among multiple conditionally loaded files"?
After rereading the design wiki you're right this proposal doesn't occur cleanly/clearly on the wiki. I'll fix that in a bit.
The idea is that "we" introduce a ".cljc" or some other "common" clojure file extension. These "common" files may contain no host interop forms, and as such are expected to be portable across all Clojure platforms with zero change. This covers the common case of Clojure code that I've seen where application & library code is built in Clojure for Clojure.
Code with host interop is then segregated into platform specific namespaces. So for CLJS we have ".cljs", for CLJCLR perhaps ".cljn" and for CLJ we just keep ".clj".
On a given platform, load first attempts to read and compile _only_ the target path as a platform file for the current platform. If that file does not exist, then load falls back to the "common" file extension and finally fails to load.
> What does "platform postfixed files" mean exactly?
src/foo/core.cljc <- common
src/foo/core.cljs <- CLJS specific
src/foo/core.clj <- CLJ specific
src/foo/core.cljn <- CLJCLR specific
So (load "src/foo/core") X not in #{"clj" "cljs" "cljclr"} would hit src/foo/core.clj. Otherwise the platform file is hit.
Note that this provides the implicit expectation that all existing Clojure code was written targeting CLJ which is a correct if portability wise minimal default.
We walked a bit down the design path for a library aliasing mechanism
but Rich ultimately decided that it made loading more complicated
without giving you anything you didn't already have if you just set up
your classpath properly.
That presumes you have a merge based class or resource path rather than a shared source tree.
Strictly you're right, if you had
src/clj/...
src/cljs/...
src/cljc/...
src/cljn/...
and then used the .clj file extension everwhere that would indeed buy you the same kind of code partition I'm talking about. Now this becomes a usability and tooling issue rather than a question of language extension.
It sounds like this path ignores the (fairly common) case of namespaces
that have *almost* but not exactly, the same implementation on different
platforms.
Yes and no. If you are within epsilon of having identical code across multiple platforms, it is my opinion (and I will stress opinion as I have no use study to back this up) that it should be trivial to factor such code so as to isolate platform interop code into platform specific functions which become candidates for a host file providing a shared host interface across platforms.
involvement in this role and it was ultimately put off. It's a visible issue in every feature/pain poll. It slows down dev on things like core.async. I do not want to wait; I want to actively solve the problem.
;; .cljc(ns my-app.util)(defn some-helper [it]it)(definterop format-date [date]);; .clj(ns my-app.util(:import [java.time.format DateTimeFormatter])(:include [some-helper]))(defn format-date [date](some-helper (.format DateTimeFormatter/ISO date)));; .cljs(ns my-app.util(:import [goog.i18n.DateTimeFormat])(:include [some-helper]))(def date-format-iso(goog.i18n.DateTimeFormat. "yyyy-MM-dd"))(def format-date [date](some-helper (.format date-format-iso date)))
Hi all,I was a little surprised and unenthused to learn recently from Alex Miller [1] that Feature Expressions [2] are expected in 1.7.
I was surprised because I have yet to understand why they're needed, after using Clojure and ClojureScript together for a long time, and after reading the design document. I was unenthused because the only thing clear to me about them is that they introduce syntactic complexity, which is probably the last thing I'd want for my favorite Lisp, and language.
My hope for any change to the syntax of Clojure would be that behind it are strong advocates with measured arguments, and I suspect feature expressions have both, I just don't know them yet. With or without feature expressions Clojure is so awesome I will of course defer to Alex and Rich/Cognitect as steward and benefactor, but I like to think that by registering my disagreement I help deliver on the reason Clojure was open-sourced in the first place :-)
What I don't understand is: what do feature expressions give us that cljx-like tools don't, when combined with the things - like system properties and macros - that platforms and languages already do? The design page enumerates how various problems can be solved with both cljx and feature expressions, but speaks little to things only solved by the presented design. This leads to my feeling of "they're happening just because, here's exactly how."
The complexity I see them introducing is very large, compared to the benefits I can understand them bringing, which seem small. First, it's another way to mix read and run time. Because feature expressions (like data readers) use syntax instead of S-expr to convey sequence, they also introduce new questions of precedence, like the one Herwig Hochleitner raises [3]. Precedence conundrums - in Lisp. Seems like a bad sign, no?
Colin Fleming explores a additional implications in the next comment [4]. In essence, read-time conditionals make Clojure code more difficult for tools to understand without running. One advantage of cljx-style preprocessing is that tooling doesn't need to care about understanding how to recognize features for other platforms, because none of the code being read is necessarily being run at pre-processing time. Transformations are "by a 3rd party". With feature expressions, tools need to at least recognize the feature/platform boundaries, and it's not clear this is possible in all cases.
As for the runtime *features* component that cljx doesn't offer - are there examples of this being used to solve problems that a combination of system properties and macros can't? While Clojure is now written for multiple platforms, there is little variation per platform - certainly not as much variation as once existed between competing, proprietary Common Lisp implementations in the 80s, which I think was the original use case. Clojure and its family of open, noncompeting implementations, divided between platforms for platform affordances, not competing language feature/implementations, seems like a totally different use case.
I really like that Clojure's relative syntactic and evaluation simplicity give tools and editors a lot of room to innovate. As co-author and maintainer of various build tools and multi-platform projects, I am afraid that feature expressions will ultimately remove flexibility and complicate my life instead of empowering me to go further and faster. I could also be totally wrong and my fear completely unfounded.
Alan
What I don't understand is: what do feature expressions give us that cljx-like tools don't, when combined with the things - like system properties and macros - that platforms and languages already do? The design page enumerates how various problems can be solved with both cljx and feature expressions, but speaks little to things only solved by the presented design. This leads to my feeling of "they're happening just because, here's exactly how."
The complexity I see them introducing is very large, compared to the benefits I can understand them bringing, which seem small. First, it's another way to mix read and run time. Because feature expressions (like data readers) use syntax instead of S-expr to convey sequence, they also introduce new questions of precedence, like the one Herwig Hochleitner raises [3]. Precedence conundrums - in Lisp. Seems like a bad sign, no?