This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-26
Channels
- # aws-lambda (15)
- # babashka (7)
- # beginners (124)
- # calva (7)
- # cider (19)
- # clj-kondo (26)
- # clojure (261)
- # clojure-australia (3)
- # clojure-dev (10)
- # clojure-europe (45)
- # clojure-nl (4)
- # clojure-uk (6)
- # clojurescript (10)
- # datomic (7)
- # depstar (7)
- # emacs (11)
- # fulcro (41)
- # graalvm (48)
- # helix (1)
- # honeysql (17)
- # inf-clojure (7)
- # introduce-yourself (3)
- # jackdaw (2)
- # lsp (36)
- # malli (2)
- # meander (2)
- # membrane (1)
- # missionary (11)
- # off-topic (17)
- # pathom (83)
- # polylith (15)
- # re-frame (31)
- # reagent (42)
- # sci (35)
- # shadow-cljs (13)
- # spacemacs (13)
- # sql (19)
- # timbre (3)
- # tools-deps (77)
Anyone care to roast a function? I'm trying to get a good idea of how to format Clojure code correctly and this looks wrong for some reason.
(defn ->user-update
"Validates and constructs a user update from the provided body."
[body]
(let [card? (fn [key-value]
(let [[key value] key-value]
(if (= key :card)
[key [:lift value]]
[key value])))]
(into {} (map card? (seq (assoc (select-keys body [:card :user-id :oauth-id]) :updated-at (c/to-sql-time (t/now))))))))
I'm kind of a noob to threading. Could you provide an example?
Oh I think I see what you mean. At the (map card? ...) part
https://clojuredocs.org/clojure.core/-%3E and https://clojuredocs.org/clojure.core/-%3E%3E
At a quick rush:
(-> body
(select-keys [:card :user-id :oauth-id])
(assoc :updated-at (c/to-sql-time (t/now))
seq
(->>
(map card?)
(into {})))
(defn ->user-update
"Validates and constructs a user update from the provided body."
[body]
(->> body )
(let [card? (fn [key-value]
(let [[key value] key-value]
(if (= key :card)
[key [:lift value]]
[key value])))]
(-> body
(select-keys [:card :user-id :oauth-id])
(assoc :updated-at (c/to-sql-time (t/now)))
seq
(->>
(map card?)
(into {})))))
That definitely helps for readability.Oh it's just a dumb way of saying "if it's this key, go ahead and surround it with a [:lift]
Yeah I'm trying that now actually
Like this?
(defn ->user-update
"Validates and constructs a user update from a given body."
[body]
(-> body
(select-keys [:card :user-id :oauth-id])
(assoc :updated-at (c/to-sql-time (t/now)))
(->>
(cond-> (:card body) (update :card (fn [v] [:lift v])))
(into {}))))
I don't think this is right.
We want to pass body, after it's transformed a little, as the first argument to cond->
, not the last (which ->>
would do)
OH, so it's just the last statement of the threading macro?
Yup, I get it now. Nice way of putting everything under one macro. I guess I need to practice writing more functional code. Any good cheat sheet for the clojure core functions?
Haha, it has a good area for transducers. I think that's where I'll go next.
There's a lot there. Have a peak through them, and 90% of the time you ask "surely there's a function for this" there probably is
So feel free to ask in here about "is there a function that does X?" when you come to that point
That's what I kind of like about clojure, there's a function for everything. Meanwhile in JS, I have to conjure some weird JS syntax to do something as simple as cloning a list.
I think I saw someone say there's about 600 functions in clojure.core
but I haven't counted them...
@rosenjcb Are you using clj-time
?
Yes. 🙂
(defn ->user-update
"Validates and constructs a user update from a given body."
[body]
(-> body
(select-keys [:card :user-id :oauth-id])
(assoc :updated-at (c/to-sql-time (t/now)))
(cond-> (:card body) (update :card (fn [v] [:lift v])))))
You know it's deprecated? We're trying to get people to stop using it.
That's what I saw on a quick google search.
Didn't know.
The README on the repo is pretty clear 🙂
I suspect (java.util.Date.)
would be sufficient as a replacement for (c/to-sql/time (t/now))
(the JDBC libraries should take care of converting it to a java.sql.Timestamp
)
Also, if you don't care about the return value but just want to perform side effects, doseq
accepts the same syntax as a for
expression.
I guess a more complete example will make it easier to understand. Laziness can be tricky!
Was sending the data outputted from a for
into jdbc but it was having some issues. And I was thinking it might be a result of laziness
doall
returns back the same passed lazy seq - while forcing side-effects. into
creates a new, realized collection and returns it. Not much insight into the doall
implementation, but the source is easy to follow and see what is happening.
> Was sending the data outputted from a for into jdbc but it was having some issues. And I was thinking it might be a result of laziness
this is highly unlikely - if jdbc reads the value, it will be calculated (btw. nitpick there's no "for loop" in clojure, for
is a list comprehension not a looping construct)
Is there a more succinct way to do both filter
and remove
? Or do I just parse my collection through both of them just like that
Can you explain with a small example collection? Are the filter and remove predicates complements of each other?
Yeap complements. So tgt what is filtered and what is filter will return the entire collection
Hi, I've just started to learn Clojurescript and I was wondering if you could recommend me some resources (courses, books or tutorials). I've developed in several languages (Python, Javascript, Ruby, Java, C, C++) and I am (or was) aware of the principles of functional programming so I don't mind jump into Clojurescript with some intermediate resources.
I know that this is a late reply, but I wrote https://www.learn-clojurescript.com to help JavaScript developers. Let me know if it's useful!
@a.villa.diez I have always found https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f quite a useful list of resources to start from 🙂
I am not sure, how to work with a Java interface from Clojure in this particular case: https://oshi.github.io/oshi/oshi-core/apidocs/oshi/software/os/InternetProtocolStats.html I would like to getTCPv4Stats
but I am doing something wrong. I don't think I can just instantiate the interface since there is obviously no constructor. What I aim to do, is get a list of network connections and their state.
I have a dependency: [com.github.oshi/oshi-core "5.8.0"]
and I import the interface like this (import 'oshi.software.os InternetProtocolStats)
After you import it, you can use (InternetProtocolStats/getTCPv4Stats)
See https://clojure.org/reference/java_interop#_member_access, it's the 4th one down on that list.
I don't think so:
(InternetProtocolStats/getTCPv4Stats)
Syntax error (NoSuchFieldException) compiling . at (/tmp/form-init261843597932239110.clj:1:1).
getTCPv4Stats
Oh goodness, i've completely misunderstood your question
This is an interface
you'll need to find some class that implements the interface, instantiate that, and call the method on it
(.getTCPv4Stats (LinuxInternetProtocolStats.))
, or similar
Ok, thanks. I was hoping I wouldn't have to be platform specific like that...
Thank you all! I was really starting to pull my hair. Not really working with Java much...
I wish to implement a chess game engine in clojure using bitboards. With bitboards you represent the chess board using an unsigned long giving you a bit for each space on the chess board between 0 and 63. However, Java, and therefore clojure, uses signed bits, which makes it impossible to be to use bit-wise operations on the very left most bit, since it will throw an error. Is there a way around this? I saw biginteger as an alternative solution, but bitshift operations are not supported here. I also question how bigintegers might impact the performance
What error do you get interacting with the last bit in a long? this works fine in my repl:
(let [show-bits
(fn [x]
(dotimes [bit 64]
(print (if (bit-test x (- 63 bit)) "1" "0")))
(println))
x (bit-or (bit-shift-left 1 63)
(bit-shift-left 1 25)
(bit-shift-left 1 4))]
(show-bits x)
(show-bits (bit-set x 50))
(show-bits (bit-clear x 63))
(println (bit-test x 63))
(println (bit-test x 25))
(println (bit-test x 4))
(println (bit-test x 0)))
1000000000000000000000000000000000000010000000000000000000010000
1000000000000100000000000000000000000010000000000000000000010000
0000000000000000000000000000000000000010000000000000000000010000
true
true
true
false
yeah, you can do bitwise ops on all 64 bits of a long, if you are treating it as a series of 64 bits the question of sign shouldn't come up at all
Thank you all for your kind answers. It seems to work now using only longs 🙂 - I describe the solution in greater detail here - https://clojurians.slack.com/archives/C053AK3F9/p1627332915264100?thread_ts=1627322982.252400&cid=C053AK3F9
Ah i see, didn' realise they had their own functions. Thanks. I had hoped to use longs, but i guess if that is not possible, biginteger are the best bet
oh, fun, just found this, it has a bitboard impl using bigint https://github.com/mdallastella/vinnik
some of these seems to point to unfamiliarity with working with bit operations, like https://github.com/mdallastella/vinnik/blob/master/src/vinnik/bitboard.clj#L13-L16 uses raising 2 to the 64 power to create a board of all 1s instead of a bitewise not operation
depends, if you stick with biginteger (dec (.shiftLeft (biginteger 1) 64))
should be sufficient
(bit-or (bit-shift-left (bit-not (bit-shift-left 1 63)) 1) 1)
or similar if you want to stick with longs
user=> (Long/toBinaryString -1)
"1111111111111111111111111111111111111111111111111111111111111111"
user=> (count (Long/toBinaryString -1))
64
user=>
if you are a beginner in clojure, I'd caution from spending your learning budget doing heavy bit arithmetic
Clojure, being a hosted language, has a few points of intersection with the platform (the JVM) where you really have to be secure with what all is going on
user=> (bit-shift-left 1 63)
-9223372036854775808
user=> (bit-test -9223372036854775808 63)
true
user=> (bit-test -9223372036854775808 60)
false
I promise you can use all 64 bitsYea i can use all 64 bits, but the problem arrises when i want to bitshift the boards to calculate moves and attacks. If i place a king on the 64th bit, i will not be able to shift it properly. At least not with my current implementation. I get the correct result from every other position than this specific one.
(def not-A-file (unchecked-long 0x7f7f7f7f7f7f7f7f))
(def not-H-file (unchecked-long 0xfefefefefefefefe))
(def not-G-file (unchecked-long 0xfdfdfdfdfdfdfdfd)) ;; Used for knights
(def not-B-file (unchecked-long 0xbfbfbfbfbfbfbfbf)) ;; Used for knights
;;Directions
;; northwest north northeast
;; +9 +8 +7
;; \ | /
;; west 1 <- 0 -> -1 east
;; / | \
;; -7 -8 -9
;; southwest south southeast
;;Bit-shift-left is for positive directions. Right is for negative directions
(defn north-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 8)))
(defn south-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 8)))
(defn east-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 1)))
(defn west-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 1)))
(defn north-east-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 7)))
(defn south-east-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 9)))
(defn north-west-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 9)))
(defn south-west-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 7)))
(defn white-king-moves [bitboards]
"White king can move in 8 different directions
1 2 3
8 K 4
7 6 5
"
(let [white-king-bboard (get-in bitboards [:white :K])
white-pieces-bboard (get-in bitboards [:occupancy :white])
king-clip-file-A-bboard (bit-and white-king-bboard not-A-file)
king-clip-file-H-bboard (bit-and white-king-bboard not-H-file)
move-ne (north-east-one king-clip-file-H-bboard)
move-nw (north-west-one king-clip-file-A-bboard)
move-w (west-one king-clip-file-A-bboard)
move-sw (south-west-one king-clip-file-A-bboard)
move-se (south-east-one king-clip-file-H-bboard)
move-e (east-one king-clip-file-H-bboard)
move-n (north-one white-king-bboard)
move-s (south-one white-king-bboard)
;;Union all possible moves and remove moves where white already has pieces
king-moves (bit-and (bit-not white-pieces-bboard) (bit-or move-ne move-nw move-w
move-sw move-se move-e
move-n move-s))
;;Remove moves that will result in check.
]
king-moves))
(white-king-moves {:white {:K (unchecked-long -9223372036854775808)}
:occupancy {:white 0
:black 2048}})
I use this site to calculate the bitboard positions and what i am expecting - https://gekomad.github.io/Cinnamon/BitboardCalculator/
So in case of 64th bit i would expect the bitboard representing the kings position to be 9223372036854775808 - Then the possible moves would be the 3 bits sorounding it - 4665729213955833856 - However what i return is -18014398509481984
I haven't fully parsed out what's going on here, but a minor style note, most of those usages of unchecked-long
do nothing - it's a function that coerces a runtime value to long even if it's outside range, it isn't a constructor for some special "unchecked" version of a long as a unique type, so using it on literals that are clearly small enough to fit in a Long is strange.
The idea is basically. To calculate the moves of the king, i can move in 8 different directions. BIt shifting in any of these will return a long with a bit set in that position i can move the king. If i union these i get all king moves. The "not-A-file" is for when the king is on the very left file or the very right file. In this case i don't, want to calculate the left or right shifts, since they will set a bit on wrong rank.
4665729213955833856, the number you say represents the 8 positions around the king, but that number only has 3 bits set
user=> (bit-shift-right -1 1)
-1
user=> (unsigned-bit-shift-right -1 1)
9223372036854775807
user=> (Long/toBinaryString (bit-shift-right -1 1))
"1111111111111111111111111111111111111111111111111111111111111111"
user=> (Long/toBinaryString (unsigned-bit-shift-right -1 1))
"111111111111111111111111111111111111111111111111111111111111111"
user=>
Switching to ((unsigned-bit-shift-right) fixed it!! Thank you so much - Also the 64'th position will be the very corner of the chessboard, if the king is here, he only has 3 possible moves. Therefore only 3 set bits 🙂
(unchecked-long (*' -9223372036854775808 -1))
you can use unchecked-longs to turn numbers that are unsigned longs outside the range of long that you get from examples or some oracle into signed longs with the same bit pattern
Yea i can use all 64 bits, but the problem arrises when i want to bitshift the boards to calculate moves and attacks. If i place a king on the 64th bit, i will not be able to shift it properly. At least not with my current implementation. I get the correct result from every other position than this specific one.
(def not-A-file (unchecked-long 0x7f7f7f7f7f7f7f7f))
(def not-H-file (unchecked-long 0xfefefefefefefefe))
(def not-G-file (unchecked-long 0xfdfdfdfdfdfdfdfd)) ;; Used for knights
(def not-B-file (unchecked-long 0xbfbfbfbfbfbfbfbf)) ;; Used for knights
;;Directions
;; northwest north northeast
;; +9 +8 +7
;; \ | /
;; west 1 <- 0 -> -1 east
;; / | \
;; -7 -8 -9
;; southwest south southeast
;;Bit-shift-left is for positive directions. Right is for negative directions
(defn north-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 8)))
(defn south-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 8)))
(defn east-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 1)))
(defn west-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 1)))
(defn north-east-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 7)))
(defn south-east-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 9)))
(defn north-west-one [bitboard]
(bit-shift-left (unchecked-long bitboard) (unchecked-long 9)))
(defn south-west-one [bitboard]
(bit-shift-right (unchecked-long bitboard) (unchecked-long 7)))
(defn white-king-moves [bitboards]
"White king can move in 8 different directions
1 2 3
8 K 4
7 6 5
"
(let [white-king-bboard (get-in bitboards [:white :K])
white-pieces-bboard (get-in bitboards [:occupancy :white])
king-clip-file-A-bboard (bit-and white-king-bboard not-A-file)
king-clip-file-H-bboard (bit-and white-king-bboard not-H-file)
move-ne (north-east-one king-clip-file-H-bboard)
move-nw (north-west-one king-clip-file-A-bboard)
move-w (west-one king-clip-file-A-bboard)
move-sw (south-west-one king-clip-file-A-bboard)
move-se (south-east-one king-clip-file-H-bboard)
move-e (east-one king-clip-file-H-bboard)
move-n (north-one white-king-bboard)
move-s (south-one white-king-bboard)
;;Union all possible moves and remove moves where white already has pieces
king-moves (bit-and (bit-not white-pieces-bboard) (bit-or move-ne move-nw move-w
move-sw move-se move-e
move-n move-s))
;;Remove moves that will result in check.
]
king-moves))
(white-king-moves {:white {:K (unchecked-long -9223372036854775808)}
:occupancy {:white 0
:black 2048}})
Thank you all. I solved it thanks to you 🙂 - https://clojurians.slack.com/archives/C053AK3F9/p1627332915264100?thread_ts=1627322982.252400&cid=C053AK3F9