This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-19
Channels
Hi everyone. I want to know what would be the idiomatic way to do something like this in clojure: To find the first power (exponent) of 2 which is greater than a give number. (So for 10 it is 2^4, for 5 it is 2^3) In python my first instinct would be to do something like this:
def find_closest_exponent(num, base=2):
power = 0
while num > 1:
num = num / base
power += 1
return power
In clojure my first instinct was something like this:
(defn find-closest-exponent [num base]
(loop [power 0 acc num]
(if (< acc 1) power
(recur (inc power) (/ acc base)))))
This is good enough and it works, I'm just trying to expand my thinking if there are other ways you would use to solve something like this?(Sorry, don't know if there's an equivalent in Clojure, but Common Lisp has it, so not impossible, I guess.)
I would probably grow acc from 1 and compare it to num instead, but that's just my personal taste, perhaps
Thanks I tried porting the python code as-is using (while)
in clojure, but that meant I had to mutate the variables which didn't feel right
(also off topic, we both have a Rurourni Kenshin profile picture haha)
huh! 🙂 yeah, but I didn't even watch it, I think (even though I have this avatar pic for like 20 years or something)
Ah I see! It's wonderful though if you ever get the time to watch. 🙂
a really memory inefficient solution:
(defn closest-exponent [num base]
(->> (iterate #(/ % base) num)
(take-while #(> % 1))
count))
@U0GRKUGLQ well, I think its memory requirements are O(1), so I wouldn't call it memory inefficient 🙂
it's actually O(logbase(num))
since using take-while
will keep the sequence in-memory before counting
extracting this counting logic:
(defn count-while [pred coll]
(or (->> (map-indexed list coll)
(drop-while #(pred (second %)))
ffirst)
(count coll)))
(defn closest-exponent [num base]
(->> (iterate #(/ % base) num)
(count-while #(> % 1))))
this would be o(1)
memoryI don't think so, there's no reason for take-while
not to return a lazy-seq
, and count
doesn't keep head
looks like the perfect use case for memoize
if you're willing to do a bit of java interop and bit shifting, then the Long
and Integer
classes have some methods (e.g. highestOneBit
) which might allow you to do this in constant time 🙂 I don't have a repl handy so I can't check whether that function does what I think it does.
perhaps (fn [i] (* 2 (Long/highestOneBit i)))
is enough
binary h4x, very l33t.
Thanks everyone! Thanks caio, although I did not understand what was happening with your code at first, after hours of http://clojuredocs.org and giving it some thought now it looks straightforward and wonderful!
Hi folks When i want to add this block to ns i get following error. Can u figure out whats happening here?
(ns something
(:import
(java.util.concurrent.Callable)
(java.util.concurrent.ExecutorService)
(java.util.concurrent Executors)))
Syntax error macroexpanding clojure.core/ns at (core.clj:1:1).
() - failed: Insufficient input at: [:ns-clauses :import :classes :package-list :classes] spec: :clojure.core.specs.alpha/package-list
(java.util.concurrent.Callable) - failed: simple-symbol? at: [:ns-clauses :import :classes :class] spec: :clojure.core.specs.alpha/import-list
:import - failed: #{:refer-clojure} at: [:ns-clauses :refer-clojure :clause] spec: :clojure.core.specs.alpha/ns-refer-clojure
:import - failed: #{:require} at: [:ns-clauses :require :clause] spec: :clojure.core.specs.alpha/ns-require
:import - failed: #{:use} at: [:ns-clauses :use :clause] spec: :clojure.core.specs.alpha/ns-use
:import - failed: #{:refer} at: [:ns-clauses :refer :clause] spec: :clojure.core.specs.alpha/ns-refer
:import - failed: #{:load} at: [:ns-clauses :load :clause] spec: :clojure.core.specs.alpha/ns-load
:import - failed: #{:gen-class} at: [:ns-clauses :gen-class :clause] spec: :clojure.core.specs.alpha/ns-gen-class
Thanks @seancorfield, really excited to learn it. There was a lot of useful advice in the responses!
Is it better to use (Long/parseLong "10")
or (long (bigdec "10"))
to coerce a string to a long?
The former
is there a reason why there's a bigdec
constructor taking a string but there is no long
constructor taking a string?
I can't seem to use Long/parseLong as a function in an update: (update {:a 1 :b "2"} :b Long/parseLong)
this fails: Unable to find static field: parseLong in class java.lang.Long
@michael819 it's because it's not quite a function, it's a static java method; try using #(Long/parseLong %)
instead?
Hmmm it's not compatible with cljs either so it causes a build warning... Need to figure something out that will work for both. Thanks for the help, it's working in clj but not cljs.
you can use reader conditionals for that: https://clojure.org/guides/reader_conditionals
I don't think js actually has integers, either 🙂 anyway, js/parseInt
should work in clojurescript, I suppose
Yeah that removed the build warnings, I don't even think my code will get ran in cljs, it's a resolver for fulcro, but rather not have the warnings.
hi, I have this simple hiccup page that receives a map correctly, but for some reason accessing keys of that map returns nil
- can anybody please tell me why? I expect this to be some obvious noob mistake… see FIXME below:
(ns webdev.item.show
(:require [hiccup.page :refer [html5]]
[hiccup.core :refer [html h]]))
(defn item-page [item]
(println item) ;; => ({:id #uuid "84a8c493-717d-41be-ba3d-52805b495524", :name one, :description one, :checked false, :date_created #inst "2020-09-18T11:32:18.416622000-00:00"})
(println (:name item)) ;; => nil FIXME why is this nil?
(html5 {:lang :en}
[:head
[:meta {:name :viewport
:content "width=device-width, initial-scale=1.0"}]
[:link {:href "/bootstrap/css/bootstrap.min.css"
:rel :stylesheet}]]
[:body
[:div.container
[:h2 "Item detail"]
[:div.row
(h (:name item))]
[:div.row
(h (:description item))]]]))
The output from (printn item)
that you show has parens around it, so it is probably either a list or some other kind of sequence of maps, not just a map.
user=> (def x1 '({:a 1 :b 2}))
#'user/x1
user=> (:a x1)
nil
user=> (def m1 '{:a 1 :b 2})
#'user/m1
user=> (:a m1)
1
user=> (:a (first x1))
1
bingo!! I’m getting a list with a single map in it. understood, thank you!
ok fixed. maybe the question that comes to my mind - does jdbc/query always return a list?
get-by-id
returns a single hash map (representing a single row). query
and find-by-keys
return a "result set": a sequence of hash maps.
@josef.richter If you have questions about clojure.java.jdbc
(or it's replacement, next.jdbc
), the #sql channel is a good place to get detailed answered (and I'm more likely to see questions there because it's lower traffic.
thank you @seancorfield