I’m a bit surprised there isn’t a different-arity version of future-call
that accepts the executor to use as a param (with the current arity one simply passing clojure.lang.Agent/soloExecutor
as it uses now). Seems like it would avoid having to reimplement things
Hmm unexpected … (clojure.set/subset? #{} #{:a :b}) => true
Is that something from set theory? Empty set is always a subset of another set?
Ever element of it is in the other set
It’s vacuously true. An easy way to think of it is to list a counter example. Name an element that is in the empty set that is not in your other set
🙂
@st3fan empty sets of things often have surprising behavior at first glance. (and) ; true
, (or) ; nil
for example.
Interesting
Similarly,
user=> (some some? [])
nil
user=> (every? some? [])
true
The latter is often more surprising, given the docstring says "Returns true if (pred x) is logical true for every x in coll, else false." because no elements are logical true.
And it can be confusing that (every? nil? [])
is of course also true
-- so every element is nil and not-nil at the same time 🙂
But it is true
because there are no elements in []
for which the predicate isn't "logical true".
What you want doesn't exist in core clojure but others have got you covered https://github.com/TheClimateCorporation/claypoole
regarding not having a param for passing an executor, I think it's because it's an implementation detail. I think future
is only meant to fulfill a basic need. anything more complex than that and it would probably be better suited as a stand-alone library rather than a core feature.
Is there a way to evaluate a symbol to use as a keyword? For example, if I have '("A" "some data")
can you give a literal example of what you want to accomplish? is some data a map with keywords and you have a string and you want to look up the value at that keyword entry?
Never mind I found it: (keyword (first '("A" "some data")) gives me what I want: A:
Hi, What is the idiomatic way to convert :two-word
keyword to Two Word
strings?
You can also use this library for similar conversions: https://clj-commons.org/camel-snake-kebab/.
str it, split on "-", map capitize, and then join it back together with a string
(->> (str/split (name :two-words) #"-") (map str/capitalize) (str/join " "))
this often comes up when converting keywords into display items in a UI. You can probably create a better regex to match on underscores and some other common separators if applicable
Hey guys,
Why does :
(first {:a 1, :z 2})
return [:a 1]
(val (first {:a 1, :z 2}))
return 1
BUT (val [:a 1])
throw a ClassCastException
instead of returning 1
as the two statements above would suggest ?
I guess it has to do with the underlying types (PersistentVector vs Map),
But wouldn't it be more consistent to have val
being equivalent to second
in case of a vector with 2 elements ?
Same thing for key
and first
yes its because of the underlying types
user=> (type (first {:a 1}))
clojure.lang.MapEntry
user=> (type [:a 1])
clojure.lang.PersistentVector
clojure has many examples where you can use a generic (second) or specific (val) function
the specific functions are usually more performant
I believe (class (first {:a 1, :z 2})
is a MepEntry class, not PersistentVector, and that key
and val
have special behavior for MapEntry objects that they do not have for regular vectors.
MapEntry objects have a default printed representation that looks like a two-element vector, and I believe operations that you can do on a vector also work on a MapEntry, e.g. nth, first, second, assoc.
But the converse is not true -- some operations like key
and val
work on MapEntry, but not on vectors.
i'm trying to get the sums of all possible pairs of numbers in a vector between i
and i-25
(let [subv (subvec v (- i 25) i)
a (transient [])]
(for [b subv
c subv
:when (> c b)]
(conj! a (+ b c)))
(persistent! a))
where v
is the input vector
why does this return an empty vector?
[]
For is not a loop
That also isn't a correct usage of transients
That is "bashing in place"
does that mean i have to use loop
and handle indices manually?
Dunno
i think if you just use the for loop without the transient you have exactly what you want: a collection of (+ b c)
when (> c b)
. you don't need to accumulate this into another collection if the for builds this collection in the first place
you're building a collection and then for each element in that collection putting it into another collection. just use the first collection without the unnecessary extra collection
cool, but now those sums are in vectors
turns out i dont need a vector at all
(let [subv (subvec v (- i 25) i)]
(for [b subv
c subv
:when (> c b)]
(+ b c)))
is enoughit returns a list which i then turn into a vector
you need random access to this collection?
wdym?
i'm wondering why you need a vector instead of the lazy sequence that is returned
uhh idk actually
i'll go forward with the list
thanks !!
Im doing the clojure farm course and I cannot solve this problem
(defn my_filter
"filters a collection on a predicate"
[collection predicate]
(let [new_collection (seq collection)]
(for [element collection]
(if (predicate collection)
(conj element new_collection)
new_collection))
new_collection)
; Syntax error compiling at (chapter4.clj:13:24).
; Unable to resolve symbol: collection in this context
anyone here who can make this work
for is not a loop
You’re also calling the predicate on the entire collection each time rather than the element
oke, but why is collection not known in the let part ?
@hiredman so I can better use recursion ? or another loop ?
it's kind of funny that this works
user=> (conj (first {:a 1}) :b)
[:a 1 :b]
I think it auto-promotes to persistent vector
hard to say
your code is missing a closing paren, so it doesn't run as is
but if I add a closing paren, I don't get an error
user=>
(defn my_filter
"filters a collection on a predicate"
[collection predicate]
(let [new_collection (seq collection)]
(for [element collection]
(if (predicate collection)
(conj element new_collection)
new_collection))
new_collection)
)
#'user/my_filter
user=>
hmm, I still see a error :
; Syntax error (ClassNotFoundException) compiling at (output.calva-repl:51:22).
; Thread.java:834
that is not the same error
yep, that is another one
what class does it say is not found?
nope, I see only this :
; Syntax error (ClassNotFoundException) compiling at (output.calva-repl:51:22).
; Thread.java:834
clojure.lang.Compiler/analyze (Compiler.java:6808)
clojure.lang.Compiler$InvokeExpr/parse (Compiler.java:3820)
clojure.lang.Compiler/analyzeSeq (Compiler.java:7108)
clojure.lang.Compiler/analyze (Compiler.java:6789)
clojure.lang.Compiler$BodyExpr$Parser/parse (Compiler.java:6120)
clojure.lang.Compiler$FnMethod/parse (Compiler.java:5467)
clojure.lang.Compiler$FnExpr/parse (Compiler.java:4029)
clojure.lang.Compiler/analyzeSeq (Compiler.java:7104)
clojure.lang.Compiler/analyze (Compiler.java:6789)
clojure.lang.Compiler/eval (Compiler.java:7173)
clojure.core/eval (core.clj:3214)
clojure.core/eval (core.clj:3210)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.core/apply (core.clj:665)
clojure.core/with-bindings* (core.clj:1973)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.main/repl (main.clj:414)
clojure.main/repl (main.clj:435)
clojure.main/repl (main.clj:345)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:84)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:56)
nrepl.middleware.interruptible-eval/interruptible-eval (interruptible_eval.clj:152)
nrepl.middleware.session/session-exec (session.clj:202)
nrepl.middleware.session/session-exec (session.clj:201)
java.lang.Thread/run (Thread.java:834)
it isn't part of the stacktrace, it is part of the exception
look at *e
?? sorry this is my first step in clojure. What do you mean with look at *e
are you at a repl?
yep
type in *e
and hit enter
it will show a data representation of the last exception that bubbled up to the top of the repl loop
oke
then I see this :
clj::chapter4=> *e
#error {
:cause "Thread.java:834"
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Syntax error compiling at (/home/roelof/clojure/Learning_in_public/ground_up/.calva/output-window/output.calva-repl:51:22)."
:data #:clojure.error{:phase :compile-syntax-check, :line 51, :column 22, :source "/home/roelof/clojure/Learning_in_public/ground_up/.calva/output-window/output.calva-repl"}
:at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
{:type java.lang.ClassNotFoundException
:message "Thread.java:834"
:at [java.net.URLClassLoader findClass "URLClassLoader.java" 471]}]
:trace
[[java.net.URLClassLoader findClass "URLClassLoader.java" 471]
[clojure.lang.DynamicClassLoader findClass "DynamicClassLoader.java" 69]
[java.lang.ClassLoader loadClass "ClassLoader.java" 589]
[clojure.lang.DynamicClassLoader loadClass "DynamicClassLoader.java" 77]
[java.lang.ClassLoader loadClass "ClassLoader.java" 522]
[java.lang.Class forName0 "Class.java" -2]
[java.lang.Class forName "Class.java" 398]
[clojure.lang.RT classForName "RT.java" 2207]
[clojure.lang.RT classForName "RT.java" 2216]
[clojure.lang.Compiler resolveIn "Compiler.java" 7394]
[clojure.lang.Compiler resolve "Compiler.java" 7357]
[clojure.lang.Compiler analyzeSymbol "Compiler.java" 7318]
[clojure.lang.Compiler analyze "Compiler.java" 6768]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3820]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7108]
[clojure.lang.Compiler analyze "Compiler.java" 6789]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
[clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
[clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7104]
[clojure.lang.Compiler analyze "Compiler.java" 6789]
[clojure.lang.Compiler eval "Compiler.java" 7173]
[clojure.lang.Compiler eval "Compiler.java" 7131]
[clojure.core$eval invokeStatic "core.clj" 3214]
[clojure.core$eval invoke "core.clj" 3210]
[nrepl.middleware.interruptible_eval$evaluate$fn__964$fn__965 invoke "interruptible_eval.clj" 87]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.AFn applyTo "AFn.java" 144]
[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
[clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
[clojure.lang.RestFn invoke "RestFn.java" 425]
[nrepl.middleware.interruptible_eval$evaluate$fn__964 invoke "interruptible_eval.clj" 87]
[clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414]
[clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414]
[clojure.main$repl$fn__9077 invoke "main.clj" 435]
[clojure.main$repl invokeStatic "main.clj" 435]
[clojure.main$repl doInvoke "main.clj" 345]
[clojure.lang.RestFn invoke "RestFn.java" 1523]
[nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 84]
[nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
[nrepl.middleware.interruptible_eval$interruptible_eval$fn__995$fn__999 invoke "interruptible_eval.clj" 152]
[clojure.lang.AFn run "AFn.java" 22]
[nrepl.middleware.session$session_exec$main_loop__1062$fn__1066 invoke "session.clj" 202]
[nrepl.middleware.session$session_exec$main_loop__1062 invoke "session.clj" 201]
[clojure.lang.AFn run "AFn.java" 22]
[java.lang.Thread run "Thread.java" 834]]}
which depending, may or may not be the same ClassNotFoundException
ah
you have a random Thread.java:834 somewhere in the code you are trying to evaluate
which was part of earlier stacktrace, which is why I didn't recognize it as part of the error message
he, I never uses Random anywhere as far as I know
not Random
this is my code in the namespace
(ns chapter4)
; Write a function to find out if a string is a palindrome–that is, if it looks
; the same forwards and backwards.
(defn palindrome?
"checks if a string is a palingdrome"
[word]
(= (seq word) (reverse word) ))
(defn my_filter
"filters a collection on a predicate"
[collection predicate]
(let [new_collection (seq collection)]
(for [element collection]
(if (predicate element)
(conj element new_collection)
new_collection))
new_collection))
no
you are trying to run something else
maybe without realizing it you copied and pasted too much or something
that can be
I think so, because now I see the code compiling
because that error says the expression Thread.java:834
literal appears in your program, and for whatever reason clojure is trying to resolve it as a class, which it isn't, which is why you get the error
now time to fin d out how I can make the predicate part in a call
I give up
(my_filter [(1 2 3 4) (fn [x] (even? x)) ])
error :
; Execution error (ClassCastException) at chapter4/eval17683 (form-init1042520059576704410.clj:20).
; class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')
(1 2 3 4)
is calling 1
as a function on the arguments 2 3 4
. The error message is saying that 1
a "java.lang.Long" can't be invoked (cast to clojure.lang.IFn)
pff, that one needs to be a collection
sure. but you're invoking it, not making a collection
(+ 1 1)
means invoke +
. (1 2 3 4)
similarly means invoke 1
pff, how do I then make it a collection ?
use [] instead
maybe the easiest way is [1 2 3 4]
making it a vector
that's the normal way in clojure also
there's also '(1 2 3 4)
but that's a more limited approach
oke, I give up on clojure . on the code that worked I see now suddenly
; Syntax error compiling at (chapter4.clj:10:1).
; Unable to resolve symbol: defn in this context
often see this happen when you do (in-ns chapter4)
before requiring it
I only do crtl-alt-c crlt-alt-j
thanks for the help butI do not like to fight the whole day against a compiler with error messages that makes no sense
yes, many operations that work on persistent vectors also work on MapEntry, but return an object with class clojure.lang.PersistentVector, not clojure.lang.MapEntry.
For whatever it's worth, you are defining my_filter to take two arguments, collection and predicate, but you only try to pass one argument when you call it, a vector containing the collection and predicate. After fixing the syntax issue with [1 2 3 4]
either use deconstruction in in my_filter, (defn my_filter [ [ collection predicate ] ] (...))
or pass the two parts separately as two different arguments.
@roelof in-ns
is only for debugging, in code it creates broken namespaces
they are fixable, but the easier fix is to just not use in-ns
@roelof You need to load the file before things start to work. (`ctrl+alt enter` if using Calva).
I feel ya about the error messages. But otherwise I kinda like how I am in control of what is defined where, using Clojure.
hi 🙂 I checked https://github.com/bbatsov/clojure-style-guide but didn’t find the following … what do you think about this as a suggestion?
> Only return a literal true
or false
from the body of an if
when you actually need a literal as a result and the if
’s condition doesn’t already evaluate to a literal.
>
> Bad — if a truthy non-literal result works in your context:
> (if (some pred coll) true false)
i'm not sure i'm following. but that repo is open to issues with suggestions for new guidelines and will most likely get some feedback
@fappy Better to say (boolean (some pred coll))
instead of if
Hi I wonder what's the best candidate in Clojure to ceate a loop like in this Java snippet:
public static Socket getListeningSocket() {
for ( int port = MIN_PORT ; port <= MAX_PORT ; port++ )
{
try {
ServerSocket s = new ServerSocket( port );
return s; // no exception means port was available
} catch (IOException e) {
// try the next port
}
}
return null; // port not found, perhaps throw exception?
}
for
? loop
?How can I break on first success (first free port assigned)?
loop
requires a manual recur. recur in your catch
and you'll stop on the first successful port
ah sorry, can't recur from the catch. so just catch and return a sigil and check that against the sigil
Thx @dpsutton What is a "sigil"?
Thanks @dpsutton, it's exactly what I needed! And TIL sigil too. 😉
some recognizable value that can't come from starting a server. can do (Object.)
or ::bad
here's an example that just uses nil as the sigil
Hi community. I am trying to make a https://docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/FileNameExtensionFilter.html with Java interop. This is what I’m doing:
(ns filter.core
(:import (javax.swing.filechooser FileNameExtensionFilter))
....
(def fnef (FileNameExtensionFilter. "CSV files", "csv"))
However, I’m getting the following error message:
Cannot cast java.lang.String to [Ljava.lang.String;
Can someone please tell me what I’m doing wrong? I’m a bit flummoxed! 😩Given [1 2 3 4 5]
how do I generate [1 2] [2 3] [3 4] [4 5]
? - Is there a convenience function for this?
(partition 2 1 [1 2 3 4 5])
🙂
https://clojure.org/reference/java_interop#_vararg_methods
that constructor uses varargs: FileNameExtensionFilter(String description, String... extensions)
you need to make the array that is used
(javax.swing.filechooser.FileNameExtensionFilter. "CSV files" (into-array String ["csv"]))
(I think I finally have all the pieces for Day 7 of Advent of Code)
Ah, I see you cross-posted this in #interop as well. We prefer folks not cross-post questions since it can waste people's time replying in one channel, not realizing someone else has already helped you in another channel.
I’ll delete there.
Thanks for your help!
(saved you the trouble -- I deleted your Q and my responses from there @scotto)
Great, thanks. Sorry for the faux pas, @seancorfield
The variadic interop catches folks out all the time. No worries!