Optional trailing map
So you'll declare with & {:keys [...] :as opts}
and then you can call with either :named "arguments"
or {:named "arguments"}
? Sounds good.
I’m a little stuck on this, it returns nil but prints nothing. I’d have expected it to print 10. Any thoughts?
(let [timeout-channel-10 (a/timeout 10)
timeout-channel-20 (a/timeout 20)
[m c] (a/alts!! [timeout-channel-10 timeout-channel-20])]
(if (= c timeout-channel-10)
(println 10)
(println 20))))
oh my goodness, it’s the extra paren. I’ve been executing the hosting comment block…
are you using CIDER?
apparently I’ve been staring at the screen too long…
if this is emacs (setq clojure-toplevel-inside-comment-form t)
is quite helpful for this
yep, cider/emacs
and these are awesome as well:
(setq cider-invert-insert-eval-p t)
(setq cider-switch-to-repl-on-insert nil)
I’ll have to look these all up but apparently they save me from myself?
these would a) evaluate the top leve inside of the comment form. and the latter two make it easier to send forms to the repl
thanks!
so i constantly use cider-send-form-to-repl and i make sure that "top level" does what i want, it doesn't focus the repl when i do it, and it evals the form
check out the map under C-c C-j d
for sent top level form to repl. e
for last expression
I tend to only use “cider-eval-last-sexp” but I’ll look at the ones you mention.
sure. the top level stuff is super useful for forms inside of a comment. you don't have to move to the end of the form, just anywhere inside of the form
What does !
at the end of a function suggest? I am confused why set-validator has it but add-watch doesn’t
It means that it is not idempotent and therefore should not ever be run inside a transaction
At least that is what is suggested by https://github.com/bbatsov/clojure-style-guide#unsafe-functions (in real world Clojure code I see it used in other ways)
or a mix of some args AND a trailing map
Oh, interesting. Do you think it'll start a major shift back to named arguments? Although I guess that will depend on how quickly folks adopt 1.11...
It's a common enough question ^ @grazfather
Thanks. Is set-validator!
vs add-watch
just an inconsistency, then?
@grazfather add-watch
is additive, set-validator!
overwrites.
But wouldn’t add-watch overwrite with a watcher with a matching key? or is the key ONLY used to provide to the function?
True, it does, but the docstring reads as if you are responsible for ensuring the keys are unique for a given reference so maybe that aspect is considered "undefined" behavior?
Either way, most set*
functions have !
and most add*
functions don't.
However, if you repeatedly add-watch
on the same key with the same function, that's idempotent.
add-watch
does an assoc
on internal state so it's safe to call multiple times. set-validator!
actually derefs the ref and runs the validator on it, and then sets the validator into the ref -- so that could throw an exception...
So, yeah, I guess that justifies the !
on it.
(sorry for the slow series of responses, I'm grubbing around in the source code of it all)
(and it's worth repeating that these are just conventions rather than hard and fast rules)
Thank you for the thorough answer!
Heys guys, ive been learning clojure for a couple months now, and really been liking it. for the most part I could do things the clojure way. ;But I cant figure this out. Most of it is Js, so sorry in advance. ; ;Im referring to the allNearbyCells function. ;In createNestedArray (3, 3), given cellId "1-1", it would modify all adjecent objects. ;given "0-0" it would return the top 4 left. so given the middle it would modify all adjacent cells. weather it modifies or returns a new ;object/making it more functional doesnt really matter. Mostly the for loops im trying to get rid of, but cant really think of a clean way of doing it. stringToId: function(string) { //given 'x-y' will return ['x', 'y'] let theId = string.split("-"); //x && y will be turned into numbers, returns array let ID = theId.map(stringNumber => parseInt(stringNumber)); return ID; } allNearbyCells: function(cellId, nestedArray, fn, skipMiddle) { //skipMiddle defaults to false, true applys function passed in to cellId let Id = this.stringToId(cellId); const y = Id[0]; const x = Id[1]; for (let i = x - 1; i <= x + 1; i++) { for (let j = y - 1; j <= y + 1; j++) { //if it dont exist, move on if (!nestedArray[i] || !nestedArray[i][j]) { continue; } //skip the cell that was passedd in if (i === x && j === y) { if (skipMiddle) { continue; } } fn(nestedArray[i][j]); } } } ; createNestedArray(3, 3) -> [[{id: "0-0"}, {id: "1-0"}, {id: "2-0"}], ; [{id: "0-1"}, {id: "1-1"}, {id: "2-1"}], ; [{id: "0-2"}, {id: "1-2"}, {id: "2-2"}]] function createNestedArray (x, y) { let nestedArray = []; for (let i = 0; i < y; i++) { nestedArray.push([]); for (let j = 0; j < x; j++) { //information of individual cell nestedArray[i][j] = { id: `${j}-${i}`, }; } } return nestedArray; )
Are you asking how to do this in Clojure?
Just the allNearbyCells function.
Here's a mostly literal translation of your code in clojure:
(ns cells
(:require [clojure.string :as str]
[clojure.edn :as edn]))
;; Using edn
(defn string->id [s]
(map edn/read-string
(str/split s #"-")))
;; Using java Integer/parseInt
(defn string->id [s]
(map #(Integer/parseInt %)
(str/split s #"-")))
(string->id "1-2")
;; => (1 2)
(defn create-nested-array [x y]
(partition
x
(for [i (range x)
j (range y)]
{:id (str j "-" i)})))
(create-nested-array 3 3)
;; (({:id "0-0"} {:id "1-0"} {:id "2-0"})
;; ({:id "0-1"} {:id "1-1"} {:id "2-1"})
;; ({:id "0-2"} {:id "1-2"} {:id "2-2"}))
(defn all-nearby-cells [id nested-array f skip-middle]
(let [[y x] (string->id id)
dir [-1 0 1]]
(map (or f identity)
(filter some?
(for [x-dir dir
y-dir dir
:let [x2 (+ x x-dir)
y2 (+ y y-dir)]
:when (not (and skip-middle
(= x x2)
(= y y2)))]
(-> nested-array
(nth y2 nil)
(nth x2 nil)))))))
(all-nearby-cells "0-0" (create-nested-array 3 3) nil false)
;; => ({:id "0-0"} {:id "0-1"} {:id "1-0"} {:id "1-1"})
(all-nearby-cells "0-0" (create-nested-array 3 3) nil true)
;; => ({:id "0-1"} {:id "1-0"} {:id "1-1"})
(all-nearby-cells "0-0" (create-nested-array 3 3) #(assoc % :found true) false)
;; => ({:id "0-0", :found true}
;; {:id "0-1", :found true}
;; {:id "1-0", :found true}
;; {:id "1-1", :found true})
Haha good stuff. Thank you, I couldn't figure it out.
My nested array is not actually a nested array, but a nested list, which isn't ideal here. With arrays you could use get-in
, here I used two nth
instead (which is O(n)
for sequences)
Anybody have any idea why I am getting this error for shadow-cljs? P.S "lein run" works perfectly.
Okay a bit of context might be a step in the right direction. I am currently going through the "web development with clojure 3rd edition" book and thats how I ran into this error. I went through all the steps and rewrote the code but I am still unsure of where I went wrong, heres a screenshot of what I get when I remove the ws namespace
I am using sente now but I still don't have access to "ws"
hi, i dont have this book but i did find the reference code. are you requiring guestbook.websockets :as ws
in core.cljs?
for the zipfile i downloaded, see the resources section of https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/
@chetlind_clojure brother i literally had to require guestbook.websockets :as ws bro thank you so much
I am not a shadow-cljs expert by any stretch but I believe you’re trying to require http-kit from a ClojureScript namespace. I believe http-kit is a JVM-only library (no JS/ClojureScript)
Oh I see, the reason why I had it there is because I would like to make use of websockets and when I dont have it there I dont have access to them
Is there a way to compare two data structures which are both a vector of hash-maps, [ {:a :one :b "start"} {:a :two :b "middle"} ,,,]
when ordering is not the same?
The use case is for a (probably quite dodgy) unit test
Each vector has hash-maps that are the same set of values, however, as one vector of hash-maps is generated then ordering of the hash-maps is different
I would prefer not to just try and sort the generated hash-map just to make the test work 🙂
Hmm, I could probably try sort the returned results in from the call in the test assertion... sorting them by the value of the string...
If it’s a dodgy test to begin with - is converting the vectors to sets an alternative?
possibly... thats an interesting thought...
Unless you can have multiple identical maps :-)
the hash-map has the same two keys but different values for each key. I could write a spec for it if I was doing it properly...
You don’t have access to them there with that lib there. It uses a bunch of Java libraries. There’s no way to compile that to js
Look for a websockets library that works on the client
what does it mean if a number is printed as 10N ?
(type 10N) #_ -> clojure.lang.BigInt
is it equal to 10?
(= 10 10N)
true
ah ha..
clojure.core/=
([x] [x y] [x y & more])
Equality. Returns true if x equals y, false if not. Same as
Java x.equals(y) except it also works for nil, and compares
numbers and collections in a type-independent manner.
that's the type independent manner of =
Hello,
I am using next.jdbc to query postgresql. Then I save results into EDN file.
Numbers in range - 2147483648 and 2147483648 are coming as *int*s from jdbc
(because the column is type int4 and not int8).
But once I read the EDN fila via (read-string (slurp "table.edn"))
any number > 10 is changed from int to long because EDN integers are in range 0-10.
What is the most idiomatic way to read these numbers and *int*s again?
@jakub.zika-extern Clojure defaults to Double and Long for numeric types. You would need to cast to a narrower type if you really wanted Integer or int instead of Long.
a minimal example of what you want is (type (clojure.edn/read-string "3"))
to return an Integer or int?
i don't see a way to do that at the reader level. you could walk the data obviously. but why do you specifically need ints?
@seancorfield @dpsutton I am using https://github.com/jgdavey/clj-pgcopy to migrate postgres database. It maps int to int4 and long to int8 - as jdbc reads. I have got a lot of int4 in my database and when I use EDN and everything is casted to longs it fails with incorrect binary data format. One of the obvious solutions is changing every column from int4 in db to int8 😄.
in your insert statements can you do the cast there? dealing with concrete types in Clojure can often be quite challenging
I dont think so. I would use next.jdbc engine which solves my problem but it seems much slower than clj-pgcopy library.
I would like to understand better the deep-code walking macros/walks like in this post http://blog.fogus.me/2013/07/17/an-introduction-to-deep-code-walking-macros-with-clojure/ did you see similar article in this topic? Or github repo? Which is useful?
reminds me of https://www.youtube.com/watch?v=HXfDK1OYpco
Thanks!
I really love Timothy Baldridge courses as at Pivotshare
@dpsutton I see that I can use option when read-string EDN so I might tag some value like #int4 and then convert it back to type i need. https://clojuredocs.org/clojure.edn/read-string
i don't see how that's easier than all of your insert statements mapping longs to ints. or redefining the target type of longs for this project
I have got two databases sharing the same structure. I want to move some data from the 1st database to the 2nd one. There are queries (SELECT * from table limit 100) which creates <file>.edn for every extracted table. Then I want to use pgcopy (clj-pgcopy) to insert these data quickly. If I remap longs to ints - it may not be always possible. If I redefine the target type of longs - it will fail once there will be int8 on db side. The point is - I can not lose the information about data type coming from first db.
I’m experimenting with writing a test where I use with-redefs
to replace clj-http.client
calls using a record live/replay a file pattern.
I try serializing the captured response with pr-str
and save it to disk, then load it again in replay mode using read-string
. However, this fails with a No reader function for tag object
because the Apache HTTP client gets serialized, e.g. :`http-client #object[org.apache.http.impl.client.InternalHttpClient 0x12079bbf …]` . Is there a way to provide a hint to the reader to ignore this tag?
(Maybe a second question is: “Is there another library in Clojure for this style of testing or record/replay?” In the past I’ve used WireMock which just occurred to me would work, though be a bit slower due to the real HTTP traffic)
You can do that @etldan by defining a reader function that does nothing
@blak3mill3r Thank you, and I appreciate the link!
you just need to put a data_readers.clj
file at a root of your classpath, containing a map from symbols (reader shorthands) to symbols (fully-qualified functions that will read a form the way you want, which in your case is to return nil
)
and then control the way they are printed, to match your reader shorthands (see print-dup
and print-method
from clojure.core
)
actually @etldan you might be able to get away with just extending the printing to print a blank string... which the reader will skip
something like this (not tested):
(defmethod print-dup org.apache.http.impl.client.InternalHttpClient
[o ^java.io.Writer w]
(print-simple "" w))
Thank you @blak3mill3r I’ll look into this. I’m assuming these are global - could they be temporarily redefined such as like with-redefs
?
yeah multimethod definitions are global... I am not sure if they can be used with with-redefs
of course you could make the body of the function do whatever you want, including calling another dynamically bound function to do the actual work
That makes sense, thanks !