This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-05
Channels
- # adventofcode (419)
- # aleph (8)
- # aws (6)
- # beginners (148)
- # boot (9)
- # cider (24)
- # cljs-dev (37)
- # cljsjs (8)
- # clojure (134)
- # clojure-android (6)
- # clojure-brasil (15)
- # clojure-dev (8)
- # clojure-dusseldorf (2)
- # clojure-greece (67)
- # clojure-italy (8)
- # clojure-japan (3)
- # clojure-russia (3)
- # clojure-spec (8)
- # clojure-uk (13)
- # clojurescript (54)
- # clojurex (6)
- # cursive (5)
- # data-science (12)
- # datomic (15)
- # defnpodcast (11)
- # emacs (25)
- # fulcro (95)
- # graphql (3)
- # lein-figwheel (1)
- # leiningen (27)
- # luminus (1)
- # lumo (6)
- # mount (2)
- # off-topic (112)
- # om (3)
- # onyx (24)
- # perun (3)
- # re-frame (20)
- # reagent (1)
- # reitit (2)
- # ring-swagger (13)
- # rum (10)
- # shadow-cljs (45)
- # spacemacs (24)
- # sql (2)
- # unrepl (78)
- # yada (1)
hey all, I just learned about tail call recursion in clojure, and I think it's great!
Is it safe to that any time you want to use recursion in clojure you can and should use loop / recur?
you don't need to use loop
- functions are also recur targets
and many of clojure's higher order constructs (map, reduce, filter, group-by, repeatedly, iterate, etc.) are replacements for common usages of recursion, and are preferred
interesting, thanks!
so if you are not in a loop it will recursively call the function?
right
and if you are generating or consuming a collection in order, you probably want one of clojure's dedicated functions instead of using a recursive function directly
great! good to know 👍
so you would never call the function name directly in a function, but instead use recur? Is only the one with recur tail-call optimized?
there are two big exceptions: functions that need to create a branching structure (eg. something that consumes a tree or graph) and functions that are lazy
in both those cases, you can't use optimized recursion
(well if you lift the continuation into the heap you can turn a branching structure into an optimized recursive one but you also make the whole thing more complex and it's probably not worth it most of the time...)
and by lifting the continuation you are undoing the performance benefit of the recursion unless you are able to do it in some optimized way that doesn't replicate a lambda capture...
that's not stuff for #beginners though I don't think
haha true. good points though!
So then what to do if tree is large and could cause stack overflow? tree-seq
doesn't look like a valid choice in this case.
Hi everyone, I've just recently started learning about spec, then I came across this particular example in its clojure guide:
(defn ranged-rand
"Returns random int in range start <= rand < end"
[start end]
(+ start (long (rand (- end start)))))
(s/fdef ranged-rand
:args (s/and (s/cat :start int? :end int?)
#(< (:start %) (:end %)))
:ret int?
:fn (s/and #(>= (:ret %) (-> % :args :start))
#(< (:ret %) (-> % :args :end))))
I don't quite understand how the :args
get evaluated. I understand that first it uses cat
to evaluate each element of the argument, by tagging the predicate with a keyword. What I don't understand is the second predicate: #(< (:start %) (:end %))
, what constitutes as the input of this? Since if I define another spec like (spec/def ::lesser-than #(< (:start %) (:end %)))
, I can't use it against a vector: (spec/def ::lesser-than #(< (:start %) (:end %)))
, it results in a null pointer exception.I've tested it around in repl, it seems that it's not that :args
evaluate things differently, I've created another spec like this:
(spec/def ::correct (spec/and (spec/cat :e even? :o odd?)
#(< (:e %) (:o %))))
It is valid for a vector like [4 5]
, but take #(< (:e %) (:o %))
predicate as another spec, then it won't work anymore, it throws an exception, which I think is obvious since the input is a vector, not a map. My question is, does (spec/cat :e even? :o odd?)
along the way transform a vector [4 5]
into a map {:e 4 :o 5}
and then it becomes the input of the second predicate? If so, what is the reasoning of this?Following up on a question and solution from @cjmurphy and @ghsgd2 Why might I favor one of these over the other?
(for [x (range 10) y (range 10) z (range 10)
:let [value (str x y z)]]
value)
vs.
(for [x (range 10) y (range 10) z (range 10)]
(str x y z))
@jereme In this example no difference, but you can add another sequence after your :let
. Try it out 🙂
I would favour the 2nd. I suspect the first would more make sense if you needed the value
in the []
part of the for
list comprehension/macro.
hey @noisesmith, I was playing around with the tail-recursion with the factorial function, but it doesn't seem to be any better than regular javascript.
for example, this seems to break around 170, with higher values of n returning "Infinity"
(defn fac
([n] (fac (dec n) n))
([n acc]
(if (= n 1)
acc
(recur (dec n) (* acc n)))))
But this javascript function works equally well up to around 170
function fac(n) {
if (n === 0) {
return 1;
} else {
return n * fac (--n)
}
}
@info at 170 you're not likely to hit a stack overflow. That'd take a depth of about 2000 or so.
and the infinity is resulting because you're running out of digits in your numeric type.
(fact 170) -> ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1501)
in clj
You can always cast n
to a bigint
to get to some bigger numbers, i.e. (fac (bigint 170)) => 7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000N
and realize that this doesn't exist in js (fact 170)
=> 7.257415615307994e+306 which is obviously incorrect
wait, why is that incorrect?
the actual value is 7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000N
oh i see, you mean the jvm one is incorrect
7.257415615307994e+306 != 7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000
when I do the float on in regular js in the chrome console it returns with e notation
"7.257415615307994e+306"
But isn't the jvm number isn't even returning 300 digits so isn't that off by an even larger amount?
hmm, I guess it is 300 digits.
Here is the result as per WolframAlpha, 7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000
there are lots of zeros because there's lots of numbers with 10 as a factor, 10, 20, 30, 2 & 5, etc
wait so was that Java or JVM Clojure?
is it possible to get the exact number with cljs?
It is possible to get the exact number in any language as long as you know what type to cast it to. The reason why the JavaScript version was ‘incorrect’ is because it was coerced into an estimate. The Clojure version that I pasted in after casting the argument to a big int is correct.
If you want the same correct answer in Cljs, just remember to cast the argument to a bigint
for precision
yeah I thought that was a java type
But just wondering, can JVM clojure calculate fac for higher numbers, like 200?
computers are really good at multiplying
hey, that’s on you for using stupid base 10 numbers :)
(10 fingers - it’s literally IN your hands!)
man, wolfram could do it super quick.
I wonder how they are implementing it
lookup table
good for benchmarking
ah, cheaters 🙂
btw I successfully got factorial of 50000 with this function (code isn't my)
(defn factorial ([n] #(factorial n 1)) ([n acc] (if (< n 2) acc #(factorial (dec n) (*' n acc)))))
(trampoline factorial 50000)
I wonder how does it fit into the type
trampoline is a great feature 🙂
trampoline tells it to use tail call recursion?
could you also use "recur" instead of the function name when it's called in the function body?
something similar
yes. but I wanted to learn trampoline
to be able to do recursive calls with 2 functions (using each other) later.
Yep, as with a lot of methods like this there's a tradeoff that can be made. In this case it's the complexity of a trampoline and increased memory allocations.
So the code will probably be slower, but will no longer cause a Stack Overflow.
can someone teach me how to callbacks?
How to get table fields in korma?
@kgofhedgehogs are you looking at the docs? http://sqlkorma.com/docs what exactly do you need?
@sova, I have two tables and one function which recieves hashmap with keys for both tables. I want to get column names from both tables and distribute received hashmap in this tables
so you need column names...
@sova, I can't find what I want in docs
btw, Im working with postgres
so you don't know the field names already and you want to figure them out via query? I think you have to know what fields you want to ask for
@sova, I dont want to hardcode fieldnames because of project in dev and they may change... Also I think its good to have some abstraction
Very true. Does (select ) do what you want?
You suggest to select one row from table and get keys from result?
hm. In fact this does what I want
Thanks, @sova!
@sova, if table is empty select will return `()
So this solution works only with filled tables
Aha! there must be one row?
Yes, must be. But project is in very early dev and almost all tables are empty now..
So what to do in case of empty table?
Try (select* tablename)
@sova,
> (select* message)
{:ent {:table "message", :name "message", :pk :id, :db nil, :transforms (), :prepares (), :fields [], :rel {"account" #object[clojure.lang.Delay 0x37
3ca86b {:status :pending, :val nil}], "chat" #object[clojure.lang.Delay 0x1c39c2a8 {:status :pending, :val nil}]}}, :where [], :group [], :table "mes
sage", :db nil, :fields [:korma.core/*], :joins [], :type :select, :alias nil, :modifiers [], :from [{:table "message", :name "message", :pk :id, :db
nil, :transforms (), :prepares (), :fields [], :rel {"account" #object[clojure.lang.Delay 0x373ca86b {:status :pending, :val nil}], "chat" #object[c
lojure.lang.Delay 0x1c39c2a8 {:status :pending, :val nil}]}}], :order [], :options nil, :aliases #{}, :results :results}
Columns there
Column
------------
id
account_id
chat_id
content
well a janky way to do it is to check if empty? add a phantom element, get the field names, remove the phantom
This solution looks way too bad...
I'm surprised this isn't line 1 of the docs
or line 0
how do people get field names in vanilla plain ol' sql?
All production dbproviders what I met, have hardcoded columns...
Maybe we can make (exec-raw "SELECT * FROM ...") with some postgres tricky query?
like a postgres query that will spit that out? yes that's an idea
testdb=> select column_name from information_schema.columns where
testdb-> table_name='message';
column_name
-------------
id
account_id
chat_id
content
(4 rows)
Here it works in psql
But in clojure:
(kc/exec-raw "select column_name from information_schema.columns where table_name='message';")
CompilerException java.sql.BatchUpdateException: Batch entry 0 select column_name from information_schema.columns where table_name='message' was aborted
. Call getNextException to see the cause., compiling:(project/scratch.clj:8:1)
(kc stands for korma.core)
(kc/exec-raw "select column_name from information_schema.columns where table_name='message';" :results)
({:column_name "id"} {:column_name "account_id"} {:column_name "chat_id"} {:column_name "content"})
@sova, thanks for participating in search of solution 🙂
Excellent!