Fork me on GitHub
#beginners
<
2017-12-18
>
olivergeorge00:12:14

How about (map (fn [f v] (f v)) [f1 f2] [v1 v2]) or (map #(%1 %2) [f g] [a b]).

Quan Nguyen02:12:16

That's very concise, thanks !

Sabbatical201701:12:54

@sova Thank you very much for your comment! I think I understand what you suggest, and it seems to do what's needed, except that if you just add a new record that Joe's ice-cream liking is now 7 then that won't automatically retract the previous 8. The solution I put in my most recent comment (`:liking-person-food` attribute unique) solves that problem but it admittedly looks inelegant in its own way...

stardiviner12:12:09

In Clojure code, how to print out current namespace?

manutter5112:12:35

In the repl, you can get (str *ns*) for a human-friendly value of the current namespace

stardiviner12:12:00

@manutter51 thanks

joshkh14:12:45

is there built-in way to swap! an atom but return the atom itself instead of it's dereferenced value? it would be useful for threading scenarios: (cond-> some-atom x? (swap! update :x inc) y? (swap! update :y inc))

joshkh14:12:56

(i could surely write a function to do it. i'm just curious.)

manutter5114:12:18

I don’t believe there’s a built-in way, but you don’t really need it:

(swap! some-atom #(cond-> %
                  x? (update :x inc)
                  y? (update :y inc)))

alexmiller18:12:52

I would go further and say you don’t want that. If you are outside the atom, you are outside the atomic update and I think you could get some very unexpected results

joshkh14:12:57

of course. thanks @manutter51

yonatanel15:12:22

Where do you put test utils code so that lein test won't try to run it as if it were a test?

noisesmith17:12:03

lein test only runs things that are defined as tests via the :test metadata or via deftest (which puts :test metadata on your var for you)

noisesmith17:12:30

as long as you don’t have side effects in your files, their code won’t be run unless it’s a test

noisesmith17:12:41

the right fix is to make sure the files don’t contain side effects

New To Clojure16:12:26

Is Clojure 1.9 compatible with Java 9?

danm16:12:15

Clojure yes. Boot/Lein, yeeees, but you have to do some mucking about. As I understand it.

danm16:12:21

I'm not sure why though

New To Clojure16:12:48

@carr0t Thanks!

danm16:12:14

Also I'm not sure what that mucking about is, as we're still on Java 8

admay16:12:28

@ghsgd2 any reason why you’re looking to move to Java 9?

New To Clojure17:12:39

@admay App development will take more than 10 months so at the time of release there will be no security fixes for Java 8.

admay17:12:15

@ghsgd2 That’s a very valid concern haha I hadn’t even thought of that. It looks like we have until September of 2018 to get our stuff together. I’m going to be holding out until summer to wait and see what happens. I’m guessing by then, there will be plans to make stuff work for Leiningen and Boot out of the box rather than having to muck about.

joshkh17:12:51

does moving to the new dep management features in clojure 1.9 help? (i honestly haven't looked at it yet)

noisesmith17:12:51

the new dep management is for users looking for a bare minimum way to test out a clojure repl, it’s not relevant for project management

jgh17:12:40

on the java 9 thing, I found that you have to add :jvm-opts ["--add-modules" "java.xml.bind"] to your lein project.clj (probably have to do something similar with boot)

admay17:12:23

@joshkh I think the goal for tools.deps.alpha is to assist those building tooling rather than those using the tooling. I wouldn’t dare use the new deps library to manage a web application project, I’ll always opt for Lein or Boot. However, if I was building a tool to manage projects, tools.deps.alpha would be my go-to for building out my dependencies. This is all assuming you’re asking about tools.deps.alpha

joshkh17:12:58

aye, that's the one. i just had a look into it and you're right - great for building up projects concurrently but is out of scope for what lein/boot has to offer

admay17:12:18

Yeah, Lein and Boot are here to stay for a while, I think. I don’t think the Clojure team will ever focus on building out a specific developer tool for Clojure unless there is a desperate need for it or the current tooling diverges from the Clojure philosophy in a major way. There’s just too much opportunity to improve on the language itself to shift focus to tooling. However, now that the library does exist, I wouldn’t be surprised if we see more niche build tools coming out. Something like a plugin to build programmable templates for targeted applications like AWS Lambda maybe. As it stands, there’s no reasonable approach to running Clojure (not ClojureScript, just Clojure) on AWS Lambda due to startup time. However, with the tools.deps library, there might be someone out there who figures out how to drastically speed up the startup time for small Clojure programs to make them Lambda-able.

danm09:12:55

Interestingly I was talking to someone at an AWS meetup about this the other week. They said they don't actually have any problems running Clojure in a Lambda, because as long as you trigger it at least once every 5 minutes it stays 'warm' waiting for a new request, rather than spinning up a new instance. So you don't pay the startup cost every time. Obviously if you have a sudden spike in requests it'll spin up a load of new instances which will be slow, but apparently for a fairly consistent and constant level of throughput the startup time for Clojure isn't a major issue in Lambdas. This is just what I was told though, I have no direct experience.

seancorfield17:12:02

@admay There's a fairly fundamental limit to how much can be shaved off start up time and, while the core team do look at that, it's not really a priority use case for Clojure.

seancorfield17:12:20

@joshkh There are Leiningen and Boot add-ons that leverage tools.deps.alpha so you can specify dependencies etc in deps.edn and then use clj (or clojure) or you can use Leiningen/Boot with the same deps file(s). `tools.deps. is "just" a building block.

New To Clojure17:12:32

@seancorfield They would help Clojure a lot by updating conj to have the same behavior for different collection types.

noisesmith17:12:35

it does - it puts a new item in the natural place for each collection type

noisesmith17:12:48

if order of insertion matters, you should be making some guarantee that the data type being used is one that naturally inserts in that order

admay17:12:32

@seancorfield yeah, that was the only contrived example that I could come up with on the spot lol

chris17:12:50

conj will never change in that way

admay17:12:17

@ghsgd2 The different behaviors of conj are deliberate. the idea is that different data structures are exactly that, different. I’m guessing an example you might refer to is (conj '(1 2 3) 4)) vs (conj [1 2 3] 4). The reason why they work differently is because different data structures are more useful in certain use cases than others.

New To Clojure17:12:31

Thank you, @noisesmith, @chris, @admay!

noisesmith17:12:47

not to mention (conj #{1 2 3} 4) or (conj {:a 0 :b 1 :c 2} [:d 3])

noisesmith18:12:22

or (conj clojure.lang.persistentVector/EMPTY 1 2 3)

admay18:12:26

I’ll admit though, a rationale doc behind the behavior of conj and the like on data structures would be a good thing for beginners and it’s been a long time coming. This discussion is usually reserved for questions in the forums

seancorfield18:12:10

The docstring is explicit about the behavior depending on the concrete type (of the collection) and http://clojuredocs.org has plenty of examples. And clojure-site now accepts PRs (from anyone with a signed CA) so the community can add rationale docs etc. This isn't something we need to wait for the core team to do.

seancorfield18:12:56

Also https://clojure.org/guides/learn/sequential_colls "However, conj always adds elements where it can be done in constant time for the data structure."

seancorfield18:12:19

I think Clojure places a lot more emphasis on understanding the primary abstractions than any other language -- and, in particular, the performance guarantees of various operations on various data structures. And, yes, that makes the on-ramp steeper for new-to-Clojure developers.

admay18:12:41

I can’t remember where I read it, but someone, somewhere said, “Clojure asks for more from you but gives more in return” or something like that. It’s absolutely got a bit of a steeper learning curve than other languages (in my own experience as well) but the payoff is incredible and filled with “AH-HA!” moments like when the design choice of (conj) returning an empty vector in particular is explained, discovered, or otherwise made known!

seancorfield18:12:55

I like that characterization of Clojure... yeah, the culture is definitely one that rewards careful thought (and, to some extent, punishes sloppy thinking!). Really grokking the abstractions can take a while. Even now, after knowing Clojure for over seven years, there are still times when I post some code snippet and someone says "You could do X instead" and I'm like, "Oh yeah! Wow! That's much more idiomatic!"...

seancorfield18:12:26

(like the other day when I posted a transducer pipeline and I knew it could be cleaner but wasn't sure how -- and someone said "Use mapcat and you can omit that middle step" -- real 💡 stuff!)

admay18:12:21

I think a big part of learning Clojure is not just watch the old talks (Hammock driven development, Programming with Hand Tools, etc…) but watching them continuously. I’m 24. I have a degree in Maths. I’ve been programming a WHOPPING 2 years. The philosophy is sticking a bit, but the more I watch those talks and read those heavy hitting papers, the more I learn (and I always learn something new from them). It’s not an easy journey to truly understanding the language.

danm09:12:21

I'll get on to that in my copious free time 😉

noisesmith18:12:56

or (conj) for that matter 😄

noisesmith18:12:22

$ clj
Clojure 1.9.0
(ins)user=> (conj)
[]

admay18:12:02

lol the ol’ no-arity-lets-return-an-arbitrary-empty-thing language design pattern

admay18:12:40

@seancorfield I’m curious now, any idea why (conj) returns an empty vector in particular?

noisesmith18:12:44

it might be arbitrary but it’s consistent (into) returns the same thing

noisesmith18:12:04

@admay it’s for reducers and transducers that use a function with no args to return a base case

noisesmith18:12:30

and [] is the natural base case for reducers and transducers, and conj the most general reducing/transducing function

noisesmith18:12:36

it’s not arbitrary at all

noisesmith18:12:30

any more than (+) returning 0 or (*) returning 1 is arbitrary

admay18:12:10

That makes much more sense now, especially when the idea of ‘choosing the proper data structures’ comes up. Thanks @noisesmith!

admay18:12:42

I’ve been thinking about my next doc production for a while now and I think it might revolve around Clojure data structures, design choices, and when to use them. I need to finish up the functional programming guide first though.

include22:12:48

Hi 🙂 I’ve installed latest version of clojure and leiningen via brew but when I run lein repl I get a clojure 1.8.0 version. What I am doing wrong?

include22:12:15

humm

$ clj
and I get a repl 🙂

michaels22:12:05

lein uses its own bundled clojure version (i’ve learned), at least by default.

alexmiller22:12:52

it’s not bundled. the default template just creates a project.clj dependent on 1.8.0 (will be updated in future version)

alexmiller22:12:57

just change the version in project.clj

include23:12:04

@wmichaelshirk @alexmiller true. did the update on project.clj 🙂 10x guys