Is there a way to repeatedly call a function, feeding it its own output?
(foo (foo (foo (foo 42))))
Check out iterate. (Iterate foo 43)
oh so i would grab (last (take 1000 (iterate foo 42))
Maybe that is nth
Working on an old Advent of Code puzzle .. so odd .. this works (take 2 (iterate simulate-motion system))
But when I hit 3 .. (take 3 (iterate simulate-motion system)))
.. class clojure.lang.LazySeq cannot be cast to class
Hm again I am bitten by lazy seqs
(defn simulate-motion [system]
(->> system
(system-apply-gravity)
(map planet-apply-velocity)))
The last map
turns my system
(a vector) into a lazy seq
@st3fan Use mapv
?
wonderful!
I should really just read clojure.core
LOL
clojure.core is just really interesting generally to see the language build itself
Hi! Please let me know if this is the wrong place, but I'm learning Clojure and have a simple problem I'm mystified by
Clojure is telling me that two (what appear to be identical) strings are not equal, but only in the context of this one function.
(defn any-chars-match
"Checks if any chars in a string match the single char in the second string. If any do, return true. Otherwise return false."
[comparisonChars checkChar]
(reduce (fn [passedVal compareChar]
(if (= compareChar checkChar) ;; This always evaluates false
(reduced true)
false))
false
(seq comparisonChars)))
another thing that would have helped is prn
instead of println
-
(ins)user=> (println ["k" \k])
[k k]
nil
(cmd)user=> (prn ["k" \k])
["k" \k]
nil
(there's also pr-str
for getting the pr behavior inside arbitrary output from println / format)
How are you all so helpful
This is my first interaction w/the Clojure community - posted a question and multiple helpful replies in minutes. Never really seen this before. ๐
haha, we try
Tried logging each value and the comparison, but that still looks identical
Could someone tell me what I'm missing? Read up on the = function, tried using identical?, still no idea
@st3fan You might find this (early access) book valuable: https://www.manning.com/books/clojure-the-essential-reference
Iโm away from keyboard but i think the issue is that compareChar is a char and checkChar is a string in your example. does (checkChars โkkโ \k)
work?
That was what I was about to say: you're comparing characters to a string.
When you do seq
on a string, you get a sequence of characters, so (seq "kk")
is (\k \k)
and then you're comparing \k
against "k"
which are not equal @sam694
Ah, knew I was missing something dumb - should've checked the types
Thanks for the quick reply @smith.adriane @seancorfield, really appreciate it
and remember to play around in your repl (seq "kk")
probably would have shed some light
to mimic what your (seq comparisonChars)
is doing. ironically, the answer is in your variable name ๐ comparison`Chars`
I did that very thing in the REPL, but I didnt put 2 and 2 together that chars were a different data type than strings. Learned today to pay more attention to such things lol
Coming from JavaScript, which doesn't use the distinction
yeah. clojurescript is the same way due to that.
its a surprise for sure
part of the distinction is driven by using the built in Java types (which dramatically helps performance). not sure if the design would be the same if reusing the built in java string and char types wasn't as beneficial
Trying to make a websocket app using http-kit, Sente and Reitit. Something is broken and don't know what, browser says it fails to connect, gets some 406's back from the websocket requests. The code is still minimal and nearly identical to working Sente examples except I'm not using Compojure, so I'm stumped on what is the problem... The relevant files are router.clj and websocket.clj at https://gitlab.com/salohonka/tic-tac-toe/-/tree/master/src/clj/tic_tac_toe. I've tried to substitute http-kit for Jetty9 and Reitit for Compojure, but no luck :thinking_face:
Hi. I have a newbie question around plumatic.schema. Given this simple schema, how would I indicate either foo
or bar
must be provided? (one or the other must be there, but not both)
[{
:id s/Int
:name s/Str
:foo s/Str
:bar s/Int
}]
Oo a websocket app, nice! Tell me more about how you are hosting your server? nginx? apache? I think websockets need a special outer layer, too.
Usually I use all of Sente if working on a real-time app, and hack with a machete. But also be mindful that it might need a reverse-proxy (apache) or something similar (for nginx) ... hope that helps. if not, i am confident we can get down to the bottom of it.
So here you have it .. I'm working on some Python code for work and I just C-c C-c
to try out a code snippet
PythonREPL?
Not using any dedicated webserver, it's a hobby project. Using Sente for both back and front, but I don't think the problem lies with Sente itself, as using just http-kit and it's builtin websocket handler also returns 406's
I will try later if it's a configuration/computer problem by making an empty lein project, adding only http-kit and seeing if that will return 406's as well. If it does, I'll start something without websockets
Oh you're running it locally?
Hmmmmmm. curl from the command-line can be helpful to see what's coming back, too.
I've tried a websocket tester, not curl in particular, but it does connect successfully to other websockets so i'm sure it's the server. First get/handshake returns 101, but then any request after 406's. If you are interested, clone and run the project
How do I take something like this and turn it into a map:
((foo bar) (baz qux))
-> {:foo "bar", :baz "qux"}
is (foo bar)
a sequence of symbols?
generally it would be into
No they are strings. I am trying (map #(into {} %))
but I get:
java.lang.Character cannot be cast to java.util.Map$Entry
entries need to either be Map$Entry or 2-element vectors
(into {} (map (fn [[k v]] [(keyword k) v])) '(("foo" "bar") ("baz" "qux")))
lists don't allow indexed access
(zipmap (map keyword (map first coll)) (map second coll))
maybe?
basically im trying to convert a string like โfoo:bar baz:quxโ into a map {:foo "bar", :baz, "qux"}
. Iโm using re-seq
but maybe thereโs an easier way?
that seems fine. can also do a straightforward clojure.string/split
(into {}
(map (fn [s] (let [[k v] (clojure.string/split s #":")]
[(keyword k) v])))
(clojure.string/split "foo:bar baz:qux" #" "))
oh the destructing in that let binding is slick
and just to make it clear for this channel, i used clojure.string/split
so it was clear what function i was using but you should require that in your namespace and alias it.
Any time you are using first/second/nth that should be a clue to use destructuring
(->> (input "resources/day4.txt" #"\n\n")
(map #(clojure.string/replace % "\n" " "))
(map #(clojure.string/split % #" "))
(map #(let [[k v] (clojure.string/split % #":")]
[(keyword k) v]))
(map #(into {} %)))
Am I missing something here? clojure.lang.PersistentVector cannot be cast to java.lang.CharSequence
you are calling a string operation on a vector
if you look at the stack trace it should show which step is actually doing so
your split will return a vector and then you're calling split on that
always helpful to do all of the mapped functions on a single thing and make sure it works and then map them over the whole collection. and a sequence of maps like this you could just combine them into one function
I did a very different solution for parsing the input .. check the Answers thread on #adventofcode ๐
ie, (->> col (map f) (map g))
could just be (map (comp g f) coll)
. then its very easy to see that the composition works in the single case and therefore necessarily works on the collection
(and here don't literally use comp
but make a single function which does what you want to "one thing")
yeah - that stack of #() blocks is much less clear than a single function doing each of those steps would be
in fact, you probably want (->> (input ...) (map (fn [el] (-> el (string/replace ...) (string/split ...) ...)))
you can stil use an arrow, but do it in the more useful place
and stylistically, make a function that takes the input file and returns a sequence of the lines (doing all the #"\n\n" stuff and splitting. then a single function that processes a single line. and then (map process-line (get-input "resources/day4.txt"))
. makes it very easy to call process-line
on a literal "foo:bar baz:quux" to check yourself
Created an empty project, added http-kit as a dependency and wrote
(defn handler [req]
(hk/as-channel req {:on-open (fn [_] (println "connection"))
:on-receive (fn [_ msg] (println msg))}))
(defn -main [& _args]
(hk/run-server handler {:port 3000}))
which did work, so the problem is project specific. Since the app is going to be very simple, I might just drop Sente on the backend and use http-kits own websocket handlinghttps://github.com/dpsutton/advent/blob/master/2018/src/advent/01.clj#L14-L16
an example here if you wanted to see
What's a nice function for taking a seq as input and returning all (unordered) pairs where no element is paired with itself?
I thought about math.combinatorics, then thought I'd write a nested for, then noticed I'd get more pairs than i wanted
(into #{} (for [a lst b lst :when (not= a b)] #{a b}))
:male-cook::skin-tone-2: ๐
thank you
(ins)user=> (def lst (range 10))
#'user/lst
(ins)user=> (into #{} (for [a lst b lst :when (not= a b)] #{a b}))
#{#{6 3} #{7 1} #{4 3} #{0 1} #{7 5} #{7 6} #{3 5} #{0 4} #{0 9} #{0 7} #{5 8} #{7 3} #{4 8} #{0 3} #{2 8} #{9 5} #{9 8} #{6 5} #{0 6} #{1 4} #{1 8} #{6 8} #{7 4} #{6 9} #{4 6} #{6 2} #{7 2} #{3 8} #{1 6} #{1 5} #{4 2} #{7 9} #{1 3} #{1 2} #{0 2} #{4 9} #{3 9} #{1 9} #{2 5} #{4 5} #{7 8} #{3 2} #{2 9} #{0 8} #{0 5}}
rule 0 of clojure: use the data type that gets the closest to the behavior you need
that will exclude a bit too much if the source collection is not distinct
(let [coll [:a :b :c :a]]
(for [i (range (count coll))
j (range (count coll))
:when (not= i j)]
(into #{} [(nth coll i) (nth coll j)])))
not sure if that's important for you. some of these sets would be single element sets
I took "no element is paired with itself" to mean equality, not input position
based on "unordered pairs"
the source collection happens to be distinct
and yeah the operation i'm feeding this data to is commutative
Hello, when I do (Integer/parseInt "1")
I get back 1
but when I do (map Integer/parseInt ["1" "1"])
I am getting the following error Unable to find static field: parseInt in class java.lang.Integer
Integer/parseInt is not a function but a java static method
(map #(Integer/parseInt %) ["1" "1"])
wrap it in an anonymous function
(map #(Integer/parseInt %) ["1" "1"])
Oh I see, thank you very much guys!!!
I need to write that down in my Clojure notes ๐
There's also a function I think in core (can't remember which) to convert a method to a function, but just wrapping it in an anonymous function is more common and convenient most of the time.
Also: https://clojure.org/guides/learn/functions#_java_methods_vs_functions
memfn
is that but generally it's not worth using because it introduces reflection
Could use (map clojure.edn/read-string ["1" "2"])
Hum... so it does something funkier then just doing (fn ~name [& args#] (. method ~@args#))
is there any difference between using edn
reader and a java static method?
edn/read-string
will read pretty much Clojure form -- hash maps, vectors, as well as numbers, strings etc. Generally, your Java static methods are going to parse just one specific thing.
It depends on your use case. They parse thing differently. If you want an Int back, better use Integer/PartseInt. If you are okay getting any type of number back (or possibly even other types like getting a string, a vector, erc. Then you can use edn read-string. Where as ParseInt will throw an error if the thing you have can't be parsed as an Integer.
well, read-string will never return an Integer, only Long :)
for this particular case, I would use Integer/parseInt (or Long/parseLong)
well it's effectively same
Thank you all! Very much appreciated the extra info ๐
it's ensuring that type hints on memfn will transfer
(clojure.edn/read-string {:readers {'an-int int}} "#an-int 42")
๐....for some definition of "never" :)
Or BigInt if the number is big...?
Oh, so doing that somehow limits the ability of the compiler to not use reflection? Versus wrapping it in an anonymous function?
Yeah why not. Chime in again if you run into any issues ^.^
type hints on memfn will work (because the impl ensures they are transferred into the interop call)
there's nothing magical here wrt the compiler or reflection
I can conditionally add something to a vector based on a condition, with when
.
(def whatev true)
[1 2 3 (when whatev 4)]
Is it possible (similarly) to conditionally add a map entry using when
? This doesnโt work (fails with Map literal must contain an even number of forms
):
{:a 1 :b 2 (when whatev (:c 3))}
that unconditionally adds either nil or 4
(cond-> [ 1 2 3] whatever (conj 4))
and (cond-> {:a 1 :b 2} whatever (assoc :c 3))
are the standard ways to do this
ah, that makes more sense. thank you
(merge {:a 1 :b 2} (when whatever {:c 3}))
and (into [1 2] (when whatever 3))
are also alternative ways to do this.
Hum, I guess I'm just confused then, say Class/foo is overloaded and I do:
(map #(Class/foo %) coll)
;; or
(map (memfn Class/foo) coll)
Won't they both use reflection?Oh, I guess memfn doesn't even work for static
But ok, ignoring that, is there any difference in terms of reflection between:
(map (memfn toUpperCase) ["a" "b"])
("A" "B")
;; and
(map #(.toUpperCase %) ["a" "b"])
("A" "B")
Is there a partition-by that can throw out the โmarkersโ ?
For example I partition on nil but donโt want the nils. I use take-nth to skip them now. Would be nice to leave that out.
Maybe the answer is: donโt be afraid to compose pipelines