This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-01-27
Channels
- # announcements (4)
- # asami (6)
- # aws-lambda (1)
- # babashka (38)
- # babashka-sci-dev (20)
- # beginners (87)
- # calva (67)
- # cider (19)
- # clerk (7)
- # clojure (102)
- # clojure-europe (52)
- # clojure-filipino (1)
- # clojure-hungary (4)
- # clojure-nl (1)
- # clojure-norway (6)
- # clojure-sweden (3)
- # clojure-uk (1)
- # cursive (13)
- # data-science (7)
- # datomic (8)
- # deps-new (1)
- # emacs (3)
- # fulcro (16)
- # graphql (3)
- # humbleui (3)
- # kaocha (3)
- # leiningen (3)
- # malli (3)
- # off-topic (14)
- # pathom (34)
- # polylith (4)
- # rdf (12)
- # reitit (3)
- # releases (1)
- # remote-jobs (7)
- # rum (2)
- # sci (22)
- # shadow-cljs (115)
- # tools-deps (26)
- # tree-sitter (29)
Hey all, running into a weird issue. So I am trying to write a method that’ll take a number as input and return the number which is smaller than current number and is a power of 2. Eg: enter 257 will return 256, enter 255 will return 128.
(def possible-values (map #(int (Math/pow 2 %)) (range)))
(defn get-just-smaller [value]
(last (filter #(>= value %) possible-values)))
(get-just-smaller 5)
My code when I run first time throws IllegalArgumentException
with ; Value out of range for int: 2.147483648E9
error. It works the second time I run in same REPL. If I remove casting to int
program goes into an infinite loop 😞. As per my understanding filter and map both return lazy sequence but I guess what is happening is filter
is simply trying to use possible-values
as an unbounded array. Now one approach I can take is only to generate values less than value
by converting possible-values
to a function and looping by passing the target value. However, is there a way to make this code work?so an infinite sequence input to filter results in a sequence that in theory is finite, but never arrives at its end, so last can never know when it has arrived at the last element to return
Or drop-while
and first
(instead of last
)?
(and a reversed condition)
your (range ) function is empty so it uses the defaults, this implies (range INF), also why without the loop it is an infinite loop
where start defaults to 0, step to 1, and end to
infinity.
https://clojuredocs.org/clojure.core/range
the (int ) is hitting the upper bound memory allocation for Java's Integer
A constant holding the maximum value an int can have, 2^31-1.
https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
(range 31) works fine
(range 32) gives your error
user=> (def possible-values (map #(int (Math/pow 2 %)) (range 31)))
#'user/possible-values
user=> possible-values
(1 2 4 8 16 32 64 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824)
user=> (def possible-values (map #(int (Math/pow 2 %)) (range 32)))
#'user/possible-values
user=> possible-values
Error printing return value (IllegalArgumentException) at clojure.lang.RT/intCast (RT.java:1255).
Value out of range for int: 2.147483648E9
it works the second time because instead of re running the (def possible-values ) it uses the values that were stored in possible-values until the crash which is equivalent to (range 31)something to keep in mind is you are dealing with binary integers, so there may be a faster way to find the next smaller power of two using bit twiddling
Thanks @U0NCTKEV8 take-while
worked. There is such a small wording difference in their documentation.
Thanks @U04V70XH6 will try drop-while
as well.
@U03GLUMEQSF Thanks for responding, I already understood the part why it was failing, just curious if there is an alternative to filter which works.
I don't know if this is a good solution, but it is definitely a solution:
(def pow2s (map #(int (Math/pow 2 %)) (range)))
(defn just-smaller-pow2 [value]
(some (fn [[k v]]
(when (> k value) v))
(map (fn [k v] [k v])
pow2s
(cons 0 pow2s))))
(just-smaller-pow2 5)
; =>
4
The map
creates a lazy seq of pairs of [pow2, 1-pow2-below-that]
, filling in 0
for the 1-lower of 1
.
I think nil
instead of 0
would also be perfectly reasonable. Depends how you want to deal with inputs that are the correct type of int
but are essentially invalid.
Then use some
to look for the first pow2
that is higher than the input, and return the corresponding 1-pow2-below-that
.(let [l2 (Math/log 2)]
(defn log2 [x]
(/ (Math/log x) l2)))
(defn your-fn [x]
(long
(Math/pow 2 (Math/floor (log2 x)))))
actually depending on how you want the actual powers of 2 to break…
(defn your-fn [x]
(if (zero? x)
x
(Long/highestOneBit (dec x))))
(defn your-fn [x]
(Long/highestOneBit x))
Ok using Sean's tip but with take-while...
I am unsure if this is the best place to ask this but - has anyone checked out https://cleancoders.com/series/clean-code/functional-programming? Clean Coders really made me a better java dev - or it fast tracked the java road path - SOLID / Design Patterns / Good software habits / refactoring etc. I am new to clojure and 90% of the code I write at work is going to be clojure from now on.
I haven’t tried that so don’t have answer to your exact question. But Exercism is pretty good along with book Programming Clojure. At this point I am able to read other people’s solutions on Exercism and can appreciate really elegant solutions 😛
Huh cool!
I haven't heard of Exercism before
It doens't seem to be too featured. I will definitely do it though if its free
lucky you! I hear Uncle Bob is a big Clojure fan. I am not familiar with Clean Coders. You might like Paul Graham's "On Lisp" when it comes to Lisp-y coding. Free PDF: http://www.paulgraham.com/onlisptext.html
> It doens’t seem to be too featured. I will definitely do it though if its free Yeah but their CLI is free and their questions are fairly simple for beginners. They also have a VSCode plugin which helps you with test run and quick submission.
https://github.com/oxalorg/4ever-clojure There's also the venerable 4clojure series, which if you haven't already seen, is a good way to familiarize yourself with the standard library and its idioms.
Hello team,
I am just starting with Clojure and Calva and I am testing them with a very simple example.
The structure of my project is:
• time
◦ deps.edn
• src
◦ time.clj
The content of the files deps.edn and time.clj is as described in the section "Writing a program" at https://clojure.org/guides/deps_and_cli.
I then execute the command: Calva: Start a project and connect, selected my directory and type deps.edn.
The output in the terminal shows an error and I do not get connected to the REPL.
Terminal output:
clojure -Sdeps '{:deps {nrepl/nrepl {:mvn/version,"1.0.0"},cider/cider-nrepl {:mvn/version,"0.28.5"}}}' -M -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware]"
Missing required argument for "-M ALIASES"
Jack-in process exited. Status: 1
What am I missing here?
I’m sorry you’re having issues. I don’t know how to use calva (but lots of people do, it’s very popular). I’m sure you can find some help by asking this question in #CBE668G4R where lots of people will be able to point out what’s going on
Thank you very much... Doing it just now!
Here works fine, @U04LNEP9KC6, and of course you are also welcome to the #CBE668G4R channel!
I can't get it working...
I'm trying to understand why this happens. Saw an issue on Github about it too this morning. Maybe that was you, I now realize.
yes, it was me... 🙂
yes, it is... what I noticed is that the call to clojure doesn't starts with "java -jar '/root/.vscode-server/extensions/betterthantomorrow.calva-2.0.326/deps.clj.jar' -Sdeps '{:deps {nrepl/nrepl ..." as when I first used the fire up Getting Started
it is like it's not linked to calva...
deps.edn
should be in the root. Check if that helps. If it does then we need to fix a better UI in Calva.
nope 😞
it is in the root of the project...
{:deps {clojure.java-time/clojure.java-time {:mvn/version "1.1.0"}}}
One complication is that I am testing on a devcontainer but the Getting Started worked perfectly...
Thank you very much!
clojure --version Execution error (FileNotFoundException) at http://java.io.FileInputStream/open0 (FileInputStream.java:-2). --version (No such file or directory) Full report at: /tmp/clojure-12876054732791771324.edn [email protected]:/workspaces/clojure# clojure Clojure 1.10.1 user=>
1.10.1, but there was an error trying to get the version directly
Do you know where it is installed? If so you could try rename it so that Calva doesn't find it, and try if it works then.
I can set the full project in a git repo if that helps...
clojure is in bin: /usr/local/bin/clojure
With devcontainer and all? That would be great. I don't think it is about the devcontainer anymore, now that it seems it is the clojure
executable that is funny. But a repo with your setup would be good anyway.
yes, sure...
I now see that Calva has a setting for using old clojure
versions. Search for ”Calva deprecated” in VS Code setting and enable Use Depecrated Alias Flag
Calva version: v2.0.327
great!!
Thank you very much!! Really appreciated!! And... I will, I am super excited to work with clojure/calva!!
btw, a more standard structure of the project is:
• deps.edn
• src
◦ some_app_namespace
▪︎ time.clj
Making the ns
form in time.clj be:
(ns some-app-namespace.time)
It shouldn't matter, but I know there are tools that assume this structure.great!! thank you!
NB: It should be underscores separating the words in some_app_namespace
in the directory name, and dashes in the ns
form. ( Super easy mistake to do to use dashes in the filename. I actually wrote it wrong first and updated the comment...)
Wow!! this is subtle... 🙂 thank you!
Here's a nested data structure:
(def data [
{:name "a" :children [
{:name "b" :children [
{:name "c" :children []}]}]}])
Wanted result:
;; search for "a" -> will return [{:name "a" :children []}]
;; search for "b" -> will return [{:name "a" :children [{:name "b" :children []}]}]
;; search for "c" -> will return [{:name "a" :children [{:name "b" :children [{:name "c" :children []}]}]}]
It's like cutting branch. Any ideas?
What should be the result for search for "d"?
Can one element have more children? Something like:
(def data
[{:name "a" :children [{:name "b" :children [{:name "c" :children []}]}
{:name "d" :children []}]}])
First attempt:
(def data
[{:name "a" :children [{:name "b" :children [{:name "c" :children []}]}
{:name "d" :children []}]}])
(defn in-tree? [data item]
(.contains (tree-seq associative? identity data)
[:name item]))
(defn search-name [{:keys [name children] :as data} searched-name]
(if (= name searched-name)
(assoc data :children [])
(assoc data :children [(->> children
(filter #(in-tree? % searched-name))
(#(search-name (first %) searched-name)))])))
(defn search [data searched-name]
(when (in-tree? data searched-name)
(search-name data searched-name)))
(search (first data) "a")
=> {:name "a", :children []}
(search (first data) "b")
=> {:name "a", :children [{:name "b", :children []}]}
(search (first data) "c")
=> {:name "a", :children [{:name "b", :children [{:name "c", :children []}]}]}
(search (first data) "d")
=> {:name "a", :children [{:name "d", :children []}]}
(search (first data) "e")
=> nil
Second attempt (example calls are the same):
(defn in-tree? [data item]
(.contains (tree-seq associative? identity data)
[:name item]))
(defn search [{:keys [name children] :as data} searched-name]
(when (in-tree? data searched-name)
(if (= name searched-name)
(assoc data :children [])
(assoc data :children [(into {} (mapcat #(search % searched-name) children))]))))
depending on what else you’re trying to do, clojure.zip
might be useful to edit and navigate the tree
@U1Z392WMQ thank you for a hint 🙂
After playing around with the code I had lower my desired requirements.
Now just want to check if tree of tags str/includes? substring. e.g
Can I use tree-seq for this?
For a real use case of this functionality see my site https://culturevein.com/tags
So far I have this:
(def data [
{:name "a" :children [ {:name "b" :children[]}
{:name "c" :children [
{:name "d" :children []}]}]}])
(defn includes-in-tags-tree? [tags substr]
(loop [tag tags]
(if (and (:name tag) (clojure.string/includes? (:name tag) substr))
true
(if-let [child (first (:children tag))]
(recur child)))))
(includes-in-tags-tree? (first data) "a") ;; => true
(includes-in-tags-tree? (first data) "b") ;; => true
(includes-in-tags-tree? (first data) "c") ;; => nil -> should be true
(includes-in-tags-tree? (first data) "d") ;; => nil -> should be true
it doesn’t look very idiomatic IMO, but another powerful option is https://github.com/redplanetlabs/specter
Something like this?
(defn includes-in-tags-tree? [tags substr]
(->> (tree-seq associative? identity tags)
(some #(and (map-entry? %)
(let [[k v] %]
(and (= k :name)
(str/includes? v substr)))))))
(includes-in-tags-tree? (first data) "a") ;; => true
(includes-in-tags-tree? (first data) "b") ;; => true
(includes-in-tags-tree? (first data) "c") ;; => true
(includes-in-tags-tree? (first data) "d") ;; => true
thank you @U01RL1YV4P7 you are very kind and helpful
that's really elegant solution.
But I'm a little surprised with 'and' condition
(some #(and (map-entry? %) and (and (= k :name)
I would use 'if'.
Is this is the way to do it or personal preference ? @U01RL1YV4P7
So, you want to write something like (if ... true false)
? You shouldn't do that- see https://github.com/bbatsov/clojure-style-guide#converting-something-to-boolean.
I would write :
(defn includes-in-tags-tree? [tags substr]
(->> (tree-seq associative? identity tags)
(some #(if (map-entry? %)
(let [[k v] %]
(if (= k :tag_name_lowercase)
(str/includes? v substr)))))))
hmm... I'm not sure this the right case 'Converting Something to Boolean'. I understand code this way. with 'and': 1. check - (map-entry? %) - if true proceed to next form, 2. check - can bind key & value to symbol k & v - if true then whole 'and' is true and will proceed further But I understand that '(let [[k v] %]' will be always true, it is always possible, if '(map-entry? %)' is true. So I would use just 'if' => '(if (map-entry? %)' then just bind symbols, don't need to check if CAN bind those value and return true if can.
That will work, I'm just more used to and
and or
(and some
expects some predicate, and small predicates joined with and
look more like predicate) ... and and
and or
are macros and expand to nested if
s, so it actually doesn't matter.
Trying to quiet some reflection warnings, how can I annotate the type of "an array of SomeClass"? (clojure has ^ints
etc. for some base classes, and I can do ^SomeClass
for a single item)
and an example from clojure.java.shell https://github.com/clojure/clojure/blob/master/src/clj/clojure/java/shell.clj#L52