This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-25
Channels
- # announcements (1)
- # beginners (131)
- # cljs-dev (1)
- # clojure (178)
- # clojure-argentina (1)
- # clojure-dev (3)
- # clojure-uk (2)
- # clojuredesign-podcast (1)
- # clojurescript (16)
- # code-reviews (2)
- # core-async (2)
- # emacs (28)
- # figwheel-main (19)
- # fulcro (11)
- # kaocha (1)
- # leiningen (4)
- # music (6)
- # off-topic (2)
- # re-frame (2)
- # reitit (6)
- # rewrite-clj (9)
- # shadow-cljs (78)
- # slack-help (6)
In Simple made easy, Rich talks about "artifacts". I'm not certain what he means by that, and how it relates to constructs. These terms are a little too abstract for me to relate them to concrete things. I can't figure out what a construct is in Clojure, and what it's artifacts are. My brain goes to, e.g. map
as a construct, but what's the artifact of that? If programs/systems are artifacts, then how does that relate to the constructs?
I think we are trying to optimize for simple artifacts based on the talk, so I think this is quite important.
> There are a bunch of constructs that have complex artifacts that are very succinctly described. So what's a complex artifact? Are maven jars complex?
Afaik that was how I understood it when I saw the video but I might miss the context 😁
https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md the talk transcript might be easier? > And so if we want to look for simple things, we want to look for things that have sort of one of something. They do, they have one role. They fulfill one task or job. They're about accomplishing sort of one objective. They might be about one concept like security. So you could have a mega-jar pulling in password hashing, and csrf, and all sorts of other simple things, to create a simple thing focused on security.
https://ask.clojure.org/index.php/8462/what-are-constructs-and-artifacts-mentioned-simple-made-easy I asked 🙂
Tools.reader has log-source which attaches the source as metadata to a read value. But what if I also want to attach the line and column number?
I think I asked this (or something similar) a while ago about the edn reader, and was told I could send a patch but it should be an optional flag.
@alexmiller @andy.fingerhut is LispReader.java part of the public API?I guess not right?
You can use it through the read
or read-string
functions. What are you looking to use?
I want to add metadata to code I'm reading so when processing I can generate an error message with the correct line and col.
In what way does read not suffice?
I don't get the metadata attached of which line and col it's reading? but I can fix that myself using an indexed reader
Clojure itself uses the reader to read code, which attaches line/col metadata, and uses it to report errors
you need to pass it a LineNumberingPushbackReader while reading though
user=> (-> "(+ x 1)" java.io.StringReader. clojure.lang.LineNumberingPushbackReader. read meta)
{:line 1, :column 1}
oh that's nice! do you perhaps know if tools.reader also supports this? 'cause it's portable to CLJS too
that line/col info is only going to be added on forms basically though, so you won't see on other colls or obviously on things without meta
ah, I think then it's good that I wrote some custom code on top of tools.reader EDN which is also more safe to use
or the (let [{sym-a :a-key sym-b :b-key} m] ...)
destructuring form
yikes:
ClojureScript 1.10.520
cljs.user=> (identical? ::eof ::eof)
false
cljs.user=>
Clojure 1.10.1
user=> (identical? ::eof ::eof)
true
user=>
because ClojureScript is doing something weird?
@dominicm I've got something portable now (.cljc):
ClojureScript 1.10.520
cljs.user=> (require '[sci.impl.parser :as p] :reload)
nil
cljs.user=> (p/read-string "[{:a 1} {:b 2}]")
[{:a 1} {:b 2}]
cljs.user=> (map meta (p/read-string "[{:a 1} {:b 2}]"))
({:row 1, :col 2} {:row 1, :col 9})
cljs.user=> (map meta (p/read-string "[^:cool {:a 1} {:b 2}]"))
({:cool true, :row 1, :col 2} {:row 1, :col 16})
okay semi-serious question that I've never heard addressed. As in, I've never heard Mr. Hickey (or any other other big names in Clojure) ever even mention Python as a potential host language for Clojure. Now, I'm a very experienced Python developer -- substantially moreso than I am at Clojure -- I am very much aware of all the performance tradeoffs that would come with using Python as the host language -- but I must be overlooking something. Has there ever been a stated reason for it?
There is at least one project, pixie, with a goal of creating Clojure hosted on Python. There may be others. It was developed by Timothy Baldridge, and I have never used it, but have half a recollection that it isn't considered "complete": http://pixielang.org/
Rich Hickey wrote implementations of Clojure on Java, C#, and JavaScript. I don't think he needs to publish reasons not to write another Clojure implementation.
That makes sense to me, too. I suppose personally I think it would be an easy win, which is what surprises me. It feels like such a natural choice that I feel like the must be a reason, stated or otherwise, why it hasn't happened.
Did ClojureScript start as an official project of the core team or was it adopted and officially sanctioned side-project at some point?
having no interest in going to a significant effort is the reason most things that require significant effort do not happen 🙂
I understand that, but, it's not that much effort. They've already figured out all the hard parts
Porting the compiler to Python is trivial compared to the work that went into the language design
I mean, anyone can do it, right? It doesn't have to be the ones who wrote Clojure.
I would guess that the areas where python is novel (ai, science) haven't been of interest to rich.
lol I've done a few partial ports already, I don't have the insight or the access to finish though
the access?
(export-api node/element* node/element node/cdata node/xml-comment node/element?
prxml/sexp-as-element prxml/sexps-as-fragment event/element-nss
name/alias-uri name/parse-qname name/qname-uri
name/qname-local name/qname name/as-qname name/uri-symbol name/symbol-uri
name/uri-file name/print-uri-file-command!
process/find-xmlns process/aggregate-xmlns)
Right. The data structures that Mr. Hickey and his team have come up with are powerful, novel, and very difficult. Porting them is not a technical challenge but there's no way I'd be able to reinvent them
and I don't have access to the source code
You do
Do I?
Eclipse Public Licensed to you and the world.
Of the clojure source code?
I thought it was proprietary?
no kidding
how do you not have access to the Clojure source code? https://github.com/clojure/clojure
ClojureScript, Clojure on the CLR, Clojure on Java, all open source.
Well then the real reason is because I don't know how to look things up
Pixie linked above, also open source.
I'm wondering if another reason, though, is one of the major differences between Python and Java which is concurrency support
Well, Pixie I would have to check more carefully. I assume it is, but haven't looked at the source myself.
https://github.com/hylang/hy maybe also of interest
A Python port of Clojure would be a strange mix of ClojureScript and Clojure in terms of performance
The concurrency features have turned out to be less useful than expected. Outside of atoms.
@alexmiller hy is interesting but it's more of a toy project
(in my opinion). They didn't even bother to work out let
statements. Said it was too hard.
??? the concurrency features of Clojure?? less useful??
Do you even core.async? 😮
Perhaps he was referring to refs and transactions in dosync, which tend not to be used often.
Well the async abilities on Python are much more akin to the model in ClojureScript than Clojure, and I feel like there might be some false expectations set in terms of performance there ... that's a legitimate complaint
I don't know if that's the real deal killer or not though
Even core async, while useful, is not prevalent. I would have to check, but I'm certain that it wasn't intended to be the root approach to async. It was for wiring callbacks up.
I'd have to disagree there... core.async is wickedly powerful
The whole thing is C, but the the stack machine is consumed by a ~3000 LOC switch statement, which, while super optimized, is still a really big switch statement ...
Pixie has no python interop btw, it's a clojure like lang impl on pypy. Also abandonware
mhm. It's still just an archaeological mystery to me. ClojureScript makes perfect sense -- ported to the most widely used language. Python is a strong contender for #2 and it's fairly easy to work with, which is why I find it so interesting that it hasn't even been mentioned
I suspect the bottom line is it's just not worth it.
I think it would be worthwhile. It would open up a lot of valuable libraries in that space. I'd use it, and wrap django with a data driven api. I'd probably finally play with some ML.
@goomba I'd say the JVM is a more attractive target than Python in the enterprise but there are certainly spaces where Python seems ubiquitous so a port of Clojure to Python may be interesting to folks in those spaces.
Personally, I've worked entirely on the JVM for 22 years now so I'm not much interested in a non-JVM implementation of a language 🙂 I've learned a bunch of non-JVM languages, for self-improvement, but work has been JVM only in that time. Well, there was a bit of C++ at the beginning of those decades since that's what I'd been doing for the decade before I adopted JVM languages 🙂
Sorry if this is off-topic but, I've been trying to justify Clojure in my (largely Python) org where there's a lot of skepticism about Java. How can I demonstrate the difference b/w Java the platform (JVM, JDK...) and Java the language? How do I compare the artifacts produced by Python and Clojure as opposed to the constructs (artifacts and constructs in the "Simple made Easy" sense) Please ignore if noise.
Python (and Ruby) orgs are often biased against the JVM, not just Java, because they view it as a big, lumbering, "Enterprise" beast. You'll see a lot of people dismiss Clojure simply because of the JVM requirement -- and there are quite a few people in the Clojure community who grumble all the time about having to use the JVM. I think you'll have a nearly impossible time convincing such orgs to use Clojure since they are used to how they manage dev/test/deployment without a JVM and don't want to deal with it.
(this was also why I worked with Frege on the JVM rather than Haskell natively during one of my many "let's try to learn Haskell again" periods!)
haha that makes sense to me! I think one of the issues may be that ... well, the success of Python largely comes from the fact that it is designed to be "readable" at the expense of obfuscating a lot of the computer science behind it.
Now it would be fantastic for a lot of senior dev folks who want a sane language while taking advantage of a vast array of tools
Python 3 is a very nice language. And it's good for beginners. Do any other languages target the Python VM?
not that I'm aware of
It's excellent for beginners, and for technical non-developers like scientists and mathematicians. It can be madness for career software developers though
plus... c'mon... repl driven development
I'd trade in 75% of Python's speed for a REPL
True, but it wouldn't be necessary to compile to byte-code
Clojure's REPL -- and the ability to run it inside remote production processes -- is extremely powerful, I agree.
You could transpile and then compile that to byte-code
Who is this "You could..."? 🙂
"One" could lol.
Much like how ClojureScript running on node.js doesn't require advanced optimizations
If you wanted, you @goomba could start with the ClojureScript source and create a version that generated Python instead of JS I guess...
Well, I've been considering it @seancorfield... but I'm concerned that I'm overlooking something obvious. It's like the old joke... an economist and his friend are walking down the street. Economist walks past a 20 dollar bill. Friend says, "why didn't you pick that up?". Economist says, "That's impossible. Law of efficient markets says someone would've picked up the 20 already, therefore it doesn't exist"
I feel like if it was a good idea it would've at least been mentioned by the core team, but I feel like there's some unspoken reason they haven't even mentioned it
and it would be a bit of a fool's errand to embark on a journey that could be killed by a single member of the core team later on saying it's a bad idea 😬
I don't understand why you think it could be killed by a member of the core team saying it's a bad idea. I also see no reason why they would ever try to stop someone from doing such a thing. They would protect the trademark on the name Clojure that Rich Hickey owns, but you can call it anything else that isn't trademarked by someone else.
There is also recent work making for easier interaction between a Python engine and Clojure. Will find a link in a bit.
http://techascent.com/blog/functions-across-languages.html There is a group of Clojure enthusiasts, looking to create new libraries/code that make Clojure a better choice for machine learning / data science, by taking advantage of Python libraries more easily.
so that's why I'm asking 😬
Back in the day, in my PhD work, I started by writing a Lisp subset interpreter in Pascal, then I designed and implemented an ML-family language (which was to be the subject of my research, along with GC implementation stuff), that transpiled to Lisp in order to run on the interpreter. A couple of times since I got into Clojure back in 2010 I've toyed with the idea of resurrecting that ML-family research language with a transpiler on top of Clojure... and then I'm like "Welp, Clojure is just more fun to use so why bother porting SURE?" 🙂
the real secret reason I want this language is because I love Clojure but there's so much money in Python right now >.<
The core team won't care if folks create new implementations of Clojure targeting different VMs etc. They just won't be interested in it (beyond a general curiosity).
No one is going to kill your project. And I expect it would be a great learning experience.
the most challenging thing to port I've found so far is the for
macro. That is really, really difficult and clever
So I think everyone is encouraging you -- but also cautioning that you'll likely be the only use for it 🙂
oh, 100%
but now that I know the source code is available it might be easier! 😅
You might open clojure up to a whole new segment :) I think clojure is very enterprise.
Since for
is a macro that produces Clojure code, you could just implement the lower-level functions and that for
macro will work as-is.
yep, that's a much better idea, since they already did all the hard work
Is the clojurescript repl completely different than the clojure repl?
Different how?
like, is it written in JavaScript ...?
Go read the source code on GitHub 🙂
bwahaha... is it part of the core code or is it something else?
ClojureScript's compiler is written in Java/Clojure and runs on the JVM.
I guess that would be tools-deps code?
But there are other cljs implementations written in other languages I think? Lumo, Plank... (I don't touch cljs so I'm not familiar)
woohoo!
Those are just building on top of the same compiler and embedding them into different JavaScript runtimes.
https://github.com/clojure has over 80 repositories containing a wide variety of projects @goomba
@dominicm Cool. I wasn't sure how much of the core clj/cljs stuff they actually reused.
100%, the novelty of these tools is clever tricks with the runtime. Lumo has a start-up time boost from a v8 memory copy feature
:thinking_face: have some reading to do. Oy... I wish I could convince my employer to give me a couple of years to just focus on this
Yeah. His wife is awesome for letting him do that. May he get paid back 1000 times over.
The most familiar Clojure not written in Clojure(Script) is probably joker (to me at least)
> The use of keyword arguments has fallen in and out of fashion in the Clojure community over the years.
Trying to figure out if I should go with (create-task "something" :optional-setting true)
or (create-task "something" {:optional-setting true})
The latter is favored by some because it makes it more straightforward to call such a function after using all of Clojure's built-in machinery to create such a map, if desired.
For the implementer of such a function, it also means they can merely do merge
or assoc
to add more things to the map before calling additional functions that use the options map.
we've got a new syntactic improvement in discussion that might actually make these the same
given a function with map-destructured varargs, you could invoke it with a trailing map and get the same effect
which would remove some of the current points of friction
For what it's worth, @st3fan, I've found the former better for "public" APIs and the latter better for both public and "private" APIs, especially if you're doing a lot of map transformations, simple reason being that if I have a function signature like
(defn foo [& {:keys [a b]}] (+ a b))
;; simple to use directly but if
(foo :a 1 :b 2)
;; passing in a map isn't so pretty
(apply foo (flatten (seq {:a 1 :b 2})))
the problem becomes substantially exacerbated when you're using transducers
so, although I tend to find the keyword style a prettier API, I think the map-style argument reduces the amount of adapter code required when composing fns
@st3fan FWIW, When I took over clojure.java.jdbc
it was all keyword arguments everywhere and as I refactored it, that became a real pain to work with since top-level functions were always having to be apply
'd to other functions instead of just calling them directly. Over time, I changed all of the API to use option maps and that made the library much easier to work with (although the migration was a bit painful for everyone involved). next.jdbc
only supports option maps, not keyword arguments, because of my experience with clojure.java,jdbc
.
I honestly never understood the appeal. It’s a difference of a single keystroke (with editor paren handling).
It’s actually only ever gotten in my way. I have to constantly ask, “Is this option map a real map or a fake map?”
The appeal of not making it a map? Or the appeal of making it a map?