Fork me on GitHub
#clojure
<
2018-10-10
>
Dormo00:10:52

There's nothing wrong with using a channel to communicate between two futures, is there?

Michael Fiano02:10:33

Why does (gensym) increment the id counter by 3 when it appears to just called nextID once?

Michael Fiano02:10:17

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

seancorfield02:10:21

@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.

seancorfield02:10:15

And Boot's REPL is Clojure code (so it's compiling and running code).

Michael Fiano02:10:36

For the record, this occurs in an NREPL and clj too

seancorfield02:10:09

Yes, so it's code that is part of the REPL itself that causing the compiler to call it.

seancorfield02:10:24

I said Boot because you showed Boot's REPL above.

seancorfield02:10:37

Clojure REPL itself is Clojure code.

Michael Fiano02:10:57

I see. That makes sense.

seancorfield02:10:10

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=>

b411:10:00

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)))

oddsor11:10:36

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)))

👍 4
oddsor11:10:09

in your code you basically try to (conj nil 9)

b411:10:11

thank very much~!!

frenata11:10:23

could also use cond-> if you were so inclined

oddsor11:10:31

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`)

b411:10:55

@andrew354 thanks. will try.

jpmonettas12:10:29

hello everybody! any idea how to translate this to clojure interop?

outputParameters.add((TypeReference)
               new TypeReference.StaticArrayTypeReference<StaticArray<Uint256>>(2) {});

deliciousowl13:10:50

that's quite something

jpmonettas13:10:09

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

jpmonettas13:10:47

I don't know what those generics make the compiler do

Yehonathan Sharvit13:10:28

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

bronsa13:10:24

@viebel it means the type either implements the protocol, or the protocol is extended to that type

bronsa13:10:38

notably it doesn't mean that all the methods of a protocol are actually supported

Yehonathan Sharvit13:10:26

Is there a way to check whether all the methods of a protocol are actually supported by a type?

bronsa13:10:00

not in a particularly robust way, no

Yehonathan Sharvit13:10:33

Why does it work this way? Is it because of difficulty of implementation or is it on purpose?

bronsa13:10:27

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

bronsa13:10:57

so even if it forced you to implement all the methods, you'd still have no stronger guarantee

mpenet13:10:08

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.

bronsa13:10:25

@mpenet yeah but that doesn't change the semantics

bronsa13:10:23

I suppose one of the benefits of the current implementation is that protocols can accrete new methods w/o breaking backward compatibility

mpenet13:10:07

same with definterface? (I don't think I ever used it)

Alex Miller (Clojure team)13:10:29

no, that’s for interop

Alex Miller (Clojure team)13:10:55

or at least that’s my initial reaction

bronsa13:10:15

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 [_])

bronsa13:10:51

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

bronsa13:10:28

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

mitchelkuijpers13:10:51

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..

mitchelkuijpers13:10:53

I found the issue! for some reason there is a class file in the root of the tigris jar

ro613:10:43

Congrats! OSGI can be rough for dependency resolution. I've never used it with Clojure. Would love to know how that works out...

mitchelkuijpers13:10:22

We are running clojure in Jira actually, I currently have a repl inside of Jira which is pretty awesome

mitchelkuijpers13:10:50

It is not really documented so if we get this working how I want I should probably write a blogpost

mario-star 4
ro614:10:10

I'd read it! I didn't realize JIRA ran on OSGI.

mitchelkuijpers14:10:13

Jira has an OSGI container (Felix), on which you can install Java plugins

Alex Miller (Clojure team)14:10:26

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) :)

Alex Miller (Clojure team)14:10:53

equally helpful is hearing that there are no issues :)

orestis14:10:59

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)

orestis14:10:20

== Eastwood 0.2.8 Clojure 1.10.0-beta2 JVM 1.8.0_152

orestis14:10:58

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 😞

orestis14:10:11

And this may be the underlying issue:

orestis14:10:50

It’s the same file that eastwood can’t lint, compiles fine under 1.9, fails with this under 1.10-beta2.

Alex Miller (Clojure team)14:10:19

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

👍 4
Alex Miller (Clojure team)14:10:47

because it’s found during macroexpansion you can’t load the file

Alex Miller (Clojure team)14:10:12

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)

Alex Miller (Clojure team)14:10:03

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))

dominicm15:10:24

What does the latter form above do? Given that java classes are loaded automatically afaik? (:import the.ns.AClass)

Alex Miller (Clojure team)15:10:21

It allows you to refer to AClass without qualification

dominicm15:10:43

Oh, I didn't realize that also dropped the prefix. Neat!

Alex Miller (Clojure team)15:10:16

that’s literally what import does

dominicm15:10:06

😳 I think I missed the point a little bit, possibly over confusion with [the.ns.AClass].

tmountain15:10:55

Can someone explain what is going on here?

user=> (def last+ (fnil last ""))
#'user/last+
user=> (last+ nil)
nil

dominicm15:10:47

@tmountain Am I right in assuming you're expecting the last will not be called, and "" will be returned instead? Short-circuiting?

bronsa15:10:59

fnil replaces nil argumetns, it doesn't affect return values

👍 8
tmountain15:10:14

(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.

bronsa15:10:48

yes, it's doing that that says :) would you expect it to behave any differently?

tmountain15:10:22

Supplied x value is "", no?

tmountain15:10:55

And I'm providing a nil first argument to last+

bronsa15:10:11

yes, thus turning (last+ nil) into (last "")

tmountain15:10:39

is there a builtin that does what I want?

bronsa15:10:52

what do you want?

tmountain15:10:18

something that will conditionally call a function given a non-nil argument, otherwise, it will return a default value

bronsa15:10:53

no -- how would that work for mutiple args

tristefigure15:10:58

why do you need to turn nil into "" ?

tmountain15:10:26

(defn get-domain
  [email]
  (-> (re-find #"@(.+)$" email)
      (last)
      (string/lower-case)))

bronsa15:10:29

clojure.string/ is not nil-safe for example

tmountain15:10:00

was trying to be clever with re-find on how to handle re-find returning nil

bronsa15:10:17

@tmountain I would (or (some-> ..) "")

dominicm15:10:00

In some contexts you can just do some-> all the way down without the or too 🙂

tmountain15:10:12

that makes sense

tmountain15:10:50

didn't know about some-> very cool

danielneal15:10:38

it's pretty or-some

16
😂 8
dominicm19:10:22

How does load-file work alongside ns declarations? The optimal result would be that they "merge", but I suspect that's unrealistic.

dominicm19:10:34

Ah, I should be asking about load, not load-file.

dominicm19:10:17

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.

andy.fingerhut19:10:08

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.

andy.fingerhut19:10:26

If you use load-file, it is pretty much like copying and pasting the contents of the file into a REPL session.

andy.fingerhut19:10:48

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.

andy.fingerhut19:10:14

Not sure if that answers your questions.

andy.fingerhut19:10:51

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.

dominicm19:10:09

My comment about confusion was about what's in scope from the top-level ns.

dominicm19:10:16

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.

andy.fingerhut20:10:20

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 required

andy.fingerhut20:10:53

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.

andy.fingerhut20:10:35

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.

dominicm20:10:48

@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?

andy.fingerhut20:10:31

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...

dominicm20:10:38

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 😄

dominicm20:10:30

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!

andy.fingerhut20:10:03

Yes, if you look at what ns forms expand into, I think it makes sense that this would work as you are hoping.

dominicm20:10:35

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 🙂

andy.fingerhut20:10:58

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.

andy.fingerhut20:10:42

Please use your new knowledge of evil for good 🙂

dominicm20:10:43

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.

dominicm20:10:37

I suppose tools namespace would ignore dev.not-valid.clj, but the dependencies wouldn't kick in. Quite a big price.

dominicm20:10:49

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.

andy.fingerhut20:10:50

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.

dominicm20:10:16

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 😉

andy.fingerhut20:10:10

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)

dominicm20:10:12

@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 🙂

dominicm20:10:25

I will stay on the light side of the force 😄

andy.fingerhut20:10:21

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"