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
You don't need to do anything, #(nth % 1)
is a function of one argument
(->> [1 2 3]
(#(nth % 1)))
But in the more general case, you can nest ->>
inside ->
or use as->
(-> [1 [2 4 6] 3]
(nth 1)
(conj 10)
(->> (map inc)))
As well as do what you did, and wrap it in an anonymous fn (you just need to call the fn as well).
Finally, if you really want a flip
, its pretty trivial to implement yourself:
(defn flip [f & args]
(apply f (reverse args)))
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 π
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.
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
Mentioned here: https://groups.google.com/u/1/g/clojure/c/pneew-XRlGY
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
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})
; 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')
because you wrote clojure.string/join(", " ...)
to call a function in clojure you must use sexp form
like this (clojure.string/join ", " ...)
thanks
still no luck
(defn to-json [suspects]
( into {} (clojure.string/join ", " [(get :name suspects)])))
(to-json {:name "Roelof" :glitter-index 2})
; Execution error (IllegalArgumentException) at chapter4/to-json (form-init1060733672431633963.clj:82).
; Don't know how to create ISeq from: java.lang.Character
get takes the map first and then the key
(get suspects :name)
join will return a string calling (into {} βsome stringβ) will throw that exception
maybe you can describe what you trying to achieve?
also [(get :name suspects)]
is a vector with one entry, so string/join won't have anything to join
I kniw
what I try to achieve is to convert this : {:name "John", :glitterindex: 2)
into a json without using a json library
so the outcome is {"John Doe", 2}
(def foo {:name "John Doe" :glitterindex 2})
(apply hash-map (vals foo))
{"John Doe" 2}
maps in clojure is unordered so vals might return [2 "john"]
However, here be dragons, json processing is very edge casey, lots of work arounds and cavets - hence a trivial translation won't suit
I would just use a library tbh and @delaguardo is right π
thanks, but I still think the purpose of the challenge of the brave book was to do it manually
Then you can use juxt to extract values under certain keys from a map
juxt ?? That one is not explained in thir or a former chapter
could you share a link to your current chapter?
otherwise I can only guess what you are trying to do)
ok, so is it exercise 4 you are working on?
Ah I just did that one
if that's ok with you I can share my solution
but I was converting to CSV
yep, the lastest ine
@antbbn of course you may. Maybe I find some ideas I can use
force is agnostic about whether its argument is actually a delay
user=> (force 42)
42
and @
is already just a reader shorthand for deref
(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))))
I used a let block to make sure that I always extract the keys in the same order
using get-many
get-many could just be (map record ks)
if you are using normal hash maps
also, keys
and vals
will always return the same order for two collections with the same keys
finally your string/join calls could be str calls, if performance is a concern at all you could use a StringBuilder instead
mhh I lost part of the conversation
yeah, slack is being weird
but now that I think about it totally makes sense that keys and vals will keep the order for the same collection
(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)
I guess the one gotcha is an ArrayMap vs. HashMap, which I didn't consider at first
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}
output should be {hi 12}
Use filter
(sorry, hi first !!)
ok thanks - I can't really think of a use case for that but I guess it was important to someone :)
@popeyepwr (into {} (filter #(< 10 (val %)) coll))
(if the hint to "use filter" isn't enough on its own)
Maps in clojure are not ordered. For ordered maps see https://github.com/flatland/ordered
PersistentArrayMap is, PersistentHashMap isn't, and past 8 pairs the former is "upgraded" to the latter
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)
if you want order, use ordered linked above
Although the order of keys
(or vals
) is "random", they are consistent: whatever order keys
gives you matches whatever order vals
gives you.
gotcha, it's only that the gist of that exercise was to convert that list of hash maps to a csv
and given that each map is a different element of the list even though they have the same keys
I was worried about the case where vals
of one item might return them in a different order than vals
of another item
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.
sorted-map or sorted-map-by can also be used to ensure a definite order on keys
another thing that I noticed looking at my code is that I reduce over the result of a mapping over the list of suspects
but It could also be refactored to reduce over the suspect by using a slightly more complex function
like so
(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)))
which style would be more idiomatic?
Nice! thanks for the tips
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.
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.
I assume the reason being, ns is not exactly equivalent to package. But kind of equivalent to fully qualified class name.
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 ...)
).
If you create a brand new project (with clj-new
) that's what you'll see...
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$
@kannangce Hopefully that new project example above will be helpful!
Thanks a lot @seancorfield! Thatβs very informative!
https://clojure.org/guides/deps_and_cli https://clojure.org/reference/deps_and_cli
@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
PersistentArrayMap is ordered, PersistentHashMap isn't
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.I didn't say it was orderd, I said vals
or keys
on two PersistentHashMap with the same keyset have the same order
@kannangce Check clojure -Sdescribe
-- I suspect you're on an old version.
Most of my projects assume 1.10.1.727 or higher.
(ins)user=> (def m1 (into {} [[:a 0] [:b 1] [:c 2] [:d 3]]))
#'user/m1
(ins)user=> (def m2 (into {} [[:a "a"] [:b "b"] [:c "c"] [:d "d"]]))
#'user/m2
(ins)user=> (= (keys m1) (keys m2))
true
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).
Yes, Sean said that too.
Hi, my question is probably very dumb and apologies for that. Iβm trying to understand how this compojure-api code works (app (-> (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.
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
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!
@francesco.losciale #Route{}
is a print format for a record called Route
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:
defrecord
creates a type that acts like a hash map, but has its name prefixed when printing, and allows custom extension of protocol methods
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.
Oh, well spotted! Yes, you need -M:test:runner
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.
For example:
(! 511)-> 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)-> cd example/
(! 513)-> 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
@antbbn thanks for showing me this
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):
> clj -M:test
Clojure 1.10.1
user=>
> clj -M:runner
Running tests in #{"test" "src/test/clojure"}
Testing user
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
> 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)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 !!
@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.
Example:
$ clj
Clojure 1.10.1
(clojure-version)
"1.10.1"
(hash 0)
0
(hash 92612215)
0
(def m1 (-> {} (assoc 0 :added-first) (assoc 92612215 :added-second)))
#'user/m1
(def m2 (-> {} (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)
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
thanks for the info
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.
Makes sense, also I agree that in this context and as a beginner reducing over something that is already mapped seems more straightforward
@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.
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?
you can use inline js to embed the data in the page, and then access the data with cljs interop
more commonly the rendering happens in cljs and the data is fetched via AJAX from the server
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