This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-10
Channels
- # 100-days-of-code (2)
- # announcements (2)
- # aws (11)
- # beginners (114)
- # boot (6)
- # calva (11)
- # cider (11)
- # cljdoc (2)
- # cljs-dev (7)
- # clojure (126)
- # clojure-berlin (1)
- # clojure-conj (4)
- # clojure-dev (1)
- # clojure-germany (12)
- # clojure-italy (22)
- # clojure-spec (96)
- # clojure-uk (111)
- # clojurescript (27)
- # core-async (8)
- # cursive (17)
- # datomic (26)
- # devops (5)
- # editors (15)
- # emacs (13)
- # events (1)
- # figwheel-main (27)
- # fulcro (64)
- # hyperfiddle (29)
- # jobs (8)
- # jobs-discuss (7)
- # liberator (4)
- # off-topic (46)
- # om (9)
- # onyx (1)
- # overtone (1)
- # perun (8)
- # re-frame (28)
- # reagent (35)
- # reitit (5)
- # shadow-cljs (96)
- # spacemacs (1)
- # testing (10)
- # timbre (8)
- # tools-deps (63)
- # unrepl (1)
- # yada (10)
There's nothing wrong with using a channel to communicate between two futures, is there?
Why does (gensym)
increment the id counter by 3 when it appears to just called nextID
once?
Weird
boot.user=> (. clojure.lang.RT nextID)
3197
boot.user=> (. clojure.lang.RT nextID)
3200
boot.user=> (. clojure.lang.RT nextID)
3203
boot.user=> (. clojure.lang.RT nextID)
3206
@mfiano Probably because each REPL cycle causes two calls to it behind the scenes. RT.nextID
is called inside the compiler for anonymous functions and other things.
And Boot's REPL is Clojure code (so it's compiling and running code).
For the record, this occurs in an NREPL and clj too
Yes, so it's code that is part of the REPL itself that causing the compiler to call it.
I said Boot because you showed Boot's REPL above.
Clojure REPL itself is Clojure code.
I see. That makes sense.
You can see that within your own code, consecutive calls yield consecutive numbers
user=> (dotimes [n 10] (println (clojure.lang.RT/nextID)))
154
155
156
157
158
159
160
161
162
163
nil
user=>
hello. im a beginner of clojure. i don't know why below code is not working as i want. i want to accumulate odd items. but its result is 9.. what happened?? (let [rf (fn [acc itm] (when (odd? itm) (conj acc itm)))] (reduce rf [] (range 1 10)))
I'm not too experienced myself, but I'd imagine you have to send the accumulator if the value isn't odd, so:
(let [rf (fn [acc itm]
(if (odd? itm)
(conj acc itm)
acc))]
(reduce rf [] (range 1 10)))
Spec question: is there a way to keep s/or from adding a "path-tuple" when conforming without using s/nonconforming? I tried
(s/and (s/or :this-way string? :that-way int?)
(s/conformer second identity))
but this breaks unform (`No implementation of method: :specize* of protocol: #'clojure.spec.alpha/Specize found for class: nil`)@andrew354 thanks. will try.
hello everybody! any idea how to translate this to clojure interop?
outputParameters.add((TypeReference)
new TypeReference.StaticArrayTypeReference<StaticArray<Uint256>>(2) {});
that's quite something
yeah, as I understand it, it is creating a instance of an anonymous class that extends TypeReference.StaticArrayTypeReference abstract class and passing 2 to the constructor
I don't know what those generics make the compiler do
A question related to protocols and records. What does it mean exactly that a record satisfies a protocol.
I am looking at the documentation of satisfies?
.
Returns true if x satisfies the protocol
@viebel it means the type either implements the protocol, or the protocol is extended to that type
Is there a way to check whether all the methods of a protocol are actually supported by a type?
Why does it work this way? Is it because of difficulty of implementation or is it on purpose?
if it didn't work this way you could still manually do (extend-protocol P T (f [_] (throw (UnsupportedOperationException.))))
which is essentially what the current implementation desugars to for missing methods
so even if it forced you to implement all the methods, you'd still have no stronger guarantee
also the fact that sometimes it's a true method, sometimes it's part of the protocol "map" depending on if it was defined inline or not (not sure I am wording that correctly heh), I guess on cljs it's probably something quite different too.
I suppose one of the benefits of the current implementation is that protocols can accrete new methods w/o breaking backward compatibility
what do you mean?
no, that’s for interop
or at least that’s my initial reaction
what do you mean?
1- lib a v1 defines (defprotocol P (f [_]))
2- lib b depends on a and (extend-protocol lib_a/P T (f [_]))
3- lib a v2 extends the protocol to include (g [_])
if clojure required a type to extend all the methods of a protocol as soon as lib b updates to lib a v2, lib b would break
the current semantics mean that updating will still work, except the new features that require g
won't, but all the old stuff requring just f
still work
That makes sense!
Are there any OSGI wizards here? For some reason when I am using clojure.osgi
and add dakrone/cheshire
packaging of the osgi module fails with:
[ERROR] Manifest nl.avisi.atlascrm:atlascrm:atlassian-plugin:1.0.0-SNAPSHOT : The default package '.' is not permitted by the Import-Package syntax.
This can be caused by compile errors in Eclipse because Eclipse creates
valid class files regardless of compile errors.
The following package(s) import from the default package null
I think I nailed it down to dakrone/tigris
somehow is triggering this issue but I have no idea why..I found the issue! for some reason there is a class file in the root of the tigris jar
Congrats! OSGI can be rough for dependency resolution. I've never used it with Clojure. Would love to know how that works out...
We are running clojure in Jira actually, I currently have a repl inside of Jira which is pretty awesome
It is not really documented so if we get this working how I want I should probably write a blogpost

Jira has an OSGI container (Felix), on which you can install Java plugins
If anyone has a chance to try Clojure 1.10.0-beta2, we would love to have feedback about any issues you find with it in your project now (rather than after it’s out) :)
equally helpful is hearing that there are no issues :)
Here’s something that I see happening with beta2 but not with 1.9:
Linting failed:
ArityException Wrong number of args (2) passed to: eastwood.error-messages/format-exception
eastwood.lint/report-analyzer-exception (lint.clj:373)
eastwood.lint/report-analyzer-exception (lint.clj:369)
eastwood.lint/lint-ns (lint.clj:408)
eastwood.lint/lint-ns (lint.clj:399)
eastwood.lint/eastwood-core/fn--7649 (lint.clj:838)
eastwood.lint/eastwood-core (lint.clj:836)
eastwood.lint/eastwood-core (lint.clj:763)
eastwood.lint/eastwood (lint.clj:965)
eastwood.lint/eastwood (lint.clj:946)
eastwood.runner/-main (runner.clj:5)
eastwood.runner/-main (runner.clj:4)
clojure.lang.Var.applyTo (Var.java:705)
clojure.core/apply (core.clj:657)
clojure.main/main-opt (main.clj:386)
clojure.main/main-opt (main.clj:382)
clojure.main/main (main.clj:493)
clojure.main/main (main.clj:456)
clojure.lang.Var.applyTo (Var.java:705)
clojure.main.main (main.java:37)
Whereas == Eastwood 0.2.8 Clojure 1.9.0 JVM 1.8.0_152
works. Unfortunately I need to leave so I can’t give much more info now 😞
It’s the same file that eastwood can’t lint, compiles fine under 1.9, fails with this under 1.10-beta2.
that’s a bug in pedestal that’s been fixed - the spec for ns will catch it now but did not before https://github.com/pedestal/pedestal/commit/64b8f877590c8bb66341544728da576d8e33124f
because it’s found during macroexpansion you can’t load the file
the bug is that (ns foo (:import (the.ns.AClass)))
is invalid - in the past this was silent (and also did not have the intended effect of importing the class)
as of the latest core.specs.alpha, it will error. should be (ns foo (:import (the.ns AClass)))
or (ns foo (:import the.ns.AClass))
What does the latter form above do? Given that java classes are loaded automatically afaik? (:import the.ns.AClass)
It allows you to refer to AClass without qualification
same as all imports
that’s literally what import does
😳 I think I missed the point a little bit, possibly over confusion with [the.ns.AClass]
.
Can someone explain what is going on here?
user=> (def last+ (fnil last ""))
#'user/last+
user=> (last+ nil)
nil
@tmountain (last "")
is nil
@tmountain Am I right in assuming you're expecting the last
will not be called, and ""
will be returned instead? Short-circuiting?
(fnil f x)
Takes a function f, and returns a function that calls f, replacing
a nil first argument to f with the supplied value x.
something that will conditionally call a function given a non-nil argument, otherwise, it will return a default value
why do you need to turn nil
into ""
?
(defn get-domain
[email]
(-> (re-find #"@(.+)$" email)
(last)
(string/lower-case)))
@tmountain I would (or (some-> ..) "")
How does load-file
work alongside ns
declarations? The optimal result would be that they "merge", but I suspect that's unrealistic.
Looking through core, it would seem that you have to use require
and in-ns
. That seems like a fairly easy way to get confused.
If you use require
or load
and friends, the file name searched for and loaded is derived from the namespace name, and IIRC there is even a check after loading such a file that it ended up creating the namespace you wanted to require
throwing exception if it did not.
If you use load-file
, it is pretty much like copying and pasting the contents of the file into a REPL session.
So unless you use load-file
, you pretty much need an ns
form (or something else that creates the namespace) in the source file. Such a single file could do weird things like switching between multiple namespaces inside of it, or creating multiple namespaces, etc., but that is uncommon and prone to confusion.
Not sure if that answers your questions.
As Stuart Halloway mentioned in his REPL driven debugging talk, you can use require
without any files on disk at all, as long as you create namespaces before you require
them, so as long as you concatenate all of your Clojure namespaces in a dependency-friendly order, you could use load-file
on one big file of code and never need any other source code files at all.
I'm up to no good honestly 🙂 I'm trying to "merge" dev.clj files together. I've settled on using watchers to proxy vars from other namespaces and making it a one-liner with :refer :all
.
You can take the code for two namespaces and concatenate them into one file if you want. If there is a dependency from one on the other, the one depended-on should be first. If you ever try doing a require
from some other code for the namespaces in that file, require
can only find the file if its name corresponds to the namespace you require
d
There are tools like tools.namespace
, and the 'reloaded workflow' based on tools.namespace
, that expects the first ns
form in a source file to be the only one it needs to know about.
In case it isn't obvious, doing some of these things will likely surprise other people examining the code, and some tools they might try to use on it.
@andy.fingerhut Just to check that I understand you correctly, if I have:
(ns dev
(:require [foo.bar :refer [system]]))
(ns dev
(:require [core.async :refer [<!]]))
(defn fetch-users
[]
(<! (:users system)))
in the repl, system
, <!
and fetch-users
will be in scope?I hadn't considered the case of two ns
forms for the same namespace -- the comment I made above was for different namespace names. Thinking...
I'm happy to test it too. I would expect the above to work though particularly. I understand your original comment better now. That is a little evil, I like it 😄
user=> (ns dev (:require [clojure.pprint :refer [pprint]]))
nil
dev=> (ns dev (:require [clojure.test :refer [deftest]]))
nil
dev=> deftest
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.test/deftest, compiling:(NO_SOURCE_PATH:0:0)
dev=> pprint
#object[clojure.pprint$pprint 0x349c1daf "clojure.pprint$pprint@349c1daf"]
Seems to work. Devious!Yes, if you look at what ns
forms expand into, I think it makes sense that this would work as you are hoping.
I always assumed ns
was special, given that it requires clojure.core
and is unqualified. I'll have to explore that a little more later 🙂
As mentioned, it will surprise some people, and perhaps break some tools like tools.namespace
. I don't know about things like code analysis in Cider, Cursive, etc., but it would throw off tools.namespace things like Eastwood, perhaps in ways that would often work but sometimes break.
Please use your new knowledge of evil for good 🙂
Using load
with an ns
definition in also works, so you can have them merge. Devious!
I wonder if this would mean that tools.namespace doesn't work on clojure.core? Because that also uses load
.
I suppose tools namespace would ignore dev.not-valid.clj, but the dependencies wouldn't kick in. Quite a big price.
I think I will stick with the watcher until it breaks 🙂 But it's cool to know this works. I may revisit it if it makes sense.
tools.namespace is for determining what the dependencies are between different namespaces. About the worst you can do with these kinds of techniques is cause it to not see dependencies that actually exist in the code.
What I'm trying to do is extract all the commonality of dev.clj, the integration with system, providing reset
and test-project
and other such things, but without breaking user expectations. It's a hard balance 🙂. Trying to make it really easy to spin up a production-ready application is making it complex.
There's a novel thought 😉
I probably don't have the interest in diving into the details of what you are doing, but just a note that is probably obvious by now: if you can achieve what you want with a single ns
form per file, your approach will be more robust for tools that assume that (and more familiar to developers reading it)
@andy.fingerhut Absolutely! My end-goal is just reducing the overhead to spinning up new projects. Having it be familiar and working with tools is an important part of that 🙂
It is kind of weird the first time you look at what typical ns
forms macro-expand into. You think -- wait a minute, I could just type that sequence of forms into the REPL and it will work exactly the same as the original ns
form? Weird. There's probably a Clojure book or blog article somewhere with a title something like "Clojure: the mutable parts"