Fork me on GitHub
#clojure
<
2020-08-28
>
dpsutton02:08:34

is :once documented anywhere for fn*?

seancorfield04:08:38

@dpsutton It's documented somewhere because I was just reading about it the other day. I just can't remember where.

seancorfield04:08:40

Hmm, it's documented in Clojure, The Essential Reference and the section about fn* was contributed by @bronsa so maybe he knows where it officially documented?

bronsa08:08:15

AFAIK it's not documented anywhere

seancorfield04:08:23

It has a footnote linking to https://groups.google.com/g/clojure/c/FLrtjyYJdRU?pli=1 and says Rich discusses the locals clearing aspect of fn* there.

seancorfield04:08:17

(I don't see fn* mentioned there, only the general concept of locals clearing)

dpsutton04:08:25

there's a comment talking about issue 232 and that's the commit where it shows up but i can't follow the logic of the commit. https://clojure.atlassian.net/browse/CLJ-232

hiredman05:08:53

A blast from the past, that ticket is littered with former co-workers. The issue there is delays used to try and run again if derefed again and the first time threw an exception

hiredman05:08:36

And you would get npes because the once fn would clear any locals so they would be nil the second time the fn was run

hiredman05:08:26

Hmm, or not and I am misremembering

seancorfield05:08:09

Because delay wraps the ^:once fn* thing...

seancorfield05:08:33

(defmacro delay
...
  {:added "1.0"}
  [& body]
    (list 'new 'clojure.lang.Delay (list* `^{:once true} fn* [] body)))

seancorfield05:08:07

Interesting bit of history in that ticket.

seancorfield05:08:35

Testing against 1.10, it seems it all got fixed even tho' there's no indication of what the resolution was in that ticket?

seancorfield05:08:14

I didn't realize delay used the :once fn* thing until just now.

hiredman05:08:35

Yeah, the patch looks like it does what it says on the commit message https://github.com/clojure/clojure/commit/93fecbd825c26e2570f8449cd64d0df0cc520c1d it disables the code that would cleared closed over locals at the end of a function of possible, and adds that functionality to the system for clearing regular locals, which already correctly handled try/finally which was the source of the bug

seancorfield05:08:34

Ah, I missed that link (I'm not signed into JIRA on this machine).

seancorfield05:08:53

Oh, that's what Rich links in the first comment?

hiredman05:08:17

I dunno, I searched GitHub for 232

Alex Miller (Clojure team)06:08:16

CLJ-232 is the jira id, but this was part of a bulk import from the older Assembla issue tracker, so had a different id originally

seancorfield05:08:31

(which I guess was the last comment before the importer messed up the timeline?)

hiredman05:08:21

Looks like it

dpsutton05:08:55

thanks both of you 🙂

yuhan06:08:50

How do I re-throw an exception preserving the stacktrace while adding an informative message to the top?

yuhan06:08:29

(try (read-raw fname)
     (catch Exception e
       (throw (ex-info
                (str "error parsing file: \n  "
                  fname "\n  " (ex-message e))
                (into  {} (ex-data e))))))
tried something like this, but it appears as the only item in the stacktrace

Alex Miller (Clojure team)06:08:48

you can use .getStackTrace` and .setStackTrace

Alex Miller (Clojure team)07:08:18

@dpsutton @seancorfield @hiredman afaik, there is no official doc about ^:once (possibly intentionally to not encourage its use outside of core). generally most things should build upon the core stuff like lazy-seq instead

dpsutton13:08:30

its things like this: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L461

(dispatch/run
         (^:once fn* []
          (let [~@(mapcat (fn [[l sym]] [sym `(^:once fn* [] ~(vary-meta l dissoc :tag))]) crossing-env)
                f# ~(ioc/state-machine `(do ~@body) 1 [crossing-env &env] ioc/async-custom-terminators)
                state# (-> (f#)
                           (ioc/aset-all! ioc/USER-START-IDX c#
                                          ioc/BINDINGS-IDX captured-bindings#))]
            (ioc/run-state-machine-wrapped state#))))

Alex Miller (Clojure team)13:08:39

as core.async go loops basically replicate the clojure analyzer, they need to dive into this level of detail, but generally that's not something most user-level code should be doing

dpsutton14:08:47

ok. thanks for looking into it. appreciate your time 🙂

Alex Miller (Clojure team)14:08:39

but as summarized above - it's a user-level hint to the compiler to tell it this is used once and can then be cleared

👍 3
wombawomba07:08:09

What’s an easy way to split a byte array in two with a given delimiter (ala (clojure.string/split s re 2))?

scknkkrer07:08:41

Simply take with n (your delimeter), and drop with n again.

scknkkrer07:08:18

(juxt (partial take n) (partial drop n))

wombawomba07:08:26

Well, I’d need to find the delimiter first. Also, the byte array is huge and I need this to be performant.

p-himik07:08:06

That goes way past the initial requirement of it being easy. :)

😅 6
parrot 3
scknkkrer07:08:21

What kind of performance do you need ?

wombawomba07:08:06

I don’t want to make any unnecessary copies and I don’t want to iterate over the entire array

wombawomba07:08:38

also, I want two byte arrays at the end

scknkkrer07:08:53

You should need to work on Clojure Data Types and why they are simply amazing for Functional Programming.

scknkkrer07:08:10

There is no unnecessary copy or something fool-ish.

scknkkrer07:08:54

The information, shared with absolute control between derived datas…

wombawomba07:08:32

Don’t worry about that; I’m perfectly familiar with Clojure’s data types 🙂

👍 3
wombawomba07:08:46

Sometimes you still need to drop down to raw byte arrays

scknkkrer07:08:52

I think, if your requirements are beyond the performance Clojure gave, you should think about technologies like C++ or D or V.

p-himik08:08:21

Or just find a Java solution and use it as is or translate it to Clojure, either directly with interop or by using Clojure alternatives to what Java uses.

wombawomba08:08:52

Yeah I’m gonna go with that. I was just hoping there’d be a more straightforward solution :)

jdt12:08:12

I copied a project from one machine to another, and I'm having this weird problem fetching javase when using leinengen. Deleting ~/.m2 didn't fix it and I'm a bit stumped after googling for a solution. Any clues? Using Java 11 and clojure 1.10.1 for now.

Could not find artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 in central ()
Could not find artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 in clojars ()
Could not find artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 in sonatype-oss-public ()
Could not transfer artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 from/to jitpack (): NullPointerException
Could not find artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 in sonatype ()
Could not find artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 in sonatype-snapshots ()
Failed to read artifact descriptor for com.github.kenglxn.qrgen:javase:jar:2.6.0
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.

jsyrjala12:08:02

Are you sure that package exists in maven central, clojars or other places that lein is looking from

jsyrjala12:08:29

hmm, that is some other package with similar name

jsyrjala12:08:14

http://mvnrepository.com lists also packages that are not part of maven central.

jsyrjala12:08:48

try adding the mulesoft repo to :repositories in your project.clj. See https://github.com/technomancy/leiningen/blob/stable/sample.project.clj#L104

p-himik12:08:46

And the repo of QRGen itself says: "As of 2.1.0 QRGen is available from http://jitpack.io. QRGen is no longer deployed to maven central"

p-himik12:08:08

So you should probably use , as the maintainers of QRGen recommend.

jdt12:08:03

Notes: 1. I didn't have to add extra repos before, but perhaps I was making due with older compilation and m2 repo contents. 2. Adding http://jitpack.io to the :repositories doesn't seem to help, in fact, interestingly, I now get TWO NullPointerException entries for http://jitpack.io: Could not transfer artifact com.github.kenglxn.qrgen:javase:jar:2.6.0 from/to (): NullPointerException

jdt12:08:26

(after adding :repositories [["" ""]]

jdt12:08:40

Following the jitpack instructions on this page https://jitpack.io/#kenglxn/QRGen just gave me additional errors trying to load the Tag dependency.

jdt12:08:13

(selecting the leinengen instruction tab)

jsyrjala13:08:09

Here is a basic lein project that fetches the lib

jsyrjala13:08:14

(defproject foo "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url ""}
  :dependencies [[org.clojure/clojure "1.10.0"] 
                 [com.github.kenglxn.QRGen/javase "2.6.0"]]
  :repositories [["jitpack" ""]]
  :repl-options {:init-ns foo.core})

jdt13:08:18

Yeah, no such luck fo rme. http://jitpack.io (and only http://jitpack.io) is failure. My project lists only these dependencies:

[[org.clojure/clojure "1.10.1"]
   [one-time "0.7.0"]
   [com.github.kenglxn.QRGen/javase "2.6.0"]
```

jdt13:08:37

(trying your expcicit javase, otherwise it isn't explicitly in my depdenencies, and I have no idea where it's coming from)

jdt13:08:23

And clojure 1.10.1 is the only dependency in my ~/.lein/profiles.clj

jdt13:08:45

lein new app and this profile also fail:

(defproject foo "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url ""}
  :repositories [["jitpack" ""]]
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [com.github.kenglxn.QRGen/javase "2.6.0"]]
  :main ^:skip-aot foo.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

jdt13:08:33

If nobody else has the problem must be some odd thing in my env.

jdt13:08:14

Fix/workaround: this repository entry works: ["Mulesoft" "https://repository.mulesoft.org/nexus/content/repositories/public/"]

jdt13:08:29

So it appears it's the jitpack repo that's hosed.

jdt13:08:41

Except ... that it apparently works for you.

jsyrjala14:08:53

Your project.clj works also for me

jdt12:08:05

A lein repl in a non-project directory works fine.

walterl20:08:59

What's a BoF?

sogaiu20:08:55

birds of a feather? don't know the origin, but ietf has had such things: https://www.ietf.org/how/bofs/

❤️ 3
Eugen20:08:07

the meeting was about packaging clojure for Debian and the issues about that. Debian is pretty particular in the sense that all Debian packages should be buildable without internet access. You should need only depend on other packages in Debian.

Eugen20:08:15

one of the issues with packaging clojure for Debian is around reproducability. Reproducability is one of the goals of Debian https://wiki.debian.org/ReproducibleBuilds .

Eugen19:08:36

one of the big issues related to packaging is that clojure is not reproducible https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/clojure.html Some context: https://reproducible-builds.org/

andy.fingerhut20:08:36

I am not familiar with the details here, but is there any software written in Java, distributed as JAR files, that is considered reproducible?

andy.fingerhut20:08:01

It seems that the reason for non-reproducibility in the sense that caused that issue is purely due to timestamps in JAR files.

dominicm20:08:59

We had that problem in my packaging library for a while. But someone just set clj files to the minimum date, and class files to the maximum.

Eugen19:08:48

It would be great if clojure can be made to support this

Eugen19:08:56

the idea is that from the source you get the same binary regardless of which machine you build it on.

ro621:08:36

I remember a talk about debugging by defing vars inline and iterating at the REPL, but I can't find it by Googling. There may have been a library and/or editor integration to assist in creating the vars. Anyone recall the name?

seancorfield21:08:03

@robert.mather.rmm ScopeCapture I think? I just have a hotkey bound to eval (def <selection>) so that I can highlight a binding in a let and turn it into a global for debugging.

ro621:08:34

@seancorfield That's the one, thanks!

seancorfield21:08:06

I prefer not to need to add any code while I'm working, and I use REBL, so I can create a def from any value sent to the REBL and between that and my hotkey to turn let bindings into def that's pretty much all I ever need.

ro621:08:01

Cool. I haven't played with REBL yet, I mostly just abuse the EOF comment block

seancorfield21:08:59

Heh, my Rich Comment Forms are all over my code! Since I work with Atom/Chlorine, the REPL panel there is readonly so you're never tempted to type into it -- so you use RCFs instead.

dominicm21:08:26

I've written a test.check test, but I don't want to use it with clojure.test, but instead separately with it's own params. Is there a pre-written script or main I can use?

dominicm21:08:45

(I want to avoid clojure.test, because I don't want to run it with the tests all the time, as it may fail unreliably)

dominicm21:08:41

I thought clojure itself had a script for this, but I cannot find it.

dominicm21:08:51

Ah, clojure.test.generative.runner :) It would seem that test.generative is not the same as test.check. But this must be the split itself in clj.

hadils22:08:20

I am using Datomic Cloud and am trying to compile my code before deployment -- to catch any errors without incurring AWS costs. I am using @seancorfield’s excellent depstar but I don't have a -main since I am deploying Ions. Can anyone advise me how to do the compilation? thanks!

seancorfield22:08:54

@UGNMGFJG3 Do Ions not have a standard entry point?

seancorfield22:08:15

(I am not familiar with them)

hadils22:08:18

No, the entry point is in Datomic Cloud...

seancorfield22:08:37

Yeah, but how does it know what to call in your Ion code?

seancorfield22:08:59

The general answer here is: 1. create a classes folder 2. add it to your :paths in deps.edn 3. run clojure -e "(compile,'your.namespace)" to compile stuff 4. run depstar so it will JAR up the source and the classes

seancorfield22:08:13

Or if you only care about putting the source in the JAR, but want to do the compile as a sanity check, add a :compile alias that has :main-opts ["-e" "(compile,'your.namespace)"] and then clojure -A:compile and don't both putting "classes" in your :paths -- you still need the folder for compile to compile into.

hadils22:08:32

Thanks @seancorfield! I appreciate your help!

hiredman22:08:52

I think the way to do that is to still use clojure.test, but have a separate test suite, in another source directory

hadils22:08:36

@hiredman Yes, that works! Thanks!

hiredman22:08:14

I was talking to @dominicm, but cool

😂 3
dominicm22:08:53

@hiredman that's what I initially reached for, but wanting to run the generative tests by themselves when otherwise running all the tests (e.g. Cider-run-tests) brings it back to a problem.

hiredman22:08:39

does it? surely you have someway to take two commands and turn them in to one command?

hiredman22:08:05

like run-test.sh && run-generative-tests.sh

seancorfield22:08:03

@dominicm What about test selectors?

seancorfield22:08:56

Both lein test and Cognitect's test-runner have ways to select tests based on metadata...

seancorfield22:08:17

(it's about the core clojure.test / test runner approach, nothing specific to Expectations)