Fork me on GitHub
#clojure
<
2020-01-22
>
Setzer2209:01:52

I have a couple questions about the package cache with tools.deps: • Is there a way I could copy a cache folder to allow for building on another machine without internet access? • Are package caches per-machine or per-project? Is there a way to re-use the same package cache for several projects (if that's not already the case by default)?

Setzer2210:01:51

I've done some experimentation and it seems I can at least partially answer myself: The cache folder for maven packages does not change, it's always $HOME/.m2 (the default for maven). There is also .cpcache folder, which I assume is for other kinds of deps (git?) but I was mostly interested in mvn dependencies.

delaguardo10:01:27

with tools.deps there are two conceptual entities: deps cache and artifacts. Deps cache is per-project cache of computed classpaths. Artifacts stored separately: normal maven jars - in globally configured maven repository, git-based deps in $HOME/.gitlibs

noisesmith17:01:16

.cpcache doesn't cache the deps themselves, just the computed classpaths that point to the local cache of the deps (in m2 etc.)

noisesmith17:01:44

it speeds up startup by allowing reuse of the classpath instead of computing it if the deps have not changed

hindol10:01:42

Hi, in Clojure, are transducers (`eduction/sequence`) also chunked? Looking at the source, it seems yes, but double checking.

petterik21:01:55

eduction & sequence sequences (i.e. when used as a seq ) are not chunked. https://clojure.atlassian.net/browse/CLJ-2356

👍 4
Hi11:01:45

Hello, I am reading this article http://www.learningclojure.com/2013/02/clojures-reader-is-unsafe.html About danger of default reader. What is the best way to do the opposite thing - serialize data structures into a string?

vlaaad11:01:54

depends on what you want exactly, @feikas

Hi11:01:32

I guess pr-str is what I want, but asking just in case if this one also is safe.

vlaaad11:01:52

what do you mean by safe?

vlaaad11:01:45

there is also *print-dup* that allows producing "unsafe-to-read" forms:

(binding [*print-dup* true] 
  (pr-str [String #'clojure.core/inc]))
"[#=java.lang.String #=(var clojure.core/inc)]"

4
zilti11:01:28

So, lazy-seqs... How do I treat them correctly? I thought map is lazy. But calling map on a lazy-seq puts me into an infinite loop it seems...

zilti11:01:20

No doall or anything alike. Just using seq? to see if it is a sequence, then map, and the caller calls take 3 on the result.

Ivan Koz11:01:24

well because printing will try to "realize" resulting sequence

zilti11:01:43

I don't call print anywhere though. Just using the result of (take 3 (function-that-maps lazy-seq-thing)) in a test

zilti11:01:10

A few lines up, (take 3 lazy-seq-thing) works perfectly as expected

Ivan Koz11:01:29

what's your function

Ivan Koz11:01:16

(take 3 (map (partial * 2) (iterate inc 0)))
=> (0 2 4)

zilti11:01:41

(defn mainblock-inputs-gen [{:keys [input url] :as state} parse-fn & {:keys [fetch-fn]}]
  (cond
    (and (nil? input) (or (keyword? url) (string? url)))
    [(mainblock-url-fetching parse-fn url state)]

    (and (nil? input) (or (coll? url) (seq? url)))
    (map #(mainblock-url-fetching parse-fn % state) url)

    (string? input)
    [(parse-fn input)]

    (coll? input)
    input

    :else
    [input]))
with url being the lazy sequence.

zilti11:01:26

...and input being nil in this example of course.

p-himik12:01:11

If url is a lazy seq of lazy seqs of lazy seqs ad infinitum, it will be an endless recursion.

p-himik12:01:47

Oh, disregard that - I read mainblock-url-fetching as mainblock-inputs-gen.

Ivan Koz12:01:23

yeah unless map is being realized it shouldnt evaluate

p-himik12:01:29

Are you sure that's the infinite loop though and not just mainblock-url-fetching never returning?

p-himik12:01:51

Or maybe parse-fn.

zilti12:01:46

Yes, in the test, I've set mainblock-url-fetching to (fn [parse-fn url _] (parse-fn url)) and parse-fn to identity

Ivan Koz12:01:06

so you basically calling identity on entire url lazy-seq?

p-himik12:01:43

Well, I just tested it with url being (range) and just called (take 3 ...) on it. It works perfectly, no infinite loops.

p-himik12:01:06

user=> (take 3 (mainblock-inputs-gen {:url (range)} identity))
(0 1 2)

zilti12:01:11

No, identity gets called inside the mainblock-url-fetching which gets called inside the map

Ivan Koz12:01:12

looks like it's not your map, but rather you trying to put mainblock-url-fetching into a vector

zilti12:01:15

And yes, when I use (iterate inc 1) as a lazy seq instead, it works...

Ivan Koz12:01:28

so mainblock-url-fetching is effectively (identity url) according to your description

p-himik12:01:57

Must be your url generation then. Can you (take 3 url) without halting?

zilti12:01:23

@p-himik yes, I can, that's what I do in a test that runs right before this one

Ivan Koz12:01:56

now replace [(mainblock-url-fetching parse-fn url state)] by (mainblock-url-fetching parse-fn url state)

Ivan Koz12:01:12

and call take 3 on result of mainblock-inputs-gen

p-himik12:01:55

@nxtk What would that solve? In that block, url is a scalar.

zilti12:01:59

Hmmm I think I found the problem... The function generating the lazy sequence returns a map containing the lazy seq, not the lazy seq directly...

Ivan Koz12:01:05

@p-himik oh i guess you are right

Setzer2213:01:11

is there a way to include a local jar file with tools deps?

Alex Miller (Clojure team)13:01:48

Yes, use a coordinate like {:local/root “/path/to.jar”}

Setzer2213:01:19

Thanks! 👍 I thought this only worked with other projects using deps.edn

paul93122415:01:00

Hello guys, anyone messed around with https://github.com/FundingCircle/jackdaw ? I installed confluent CLI and start the repl. then loaded the pipe example

user=> (ns pipe)
nil
pipe=> (confluent/start)
Syntax error compiling at (/private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/form-init10224179169549008804.clj:1:1).
No such namespace: confluent
What do I miss?

kelveden16:01:40

There's actually a separate #jackdaw channel that some of the FundingCircle guys lurk in - they're good at responding too.

noisesmith17:01:18

this is a regression in the example, I'm going to see if I can find the correct namespace in the edit history of that ns

noisesmith17:01:02

OK - the example never worked, I'll ping the author

noisesmith17:01:47

I'm certain the confluent in the confluent/start referenced here is this file, if you just load it before pipe.clj it should work https://github.com/FundingCircle/jackdaw/blob/7403f8714f4b77573be03ac69368200d856fa902/examples/dev/confluent.clj

noisesmith17:01:19

worth a try!

noisesmith17:01:50

I added this - if I get some free time I might attempt the fix since I have access to the repo https://github.com/FundingCircle/jackdaw/issues/222

paul93122416:01:11

Thank you very much. I made a lot of progress in setting this up. Anyway, I try the word-count.clj example now, and I found some errors there too, I make a post about it in #jackdaw .

paul93122418:01:15

oh, nevermind, I succeeded 😄

noisesmith18:01:51

please do follow up on my bug ticket above with what worked if you have a chance! I didn't get around to digging deeper into this yesterday

paul93122414:01:19

well it didn’t, I started confluent separately, and moved to the word-count example, and that one worked well with clj -A:dev. Now I can learn more about it.

pez15:01:06

What are some good Clojure books for someone who is not completely new to the language, but also haven't fully grokked it? (Yes, I.) I enjoy 4clojure and other puzzles, but feel the need for something more systematic. I don't mind if it gets advanced, but it needs to start reasonably basic. And if there is some video course that I should consider, those tips are welcome as well.

pez15:01:01

Nice! Is it up-to-date, you think?

Linus Ericsson15:01:34

I would consider the videotutorials at: https://lambdaisland.com/

❤️ 8
synthomat15:01:58

(btw. Packt Publishing has an offer right now, many ebooks for $5, also Clojure!)

❤️ 4
synthomat15:01:46

Not much but maybe one can find something useful there https://www.packtpub.com/catalogsearch/result/?q=clojure

mloughlin15:01:24

Are the clojure books available on packt good? IME the quality of their books is usually questionable

synthomat15:01:29

not exceptionally great at least 😄 but they are also not horribly bad

em16:01:59

I really liked https://www.amazon.com/Professional-Clojure-Jeremy-Anderson/dp/1119267277, unlike many of the other introductory/mid-level clojure books it's more focused on the application side and has a lot of hands on examples with full-stack development. The Programming Clojure book (https://www.amazon.com/Programming-Clojure-Pragmatic-Programmers-Miller/dp/1680502468/ref=sr_1_2?keywords=programming+clojure&amp;qid=1579709713&amp;s=books&amp;sr=1-2) was also fantastic, and is a step above in difficulty than Getting Clojure

❤️ 4
jgerman16:01:05

Zack Tellman's book is excellent as well: https://leanpub.com/elementsofclojure

jgerman16:01:09

imo it transcends just Clojure

Eamonn Sullivan16:01:43

+1 on Programming Clojure (by @U064X3EF3). I'm a Scala programmer, so not completely new to functional or the JVM and found it hit the sweet spot. I've also read Elements of Clojure and found it more thought provoking than immediately useful. I'm in the middle of Getting Clojure and I'm finding it a bit too basic for me.

❤️ 4
synthomat16:01:19

“Elements of Clojure” is more of a best-practice and patterns book, isn’t it? @U06DEA21F

synthomat16:01:34

not really explaining the language

synthomat16:01:03

for that purpose it is great, though

Eamonn Sullivan16:01:52

I mostly stopped reading programming books years ago (I have a ton of O'Reilly books), but since I'm doing Clojure as a side project and all by myself, I feel I need a bit more of an overall feel/high-level guidance than what you get in random StackOverflow posts.

synthomat16:01:33

same here… reading other project’s code helps

em16:01:56

Oh yeah Elements definitely transcends just clojure, highly recommended. It provides guidance in the less instructory aspects of a language, like idioms, higher level design, and I particularly liked its section on understanding abstraction. Lots of fun references to completely non-programming texts and interesting reads from philosophy and social theory that have surprising connections to programming in clojure.

❤️ 4
jgerman16:01:49

@U4E39A29Y yes, and realistically it's stuff you pick up as you gain experience as a while, written very well

jgerman16:01:26

it's probably the second book I'd give to a new hire after they've gained some experience in the language

seancorfield17:01:40

Surprised no one mentioned Clojure Applied

gerred17:01:32

older but good, Joy of Clojure

jgerman17:01:52

@U04V70XH6 Clojure Applied is good as well, I'm partial to the cover, most of these weren't out when I started Clojure so I don't know how great they are from a 'getting started' standpoint

seancorfield17:01:58

Clojure Applied is good for someone with some Clojure background, wanting to get more advanced/real world insight.

💯 8
seancorfield18:01:19

I pretty much just buy every Clojure book out there (except the Packt stuff, most of which is awful).

8
jaihindhreddy18:01:43

Programming Clojure -> Clojure Applied as the details books. Joy of Clojure -> Elements of Clojure as the rationale/ideas books. Recommend doing the both in parallel.

8
pez19:01:56

@UQY3M3F6D, I have watched two of the free videos now. I love the pace. Video/audio resources can sometimes stress me up, because they go a bit too slow. Not these. They are to-the-point and zero-nonsense. There is a pause button there, after all. Really good work, @U07FP7QJ0 ! (I can't afford the payed tier right now, but hopefully my next employer will realize how smart it would be to give me full access.)

pez19:01:09

And thanks all of you here for all this input! I've started with Brave online. It allows me to fast forward to the pieces that are missing for me. But I see more tips here that I will follow up on.

Alex Miller (Clojure team)20:01:11

Have you filled out the 2020 State of Clojure Community Survey yet? It's a great source of info in understanding the community, and we'd welcome your participation if you have a few minutes. https://surveymonkey.com/r/2020clojure

4
👍 4
erwinrooijakkers20:01:05

#object[java.util.Locale 0x28caec3 "nl"] is the 0x28caec3 the hashcode?

erwinrooijakkers20:01:33

Answer: no

user=> (import 'java.util.Locale)
java.util.Locale
user=> (def l (Locale. "nl"))
#'user/l
user=> l
#object[java.util.Locale 0x562fcb0 "nl"]
user=> (.hashCode l)
104804738

bfabry20:01:52

memory address?

ghadi20:01:01

System/identityHashCode

ghadi20:01:27

it's a hashcode, but not the same as Object.hashcode()

erwinrooijakkers21:01:50

More convincing 😉

Jakob Riishede Møller21:01:14

Maybe this should have been posted in the beginners channel - bear with me: From https://clojure.org/guides/learn/syntax: "Many languages have both statements and expressions, where statements have some stateful effect but do not return a value. In Clojure, everything is an expression that evaluates to a value. Some expressions (but not most) also have side effects." When I read this, I get the impression that Clojure does not have statements, but isn't (def x (+ 3 4)) equivalent to a statement?

bfabry21:01:44

it's an expression with a side effect. it returns the var that it defines

bfabry21:01:02

cljs.user=> (def foo 1)
#'cljs.user/foo

bfabry21:01:17

sorry, "evaluates to" the var that it defines

Jakob Riishede Møller21:01:23

Right, but is is the side effect that we are interested in?

bfabry21:01:51

it is the side-effect that we are interested in, yes. that's true lots of times. like when we call println

bfabry21:01:04

however it's not true "most" of the time. in most well written clojure programs I would say it's probably only true <1% of the time

bfabry21:01:50

eh, maybe <10% of the time I guess if you include def defn and ns which as you correctly note are useful for their side-effects

Jakob Riishede Møller21:01:33

I mean: using def is not very "pure" to me

Jakob Riishede Møller21:01:58

but practical, I guess

bfabry21:01:01

even haskell let's people define things 🙂

bfabry21:01:18

although haskell separates compile/definition time from runtime I guess

kwladyka21:01:46

https://clojure.wladyka.eu/posts/when-use-exclamation-mark/ this is in the topic of side effects. Maybe will be useful.

kwladyka21:01:44

I am very wrong about definitions but in Clojure data is code and code is data, so: (foo 1 2 3) is a list where first item is a name of the function. But you can generate the same list by other function and run it as you expect or threat as a data only.

Jakob Riishede Møller21:01:01

My point was only, that I suspect def is used a lot to hold state

ghadi21:01:26

You will only see def at the top-level

kwladyka21:01:27

(def hostname (-> (InetAddress/getLocalHost)
                  (.getHostName)))
^ example of dynamic thing during start the app But in most cases (def conf-status #{3 5}) etc.

Jakob Riishede Møller21:01:28

I am used to OOP and a newbie in functional programming, so that kind of advice is worth remembering

noisesmith21:01:24

@USNL3G7GE it's not that clojure doesn't have side effects, it that clojure has no forms that don't return a value

kwladyka21:01:41

oh that was a point of your question, now I see the point 🙂

noisesmith21:01:56

these things are related, but it's a nuance - you can say (def foo-var (def foo 42)) - foo-var holds the var that holds foo

noisesmith21:01:52

@@foo-var returns 42, @foo-var returns a var that currently holds 42, but could hold something else later

noisesmith21:01:04

that's not really what you asked - a lot of things return nil, you can use for example (let [x (f 1) _ (println x) y ...] ..) and clojure doesn't error about the println in a binding context - it returns nil, which is a valid thing to bind to

kwladyka21:01:16

but don’t bother too much about this theory, this is not something what you would think about during coding later. Things come naturally.

noisesmith21:01:29

@USNL3G7GE the primary way this comes up: (let [x (if (f) 0 1)] ...) - since everything returns a value, you can use if for a value instead of a side effect, which is very useful

Jakob Riishede Møller21:01:31

I think you should bother about code structure - I cannot imagine that it is not possible to write programs in Clojure with a clumsy structure

kwladyka21:01:15

oh it is, I saw terrible projects in Clojure, terrible…

Jakob Riishede Møller22:01:35

@U050ECB92 Oh - I guess you meant that def sets global state (and nothing else)

ghadi22:01:11

yeah it defines initial meaning

ghadi22:01:24

even in "pure" functional systems there is something that does that

ghadi22:01:46

binds a symbol to its meaning

Jakob Riishede Møller22:01:08

But I think global state should be minimized...(?) https://wiki.c2.com/?GlobalVariablesAreBad

noisesmith22:01:28

sure, but you need at least one

noisesmith22:01:15

the idea with def is we don't use it for in-app logic, we use it for iterative debugging and development of a live system

noisesmith22:01:07

in order to be productive as a programmer I want to be able to replace the buggy version of f (a globally visible function) with a new one, that's a mutation but it's not a mutation in my app logic, just my dev flow

ghadi22:01:27

it's not global mutable state it's a constant that's being defined

Jakob Riishede Møller22:01:45

So just dont redefine it 😉

andy.fingerhut22:01:43

Well, a mutable constant 🙂

andy.fingerhut22:01:20

I realize that isn't necessarily clarifying anything for someone just learning it, but it really is mutable, since you can change it at run time. It is considered good style/practice to def a function at run time when developing, to fix things or try things out. It would be considered bad style/practice by most Clojure devs to do that in a production system, except perhaps in emergencies involving manual intervention by a live human, which is like the development time scenario.

andy.fingerhut22:01:04

And that last scenario would be considered bad practice by many developers.