beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-01-04T00:28:56.063500Z

transients don't replace hash-maps, they are an optimization for code that builds up hashmaps, so they lack many of the read-oriented features

2021-01-04T04:52:37.064300Z

You don't need to do anything, #(nth % 1) is a function of one argument

2021-01-04T04:53:11.064500Z

(->> [1 2 3]
  (#(nth % 1)))

2021-01-04T05:08:37.064900Z

But in the more general case, you can nest ->> inside -> or use as->

(-> [1 [2 4 6] 3]
  (nth 1)
  (conj 10)
  (->> (map inc)))

2021-01-04T05:09:08.065100Z

As well as do what you did, and wrap it in an anonymous fn (you just need to call the fn as well).

2021-01-04T05:09:27.065300Z

Finally, if you really want a flip, its pretty trivial to implement yourself:

(defn flip [f & args]
  (apply f (reverse args)))

Andrew Doolittle 2021-01-04T05:31:35.065600Z

Despite having updated to the latest CIDER nrepl 0.25, my repl was only using 0.22. After some more research, I seem to have solved my problem by updating my ~/.lein/profiles.clj. I removed references to CIDER as https://jakemccrary.com/blog/2017/08/27/my-current-leiningen-profiles-dot-clj/ stated that the latest CIDER no longer requires you to list dependencies explicitly. Feels like a big DUH after fixing this. Thanks for pointing me in the right direction @dpsutton πŸ™

Ty 2021-01-04T07:52:05.070900Z

My last little foray into clojure went really well. I have another idea I could use some validation for, as well as some direction on how to approach it. I watched a Pharo Smalltalk demo and thought the codebase visualization and reflection metrics were really cool. What I'd like to do is be able to parse a clojure codebase, run some metrics on that codebase, and then generate some visualization tools and maybe even a way to traverse the codebase. Some simple ideas might be showing the number/location of references to a function. Showing a hierarchy of macro usage, along with some example inputs/outputs that show macro expansion. In general being able to generate a graph of the codebase that spans out from the entry point(s). Would this type of tool be at all useful? Is there something like this already out there? If it would be useful, what are some additional things that also might be nice to have with a tool like this? Lastly, if I were to attempt this, what would be a good way to approach it? I'd really like to be able to fully parse the contents of a file/codebase so that I can have all the semantic information I need without having to resort to hacks/tricks.

jumar 2021-01-04T08:02:57.071Z

I had a similar idea/need a long time. There are some plugins/libs to visualize the call graph, e.g. clj-usage-graph: https://github.com/gfredericks/clj-usage-graph/blob/master/src/com/gfredericks/clj_usage_graph/usages.clj

jumar 2021-01-04T08:03:34.071400Z

Mentioned here: https://groups.google.com/u/1/g/clojure/c/pneew-XRlGY

Tim Robinson 2021-01-04T11:40:49.075100Z

Can anyone explain why I would use force with a delay? We already have @ and deref and it seems to me they do exactly the same thing

roelof 2021-01-04T11:51:03.075600Z

Why do I get here a error :

(defn to-json[suspects]
  into {} (clojure.string/join( ", " (get :name suspects) (get :glitter-index suspects))))


(to-json {:name "Roelof" :glitter-index 2})

roelof 2021-01-04T11:51:33.076Z

; Execution error (ClassCastException) at chapter4/to-json (form-init1060733672431633963.clj:82).
; class java.lang.String cannot be cast to class clojure.lang.IFn (java.lang.String is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')

2021-01-04T11:52:35.076800Z

because you wrote clojure.string/join(", " ...)

2021-01-04T11:53:24.077500Z

to call a function in clojure you must use sexp form like this (clojure.string/join ", " ...)

roelof 2021-01-04T11:59:46.077700Z

thanks

roelof 2021-01-04T11:59:49.078Z

still no luck

roelof 2021-01-04T11:59:53.078300Z

(defn to-json [suspects]
  (  into {} (clojure.string/join ", " [(get :name suspects)])))


(to-json {:name "Roelof" :glitter-index 2})

roelof 2021-01-04T12:09:04.079800Z

; Execution error (IllegalArgumentException) at chapter4/to-json (form-init1060733672431633963.clj:82).
; Don't know how to create ISeq from: java.lang.Character

Antonio Bibiano 2021-01-04T12:11:54.080700Z

get takes the map first and then the key

Antonio Bibiano 2021-01-04T12:12:14.081400Z

(get suspects :name)

2021-01-04T12:12:59.082100Z

join will return a string calling (into {} β€œsome string”) will throw that exception

2021-01-04T12:13:29.082600Z

maybe you can describe what you trying to achieve?

Tim Robinson 2021-01-04T12:16:06.083500Z

also [(get :name suspects)] is a vector with one entry, so string/join won't have anything to join

roelof 2021-01-04T12:21:16.083800Z

I kniw

roelof 2021-01-04T12:22:11.084900Z

what I try to achieve is to convert this : {:name "John", :glitterindex: 2) into a json without using a json library

roelof 2021-01-04T12:22:35.085400Z

so the outcome is {"John Doe", 2}

dharrigan 2021-01-04T12:30:03.085600Z

(def foo {:name "John Doe" :glitterindex 2})

dharrigan 2021-01-04T12:30:10.085800Z

(apply hash-map (vals foo))

dharrigan 2021-01-04T12:30:14.086Z

{"John Doe" 2}

2021-01-04T12:32:13.087500Z

maps in clojure is unordered so vals might return [2 "john"]

dharrigan 2021-01-04T12:32:39.087900Z

However, here be dragons, json processing is very edge casey, lots of work arounds and cavets - hence a trivial translation won't suit

dharrigan 2021-01-04T12:33:06.088200Z

I would just use a library tbh and @delaguardo is right πŸ™‚

roelof 2021-01-04T12:41:30.090Z

thanks, but I still think the purpose of the challenge of the brave book was to do it manually

2021-01-04T12:45:40.092200Z

Then you can use juxt to extract values under certain keys from a map

roelof 2021-01-04T12:50:36.093100Z

juxt ?? That one is not explained in thir or a former chapter

2021-01-04T12:52:00.093400Z

could you share a link to your current chapter?

2021-01-04T12:52:26.093900Z

otherwise I can only guess what you are trying to do)

roelof 2021-01-04T13:00:47.094100Z

sure: https://www.braveclojure.com/core-functions-in-depth/

2021-01-04T13:08:30.094800Z

ok, so is it exercise 4 you are working on?

Antonio Bibiano 2021-01-04T13:24:38.095200Z

Ah I just did that one

Antonio Bibiano 2021-01-04T13:24:52.095600Z

if that's ok with you I can share my solution

Antonio Bibiano 2021-01-04T13:25:00.095800Z

but I was converting to CSV

roelof 2021-01-04T13:44:18.096100Z

yep, the lastest ine

roelof 2021-01-04T13:44:57.096800Z

@antbbn of course you may. Maybe I find some ideas I can use

2021-01-04T13:57:23.096900Z

force is agnostic about whether its argument is actually a delay

user=> (force 42)
42

2021-01-04T13:58:19.097100Z

and @ is already just a reader shorthand for deref

Antonio Bibiano 2021-01-04T15:05:21.098200Z

(defn get-many
  [ks record]
  (map #(get record %) ks))
(defn suspects-to-csv 
  [suspects]
  (let [header-keys (keys (first suspects))]
    (reduce #(clojure.string/join "\n" [%1 %2]) 
            (clojure.string/join "," header-keys)
            (map 
             (comp (partial clojure.string/join ",") (partial get-many header-keys))
             suspects))))

Antonio Bibiano 2021-01-04T15:06:51.099200Z

I used a let block to make sure that I always extract the keys in the same order

Antonio Bibiano 2021-01-04T15:07:05.099500Z

using get-many

2021-01-04T15:08:54.101200Z

get-many could just be (map record ks) if you are using normal hash maps

2021-01-04T15:08:59.101400Z

also, keys and vals will always return the same order for two collections with the same keys

2021-01-04T15:11:08.103100Z

finally your string/join calls could be str calls, if performance is a concern at all you could use a StringBuilder instead

Antonio Bibiano 2021-01-04T15:12:23.104200Z

mhh I lost part of the conversation

2021-01-04T15:15:30.105300Z

yeah, slack is being weird

Antonio Bibiano 2021-01-04T15:17:12.105500Z

but now that I think about it totally makes sense that keys and vals will keep the order for the same collection

2021-01-04T15:17:52.105700Z

(the main reason to use join instead of iterating str calls is performance, using small calls to join in a loop like this undoes that advantage)

2021-01-04T15:18:33.106300Z

I guess the one gotcha is an ArrayMap vs. HashMap, which I didn't consider at first

popeye 2021-01-04T15:33:21.107400Z

Hi, I have a map and i want to fetch the keys which has more that 10 value, How can I get it

{"hello" 10, "hi" 12}

popeye 2021-01-04T15:35:06.107800Z

output should be {hi 12}

caumond 2021-01-04T16:33:06.108500Z

Use filter

caumond 2021-01-04T16:35:34.108600Z

(sorry, hi first !!)

Tim Robinson 2021-01-04T17:19:12.108700Z

ok thanks - I can't really think of a use case for that but I guess it was important to someone :)

seancorfield 2021-01-04T17:30:56.110300Z

@popeyepwr (into {} (filter #(< 10 (val %)) coll)) (if the hint to "use filter" isn't enough on its own)

😁 1
βœ… 2
clyfe 2021-01-04T17:56:57.111500Z

Maps in clojure are not ordered. For ordered maps see https://github.com/flatland/ordered

clyfe 2021-01-04T17:57:58.112Z

PersistentArrayMap is, PersistentHashMap isn't, and past 8 pairs the former is "upgraded" to the latter

Antonio Bibiano 2021-01-04T17:58:55.112200Z

so you think it's a good idea to make sure that you get the keys in the explicit order you want using something like (map record ks)

clyfe 2021-01-04T17:59:54.112400Z

if you want order, use ordered linked above

seancorfield 2021-01-04T18:00:40.112600Z

Although the order of keys (or vals) is "random", they are consistent: whatever order keys gives you matches whatever order vals gives you.

Antonio Bibiano 2021-01-04T18:01:08.112800Z

gotcha, it's only that the gist of that exercise was to convert that list of hash maps to a csv

Antonio Bibiano 2021-01-04T18:02:49.113Z

and given that each map is a different element of the list even though they have the same keys

Antonio Bibiano 2021-01-04T18:03:28.113200Z

I was worried about the case where vals of one item might return them in a different order than vals of another item

seancorfield 2021-01-04T18:04:10.113400Z

Right, I think your overall approach -- get keys from the first hash map and use that, in order, to get values from the other maps makes sense. You can't rely on vals producing the same order of keys across multiple hash maps.

clyfe 2021-01-04T18:08:26.113600Z

sorted-map or sorted-map-by can also be used to ensure a definite order on keys

Antonio Bibiano 2021-01-04T18:11:24.114900Z

another thing that I noticed looking at my code is that I reduce over the result of a mapping over the list of suspects

Antonio Bibiano 2021-01-04T18:11:56.115600Z

but It could also be refactored to reduce over the suspect by using a slightly more complex function

Antonio Bibiano 2021-01-04T18:12:04.116Z

like so

Antonio Bibiano 2021-01-04T18:13:03.116700Z

(defn suspects-to-csv 
  [suspects]
  (let [header-keys (keys (first suspects))]
    (reduce (fn [result m]
              (str result 
                   "\n" 
                   (clojure.string/join "," (map m header-keys))))
            (clojure.string/join "," header-keys)
            suspects)))

Antonio Bibiano 2021-01-04T18:13:28.117Z

which style would be more idiomatic?

Antonio Bibiano 2021-01-04T18:18:43.117100Z

Nice! thanks for the tips

Kannan Ramamoorthy 2021-01-04T18:29:08.118400Z

I’m fiddling to setup test files and CLI commands to run it using deps.edn. If anyone could point me out to any reference that would be helpful.

Kannan Ramamoorthy 2021-01-06T04:00:06.246200Z

Got it working! Thank you Sean and Pavlos. Took a while to relaize that unlike Java, we have to have different namespace for test and actual source that we have to test. In java the package name stays the same for both the actual and test class.

Kannan Ramamoorthy 2021-01-06T04:00:55.246400Z

I assume the reason being, ns is not exactly equivalent to package. But kind of equivalent to fully qualified class name.

seancorfield 2021-01-06T04:16:42.246600Z

Ah, yes! The convention is that if you have src/foo/bar.clj (with (ns foo.bar ...)) then you would have test/foo/bar_test.clj (with (ns foo.bar-test ...)).

seancorfield 2021-01-06T04:17:09.246800Z

If you create a brand new project (with clj-new) that's what you'll see...

seancorfield 2021-01-06T04:21:10.247Z

seanc@DESKTOP-30ICA76:~/clojure$ clojure -X:new :name foo.bar
Downloading: seancorfield/clj-new/maven-metadata.xml from clojars
Generating a project called foo.bar based on the 'lib' template.
The lib template is intended for library projects, not applications.
seanc@DESKTOP-30ICA76:~/clojure$ tree foo.bar
foo.bar
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
β”œβ”€β”€ deps.edn
β”œβ”€β”€ doc
β”‚Β Β  └── intro.md
β”œβ”€β”€ pom.xml
β”œβ”€β”€ resources
β”œβ”€β”€ src
β”‚Β Β  └── foo
β”‚Β Β      └── bar.clj
└── test
    └── foo
        └── bar_test.clj

6 directories, 8 files
seanc@DESKTOP-30ICA76:~/clojure$ cd foo.bar/
seanc@DESKTOP-30ICA76:~/clojure/foo.bar$ clojure -M:test:runner

Running tests in #{"test"}

Testing foo.bar-test

FAIL in (a-test) (bar_test.clj:7)
FIXME, I fail.
expected: (= 0 1)
  actual: (not (= 0 1))

Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
seanc@DESKTOP-30ICA76:~/clojure/foo.bar$ cat test/foo/bar_test.clj
(ns foo.bar-test
  (:require [clojure.test :refer :all]
            [foo.bar :refer :all]))

(deftest a-test
  (testing "FIXME, I fail."
    (is (= 0 1))))
seanc@DESKTOP-30ICA76:~/clojure/foo.bar$

seancorfield 2021-01-06T04:22:25.247300Z

@kannangce Hopefully that new project example above will be helpful!

πŸ‘ 1
Kannan Ramamoorthy 2021-01-06T05:34:47.248Z

Thanks a lot @seancorfield! That’s very informative!

2021-01-04T18:33:10.119200Z

@claudius.nicolae maps are not ordered, but to PersistentHashMap instances with the same keys will have a keys output and a vals output in the same order

clyfe 2021-01-04T18:33:58.119400Z

PersistentArrayMap is ordered, PersistentHashMap isn't

Kannan Ramamoorthy 2021-01-04T18:34:33.120100Z

Is there any sample projects that I can look upto? I referred to @seancorfield’s https://github.com/seancorfield/dot-clojure/blob/develop/deps.edn. And added below,

:test   {:extra-paths ["src/test/clojure"]
          :extra-deps  {org.clojure/test.check {:mvn/version "RELEASE"}}}

 :runner {:extra-deps {com.cognitect/test-runner
                       {:git/url "<https://github.com/cognitect-labs/test-runner>"
                        :sha     "b6b3193fcc42659d7e46ecd1884a228993441182"}}
          :main-opts  ["-m" "cognitect.test-runner"
                       "-d" "test"
                       "-d" "src/test/clojure"]}
but when I run clj -M:test or clj -M:runner , it takes me to repl instead of running the tests.

2021-01-04T18:34:43.120500Z

I didn't say it was orderd, I said vals or keys on two PersistentHashMap with the same keyset have the same order

πŸ‘ 1
seancorfield 2021-01-04T18:35:25.121400Z

@kannangce Check clojure -Sdescribe -- I suspect you're on an old version.

seancorfield 2021-01-04T18:35:39.121700Z

Most of my projects assume 1.10.1.727 or higher.

2021-01-04T18:36:21.122600Z

(ins)user=&gt; (def m1 (into {} [[:a 0] [:b 1] [:c 2] [:d 3]]))
#'user/m1
(ins)user=&gt; (def m2 (into {} [[:a "a"] [:b "b"] [:c "c"] [:d "d"]]))
#'user/m2
(ins)user=&gt; (= (keys m1) (keys m2))
true

seancorfield 2021-01-04T18:36:40.123400Z

For example https://github.com/seancorfield/clj-new and https://github.com/seancorfield/depstar both state 1.10.1.727 or higher as a requirement in their READMEs (my dot-clojure does not, but it probably should).

clyfe 2021-01-04T18:36:45.123900Z

Yes, Sean said that too.

gibi 2021-01-04T18:38:29.124600Z

Hi, my question is probably very dumb and apologies for that. I’m trying to understand how this compojure-api code works (app (-&gt; (mock/request :get "/api/documents?id=123")) works behind the scene. I printed in the repl both app and the mock request , you can find them here. https://paste.ofcode.org/gYrXDmzUzHTiYrQvKSzsxD what I don’t understand is how (app mock-request) is executed. I can’t find the function that receives the request. Also is not clear to me what #Route is printed just before any dictionary. Thanks for any help in advance.

seancorfield 2021-01-04T18:40:22.124800Z

All of my projects use deps.edn for testing these days -- https://github.com/seancorfield/next-jdbc/ is a good example since it has both GitHub Actions and CircleCI configured to run tests via deps.edn

Kannan Ramamoorthy 2021-01-04T18:42:34.125Z

My version is β€œ1.10.1.727”. But not sure why running clj -M:testΒ orΒ `clj -M:runner` takes me to repl. Will check some of your projects and compare my deps.edn. Thanks Sean!

2021-01-04T18:43:04.125600Z

@francesco.losciale #Route{} is a print format for a record called Route

pavlosmelissinos 2021-01-04T18:43:21.125700Z

Aren't the :test and :runner aliases meant to be run together? like so: clj -M:test:runner Not sure about :runner on its own but the :test alias doesn't have a :main-opts entry, so I think it makes sense that it takes @kannangce to a repl, no? :thinking_face:

2021-01-04T18:43:49.126500Z

defrecord creates a type that acts like a hash map, but has its name prefixed when printing, and allows custom extension of protocol methods

πŸ™Œ 1
clyfe 2021-01-04T18:44:12.126800Z

See https://skillsmatter.com/skillscasts/3445-functional-web. Note: Compojure is old and slow O(n); works well with few routes, but generally prefer https://github.com/metosin/reitit.

πŸ‘ 1
πŸ™Œ 1
seancorfield 2021-01-04T18:46:30.127400Z

Oh, well spotted! Yes, you need -M:test:runner

seancorfield 2021-01-04T18:47:30.127600Z

But clj -M:runner should not give you a REPL -- I would expect in most projects for it to give you an exception since you won't have any test dependencies added in.

πŸ‘ 1
seancorfield 2021-01-04T18:49:01.127900Z

For example:

(! 511)-&gt; clojure -X:new :name kannan/example
Downloading: seancorfield/clj-new/maven-metadata.xml from clojars
Generating a project called example based on the 'lib' template.
The lib template is intended for library projects, not applications.
(! 512)-&gt; cd example/
(! 513)-&gt; clojure -M:runner

Running tests in #{"test"}
Execution error (FileNotFoundException) at cognitect.test-runner/test (test_runner.clj:62).
Could not locate kannan/example_test__init.class, kannan/example_test.clj or kannan/example_test.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.

Full report at:
/var/folders/p1/30gnjddx6p193frh670pl8nh0000gn/T/clojure-3814224161163105319.edn

roelof 2021-01-04T18:50:32.128400Z

@antbbn thanks for showing me this

πŸ™Œ 1
pavlosmelissinos 2021-01-04T18:52:12.128700Z

For what it's worth, here's what I'm getting in each case (this is for a project that doesn't have any tests yet):

&gt; clj -M:test       
Clojure 1.10.1
user=&gt; 
&gt; clj -M:runner

Running tests in #{"test" "src/test/clojure"}

Testing user

Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
&gt; clj -M:test:runner

Running tests in #{"test" "src/test/clojure"}

Testing user

Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
(I'm on v1.10.1.763)

caumond 2021-01-04T19:01:18.129100Z

Hey I did a full answer then, but making o e answer in multiple message was not a good idea with slack outage. The full answer never arrive !!

2021-01-04T19:17:56.129600Z

@noisesmith Not quite. keys and vals are only guaranteed to return orders consistent with each other for the same identical map object. While it is common for two PersistentHashMap objects that are = to return the same order as each other for keys (or vals), that is not guaranteed, and can be false when two keys have the same hash value, but were added to the not-identical-but-= PersistentHashMap instances.

πŸ’― 1
2021-01-04T19:20:59.129800Z

Example:

$ clj
Clojure 1.10.1
(clojure-version)
"1.10.1"
(hash 0)
0
(hash 92612215)
0
(def m1 (-&gt; {} (assoc 0 :added-first) (assoc 92612215 :added-second)))
#'user/m1
(def m2 (-&gt; {} (assoc 92612215 :added-first) (assoc 0 :added-second)))
#'user/m2
m1
{0 :added-first, 92612215 :added-second}
m2
{92612215 :added-first, 0 :added-second}
(= m1 m2)
false
(keys m1)
(0 92612215)
(keys m2)
(92612215 0)

πŸ‘ 2
2021-01-04T19:22:00.130Z

This happens because PersistentHashMap puts all keys with the same hash value into the same "hash bucket", which is simply a linked list of elements, in the order that they were last added to the PersistentHashMap

2021-01-04T19:22:16.130300Z

thanks for the info

2021-01-04T19:37:23.130600Z

Reducing without building intermediate sequence first can be faster -- I'd think only noticeably so with larger sequences. As a beginner I usually find separate reduce and map steps sometimes easier to manipulate in code, but that's probably highly editor/user-dependent. I'd be surprised though if one of the two variants was less idiomatic than the other -- I'd expect readability/style preference to be criterium of choice here.

Antonio Bibiano 2021-01-04T20:02:02.131100Z

Makes sense, also I agree that in this context and as a beginner reducing over something that is already mapped seems more straightforward

seancorfield 2021-01-04T20:16:18.131400Z

@pavlos Yup, it's going to depend on exactly what's in your project, with -M:test producing a REPL (since there's no :main-opts in that alias) and -M:runner either failing (as I showed above in a freshly created project) or finding no tests to run as you saw.

πŸ‘ 1
Daniel Tobias 2021-01-04T20:36:07.132900Z

hi all, im using cljs with reagent which produces an html and a js. My backend webserver is trying to render the page with jinja2 and i wanted to load the page with some data (it's a json object or an array in practice). How can i 'access' this data in cljs?

2021-01-04T21:11:08.133100Z

you can use inline js to embed the data in the page, and then access the data with cljs interop

2021-01-04T21:11:31.133300Z

more commonly the rendering happens in cljs and the data is fetched via AJAX from the server

Daniel Tobias 2021-01-04T23:12:36.133600Z

I guess i could do ajax here but im changing the design from being written in straight js to cljs and thats how it currently works. I'll look into ajax though, thanks