This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-27
Channels
- # announcements (1)
- # beginners (71)
- # braveandtrue (4)
- # cider (1)
- # cljs-dev (4)
- # cljsrn (8)
- # clojure (111)
- # clojure-italy (5)
- # clojure-spec (22)
- # clojure-uk (8)
- # clojurescript (80)
- # cryogen (14)
- # cursive (7)
- # data-science (1)
- # datomic (25)
- # dirac (1)
- # figwheel-main (4)
- # fulcro (13)
- # incanter (1)
- # off-topic (6)
- # other-languages (3)
- # pathom (11)
- # portkey (5)
- # re-frame (13)
- # reagent (3)
- # reitit (24)
- # ring-swagger (7)
- # shadow-cljs (63)
- # spacemacs (3)
- # specter (4)
- # tools-deps (9)
The clojure function repeatedly
is a function which returns a lazy sequence of explicitly side-effecting functions. As a result, chunking said sequence would violate the principle of least surprise, because more things would be evaluated than are consumed from the sequence. In the case of using something like take-while on the return values of repeatedly
, can you expect that the function will only be called enough times to complete that call, and no more?
user=> (def n (atom 0))
#'user/n
user=> (defn f [] (swap! n inc))
#'user/f
user=> (take-while (fn [q] (< q 10)) (repeatedly f))
(1 2 3 4 5 6 7 8 9)
user=> @n
10
Thanks, that does make it very clear.
The REPL is always your friend here. I didn't know for sure, so I tried it.
Yeah. It was a question that hit me while I was helping someone in another avenue and didn't have access to a repl.
Do you have a smart phone? A web browser?
fair enough, I haven't seen if http://repl.it works on mobile
There's a ClojureScript REPL app for the iPhone π
Replete.
Oh, nice, I might try that
oh, wait, that iPhone only?
looks like it. I definitely don't have an iPhone.
And the irony is Android is Java-based π
Yeah. It's too bat skummit isn't being maintained.
http://repl.it on Edge on iOS
@suskeyhose I can't test on Android but http://repl.it works on MS Edge on iOS, if that's any help π
(but I will admit that's a fairly painful way to type in Clojure and try stuff out!)
Given a macro in the form of (defmacro getclass [instance] ...)
, what's the best way to get the class of the instance given as argument? How do I resolve the argument the way a function does it?
javafx has been moved out of the sdk in java11 right ? so what do people do to create custom ui's with clojure then ... back to awt or going for platform dependent openjfx ?
@kulminaator JavaFX is available as a library for all platforms, all you need is to add a dep in Leiningen/Boot/Gradle.
i was thinking of tinkering something together that i could just distribute as a standalone app
but then it would have to bundle in the support for each platform or i should make different builds for different platforms π
or am i on the wrong track on that one
With the javapackager on the other hand, yes, you'll have to create one bundle per platform
i probably need to do some testing and background research for myself on the topic
The thing at the moment is that the OpenJFX version that's distributed as library, and as part of e.g. Oracle JDK 9/10, is, honestly, crap. At least on Linux. Good luck showing a dialog window that isn't completely weird. JavaFX 8 is fine though.
have you tried out how big the uberjar of that would be ?
That actually depends on how much of JavaFX you include. Here's the maven artifacts: https://search.maven.org/search?q=g:org.openjfx
doesn't seem too bad though
:dependencies [
[org.clojure/clojure "1.9.0"]
[org.openjfx/javafx "11" :extension "pom"]
[org.openjfx/javafx-controls "11"]
]
results in 13 megabytes jar filei was prepared for worse
but i'm not sure if this is "enough" for an app, i just tried to get the first sample that i found to work and i failed miserably
I never got it to work with adding the org.openjfx/javafx dependency, I simply added the individual parts I needed. Apparently at least Boot can't deal with that pom-only dependency, and iirc both Lein and Boot use the same library underneath for deps
javafx-base and javafx-controls should be enough to get up a window with some basic controls
thanks for the info π
Hm, now that's a bit embarassing... I'm using Clojure since 8 years now, and I still don't fully get how macros work...
It's probably a simple, silly thing, but could someone look over this?
clojure
(defmacro connect
"This macro is used to make use of functional interfaces."
[instance method args & code]
`(let [functional-method# (first (clojure.lang.Reflector/getMethods ~(class instance) 1 ~(str "set" (camelcase (name method))) false))
functional-para# (first (.getParameterTypes ^Method functional-method#))]
(~(symbol (str ".set" (camelcase (name method)))) ~instance
`(proxy [~functional-para#] []
(~(symbol (.getName functional-method#)) ~~args
~~@code)))))
The problem seems to be at ~~args
. It somehow resolves that and reports it can't resolve the symbol, but it's meant to be included verbatim into proxy.
~'~args
Hm, alright. Now I'm getting an NPE, but that probably has a different reason... back to debugging
I've been using this https://github.com/TristeFigure/shuriken#macroexpand-do every now and then when developing macros
forgot to tell you about that part hehe. Can you pm a copy-paste of the bug por favor ?
"java.lang.RuntimeException - Unable to resolve symbol: setOnAction in this context clojure.lang.Util.runtimeException (Util.java:221)"
Thanks, the bug is fixed !
Also, macroexpand-n seems to be broken, as in it, I guess, first does all the macroexpands, and then starts to print the expansions. So as soon as there's any kind of error in the macro, it becomes useless. macroexpand-do on the other hand prints straight away.
eeeehh�
user=> :9f22
:9f22
user=> :tag/9f22
Syntax error reading source at (2:0).
Invalid token: :tag/9f22
When I type it in a REPL in the user
namespace, I get back :user/9f22
I believe while that behavior violates the official docs about what is allowed in a keyword (i.e. it leads with a digit), the Clojure/Java implementation does not give an error for it, partly because of the extra compute time required to check it, and now from years of allowing it, partly because of backward compatibility of not breaking library code that relies on it.
Oh, but reading back now, yeah, a little incongruous that :user/9f22
is an error on attempting to read it.
"Trying things that are not supported in the official docs" combined with "some things are allowed by the implementation despite not being officially supported" are colliding here @schmee
I'd recommend strings for storing things like "9f22" especially if you don't need namespaces.
Sounds like a good idea
I found the ticket I was thinking of where they did in 2013 temporarily tighten up the reader to disallow all keywords starting with a digit, then reverted it after it broke things they didn't want to break: https://dev.clojure.org/jira/browse/CLJ-1252
I remember that! One of the libraries I worked with a lot broke when they tightened that screw...
I'm trying to run a socket repl through the clojure cli, how do I enable the jvm-opts from a deps.edn such as this one: https://github.com/seancorfield/dot-clojure/blob/master/deps.edn#L54
hmm
clj -A:socket
Exception in thread "main" java.io.FileNotFoundException: -A:socket (No such file or directory)
...
The dep-opts are used to build the java-opts and classpath:
-Jopt Pass opt through in java_opts, ex: -J-Xmx512m
-Ralias... Concatenated resolve-deps aliases, ex: -R:bench:1.9
-Calias... Concatenated make-classpath aliases, ex: -C:dev
-Spath Compute classpath and echo to stdout only
-Srepro Use only the local deps.edn (ignore other config files)
-Sforce Force recomputation of the classpath (don't use the cache)
-Spom Generate (or update an existing) pom.xml with deps and paths
-Sverbose Print important path info to console
...
nothing about -A there-A
is kind of the "do what I expect" flag, where as otherwise you have to build up what you want using the other flags
but your older version also didn't have -O
which is the flag you would have needed without -A
any ideas why this is the case?
user=> (= (java.util.ArrayList.) [])
true
user=> (= #{(java.util.ArrayList.)} #{[]})
false
because mutable Java collections still use Java .hashCode
as a return value for (hash x)
but as of Clojure 1.6 and newer, immutable Clojure collections use a modified hash function for (hash x)
that a close associate of your helped develop π
I see
This article has some gotchas and details on Clojure =
and hash
that gives a link to a Clojure ticket raise for this: https://github.com/jafingerhut/thalia/blob/master/doc/other-topics/equality.md
The recommendation I've heard (and pass on there) is to avoid using mutable Java collections inside of Clojure collections.
according to that,
> Clojure's = is true when called with two collections, if:
> Both arguments are sets (including Java sets implementing java.util.Set), with =
elements, ignoring order.
which is true here
Ah, and here is the ticket it eventually references: https://dev.clojure.org/jira/browse/CLJ-1372
Yes, that is the short summary. Does it also have a bullet list item that mentions the exception about mutable Java collections? If not, I can add one.
and those are not "official" docs -- just info collected via OCD
I don't see it until much later in the doc, except for a vague hint in the first paragraph. I can make that more explicit.
I will add it as the first bullet under "Exceptions, and possible surprises"
That would be nice. Not sure how best to word it, maybe "When using non-Clojure collections as keys in a Clojure hash-based collection (map or set), it won't appear equal to a similar collection with Clojure counterparts, due to the difference in hashing behavior. (link to ticket)"
Basically, when hash
was improved to avoid some bad performance cases due to hash collisions when you use things like short vectors of integers as set elements or hash keys, hash
was not changed to add explicit updates for all java.util.Set, java.util.List, etc. classes, too, primarily I believe because it was not easy to see how to do so without making the performance of hash
potentially much worse when called for all types.
Yeah, there is a whole subsection on it later in the doc, but it belongs early and more prominently.
Yep, I do recall those changes, but didn't realize until now that it adversely affected Java collections
It didn't change the hash
return value for Java collections, but that is the root of the behavior you are seeing (that it didn't)
And of course, even though I have edited that document at least 5 times, there is still room for improvement π
> avoid using mutable Java collections inside of Clojure collections you're right, but in this particular use case I'm trying to write generative tests for an EDN serializer I've written, which has special behavior for Java collections, coercing them into Clojure collections, and I'm having trouble testing equality during the codec roundtrip.
Sounds like the code you are writing to coerce Java collections to Clojure collections will help other people using the lib avoid this issue, but you get to face it head on.
exactly
Clojure's equality semantics are super magical for the most part, I think the only times I'm ever frustrated by them is writing test cases. Typically, the system under test works perfectly fine but the test cases themselves get false negatives. The main offenders are Java collections, regexes, and NaN. π
Given the lib you are writing, you may want to familiarize yourself with other corner cases mentioned in that doc. And if you find anything that isn't listed there, please let me know -- I would like to add it.
e.g. open an issue on the repo
OK, I will do that if I find more interesting cases.
thanks for the tips!
you are welcome
bullet added as first in the "Exceptions and possible surprises" list, with wording similar to what you suggested.