Fork me on GitHub
Cameron Cunning00:04:10

Have a stupid question 😞 Why doesn't this function to generate a fibonacci sequence of length n work?

(defn createFib
  ([length] (createFib length [0 1]))
  ([length a] (if (= (count a) length) (a) (recur length (conj a (+ (nth a (- (count a) 1)) (nth a (- (count a) 2))))) )) )


@negatifzeo (a) means "call the function a with no arguments"

Cameron Cunning00:04:31

Oh my gosh, so simple, And it works!


user=> (let [a [1 2 3 4 5]]
               [(= (nth a (- (count a) 1))
                   (peek a))
                (= (nth a (- (count a) 2))
                   (peek (pop a)))])
[true true]

Cameron Cunning00:04:32

Now I have another question... I get an integer overflow before long

Cameron Cunning00:04:42

How would I use longs or big ints?


use +'instead of +

Cameron Cunning00:04:02

One more.... What does the N at the end of a very large number indicate?


user=> (type 1N)


it's a read/write notation for BigInt

Cameron Cunning00:04:47

Beautiful. Thank you!


(you only see it with very large numbers usually, but even 1N is a bigint)



user=> (type 1M)

Cameron Cunning00:04:58

Not sure if I would have found this had I not asked here


@negatifzeo if you can figure out the right regex, clojure.repl/find-doc can help a lot

user=> (find-doc #"\Wsum\W")
([] [x] [x y] [x y & more])
  Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'
([] [x] [x y] [x y & more])
  Returns the sum of nums. (+') returns 0. Supports arbitrary precision.
  See also: +
([x y])
  Returns the sum of x and y, both long.
  Note - uses a primitive operator subject to overflow.
([x y])
  Returns the sum of x and y, both int.
  Note - uses a primitive operator subject to overflow.


sadly the doc strings are not optimized for regex searchability, but the facility does exist


bonus, it's not limited to core - it works with every defined function with a doc string

Cameron Cunning00:04:14

Also, can I ask what you use to format your code so that it's so readable?


here in slack I use the standard markup three ` introduces a code block, there's also a button for it

Cameron Cunning00:04:55

The final form:

(defn createFib
  "Usage: (createFib n), creates a fibonacci sequence of length n"
  ([length] (createFib length [0 1]))
  ([length a] (if (= (count a) length) a (recur length (conj a (+' (peek a) (peek (pop a)) ))) )) )


Just a note on Clojure style, we use kebab-case rather than camelCase for names.

👍 1

Any suggestions for porting to Clojure? The mutable tree structure of fibers is throwing me for a loop. Zippers came to mind, but there are several references to locations within the tree at the same time which complicates the matter considerably.

Michael Stokley04:04:38

does clojure have an all function? (apply and [true true false]) doesn't work i guess because and is a macro

Jim Newton07:04:29

HI Everyone. I have a problem with is in clojure.test . Is there an is-not I can use? If I simply test (is (not ...)) then the failure messages are uninformative. If (is (> a b)) fails, I get a message like (not (> 1 2) but when (is (not (> a b))) fails I just get a message (not (not true)) . Certainly for > I could choose a better predicate for the test, but in general (is (f a ...)) vs (is (not (f a ...))) is problematic.

(deftest t-nullable
  (let [a 1 b 2]
    (is (> a b))
    (is (not (> b a)))))

(run-tests 'clojure-rte.core-test)
FAIL in (t-nullable) (form-init4386036104585295471.clj:33)
expected: (> a b)
  actual: (not (> 1 2))

FAIL in (t-nullable) (form-init4386036104585295471.clj:34)
expected: (not (> b a))
  actual: (not (not true))

Jim Newton07:04:06

Is there a cousin of isa? which tests not type inclusion, but rather type intersection? I.e. given two isa? compatible type designators how can I know whether there can exist an object which is a member of both types?


Not directly,but you can call ancestors on both, and then do a set intersection on the sets they return:

Jim Newton08:04:33

@didibus, does it suffice to call ancestors once for A and once for B and find the intersection of those two results, or do I need to walk up the return value and keep calling ancestors ?

Jim Newton08:04:00

E.g., does this suffice? Note, that I'm calling not-any? twice rather than calling intersection, because I don't need the intersection, I just need to know whether the intersection is empty.

(defn disjoint? [t1 t2]
  (let [ancestors-1 (ancestors t1)
        ancestors-2 (ancestors t2)]
    (and (not-any? (fn [a2] (contains? ancestors-1 a2)) ancestors-2)
         (not-any? (fn [a1] (contains? ancestors-2 a1)) ancestors-1))))

Jim Newton09:04:15

This implementation is sadly wrong. 😭 It asks whether the two types have a common supertype, not whether they have a common subtype.

Jim Newton09:04:09

I believe it should be the following:

(defn disjoint? [t1 t2]
  (let [descendants-1 (descendants t1)
        descendants-2 (descendants t2)]
    (and (not-any? (fn [a2] (contains? descendants-1 a2)) descendants-2)
         (not-any? (fn [a1] (contains? descendants-2 a1)) descendants-1))))

Jim Newton14:04:26

Found another bug in this function disjoint? Here is my current implementation

(defn disjoint? [t1 t2]
  (and (not (isa? t1 t2))
       (not (isa? t2 t1))
       (let [descendants-1 (descendants t1)
             descendants-2 (descendants t2)]
         (and (not-any? (fn [a2] (contains? descendants-1 a2)) descendants-2)
              (not-any? (fn [a1] (contains? descendants-2 a1)) descendants-1))))) 

Jim Newton14:04:54

The previous version was answering false in the case one type isa? subtype of the other


Hum, I believe ancestors will return the following chain of parents, so you shouldn't have too walk up it


I think that's the difference with the parents function, which will only return the immediate parents, ancestors I think will walk up the parents and aggregate their parents and their parents parents all the way for you

👍 1
Jim Newton09:04:24

Looking at the documentation for I see how to find a type of an object. And in the see-also section it talks about the function `instance?` which tests whether an object is a member of a designated class.  Is the documentation using the word class and type interchangeably here? What is the correct way to check type membership, assuming I have a type designator compatible with `isa?` ?


According to the doc:

user=> (doc type)
  Returns the :type metadata of x, or its Class if none
From what I've seen, it looks like type/`isa?` and class/`instance?` are counterparts with each other.


class and instance? dealing strictly with java object hierarchy; type/`isa?` deal with derived types, falling back to Java classes if no derived type hierarchy is available.

Jim Newton09:04:01

No, as far as I understand isa? takes two type designators and tells whether one is a subtype of the other. I'm looking for a function which takes an object and a type designator and asks whether the object is a member of that type.

Jim Newton09:04:39

i.e., something that can be called like instance? but which accepts any 1st argument which is compatible with isa?


Yes, (isa? (type a-value) a-type) vs (instance? a-class an-object)


But because isa? and type fall back to Java type hierarchy, they will likely fit.


and since you mention you have an isa? compatible type designator, type would make more sense to me.

Jim Newton10:04:13

Good suggestions.

Jim Newton10:04:14

Thanks. But since I really don't understand all the flexibility of isa?, what's the best way to test my code? How can I generate a huge set of isa? compatible arguments and corresponding instances? Perhaps I could look at the testing code for isa? itself? Does anyone know how to locate that?


Are you using derived types? Or is that what you're looking at doing?

Jim Newton12:04:04

Hi penryu, for the moment here is what I think I'm doing. I'm implementing a DSL which lets the user talk about types. I want to claim on my DSL that I accept any type which isa? supports.


iiuc, as long as your program uses type, isa?, or by extension defmulti/`defmethod`, this is implicitly true.


but I haven't done a lot with derived types

Jim Newton10:04:04

I'd like to write a function which takes a single argument and distinguishes several cases: (1) anything other than list, (2) empty list (3) singleton list (4) non-singleton list. Can someone suggest the most idiomatic way of doing this?

(cond (not-a-list x) ...
      (empty-list x) ...
      (singleton-list x) ...
      (non-trivial-list x) ...)
Here is what I'm trying.
(cond (not (list? pattern)) ...
         (= pattern ()) ...
         (not (rest pattern)) ...
         :else ...)


Based on what I know of your question, I might start with something like:

(def do-stuff [x]
  (if (sequential? x)
    (case (count x)
      0 (do-empty x)
      1 (do-single x)
      (do-longer x))
    (do-not-list x)))


This handles sequences other than actual lists (eg, vectors) as well. If you're expecting the method to be called with different types, you might consider multimethods.

Aviv Kotek11:04:45

Using clojure.jdbc I would like to write a method that does update-or-insert-rows [db table rows where] where rows could be a seq of maps. this would work for 1x row: (defn update-or-insert [db table row where] (sql/with-db-transaction [t-conn db] (let [result (sql/update! t-conn table row where)] (if (zero? (first result)) (sql/insert! t-conn table row) result)))) Is there any way using insert-multi! or doing a batch operation and not calling this method for each row? assuming my DB would need to update some data. or a way to use ON DUPLICATE KEY UPDATE..., I can also delete > insert - which I prefer not to


you might want to just call sql/execute! with a statement that has the on duplicate key update... clause

Aviv Kotek14:04:16

yea but i'm looking for some abstraction, as I would need to parse all given maps... etc to query,


@aviv The problem (from a library point of view) is that upserts have different syntax across different databases, and there are also different ways to implement upsert even for a single DB, depending on exactly what semantics you want and what trade offs you want to make.

👍 1
Aviv Kotek19:04:53

How would you tackle this kind of scenario? 🙂 @U04V70XH6


@aviv When I researched this for MySQL (which is what I use at work), I found three completely different approaches with three different sets of trade offs, so the approach I would code up would very much depend on the specific trade offs I was willing to accept in those specific circumstances.


We write upserts quite often at work, but never for bulk updates/inserts -- they are always single row solutions -- and we do it in different ways depending on all sorts of parameters to the problem (how write heavy the table is, whether a double insert actually matters (and whether it is detectable through key constraints -- it isn't always). So the logic varies a lot.


If I was using PostgreSQL, I would no doubt have the option of different solutions, with different trade offs, due to the different syntax/semantics that PG provides compared to MySQL.

Aviv Kotek20:04:56

I see, by double insert you mean duplication. we use MySQL and currently I choose to batch delete & insert compared to upsert-each-row of the batch

Aviv Kotek20:04:23

I could test it timing as this is my only concern atm


When deleting and inserting, there's also the consideration of what happens if another process queries for the record concurrently and doesn't find it.


For some tables, it's safer for us to do an insert, then delete the older record. For other tables, we do an update and if that hits no records we do an insert -- but then you have to deal with potential concurrent insertions (two threads both do the update and both get zero rows so both of them then try to insert a new record... which you may have to then detect and fix if there's no constraint violation on the inserts). So many fun possibilities 🙂

🚀 1
Aviv Kotek07:04:07

Deleting and inserting is also much-less-efficient than an update query

Aviv Kotek07:04:23

as a rule of thumb it's better to do an upsert rather than delete-insert I guess

Aviv Kotek07:04:42

(we have totally different timezones so responding in delay 🙂)


Correctness outweighs efficiency. Again, the choice of approach depends on the exact problem and the trade offs that are appropriate.

Jim Newton16:04:06

Can someone help me understand why this evaluates to false.

(let [a 100] (list? `(:or ~a)))
while this evaluates to true
(list? '(:or 100)) 
and this evaluates to true as well.
(= '(:or 100) (let [a 100] `(:or ~a)))


= is value-based in Clojure so, for example (= [:a 100] (list :a 100)) produces true even tho' we're comparing a vector and a list.


list? itself tests whether its argument is an instance of a specific type: IPersistentList

user=> (source list?)
(defn list?
  "Returns true if x implements IPersistentList"
  {:added "1.0"
   :static true}
  [x] (instance? clojure.lang.IPersistentList x))

Jim Newton16:04:39

so backquote returns a vector?


user=> (type `(:or 100))


user=> (type '(:or 100))

Jim Newton16:04:01

it prints with parenthesis not with brackets.

Jim Newton16:04:07

why is a Cons not a list? Should I be as confused as I am?


user=> (ancestors clojure.lang.Cons)
#{clojure.lang.ISeq clojure.lang.Sequential .Serializable clojure.lang.IPersistentCollection clojure.lang.ASeq java.lang.Iterable clojure.lang.IObj clojure.lang.Seqable java.util.Collection java.lang.Object clojure.lang.Obj clojure.lang.IHashEq java.util.List clojure.lang.IMeta}
Cons is a lot of things -- including an IPersistentCollection but not an IPersistentList


Backquote is a special construct, most often used with macros.

user=> (macroexpand '`(:or 100))
(clojure.core/seq (clojure.core/concat (clojure.core/list :or) (clojure.core/list 100)))
user=> (macroexpand '(:or 100))
(:or 100)


This might help explain some of the "punctuation" you'll see in Clojure

Jim Newton16:04:16

which part of the punctuation link are you referring to? And why do we have to different list-like structures which print the same and both look like lists but are not both lists?

clojure-rte.core> (let [a 100] `(:or ~a))
(:or 100)
clojure-rte.core> '(:or 100)
(:or 100)
They print exactly the same.


That page describes what single quote and backquote (syntax quote) do.


Printing data structures is "lossy" -- partly because data structures have to be realized in order to display them as characters. So a lazy seq and a cons will both get realized and printed as "lists".

Jim Newton16:04:06

Yes thanks for the link. The backquote is familiar to me. and the page says that parentheses denote "List"s.

Jim Newton16:04:05

Even more bizarre:

Jim Newton16:04:13

clojure-rte.core> (type `(:or))
clojure-rte.core> (type (let [a 100] `(:or ~a)))


type is showing you a concrete type, but the abstractions that type implements are the more important part (which you're not seeing)

Jim Newton16:04:32

clojure-rte.core> (rte-list? (let [a 100] `(:or ~a)))
clojure-rte.core> (= 'clojure.lang.Cons (type (let [a 100] `(:or ~a))))
clojure-rte.core> (type (let [a 100] `(:or ~a)))
can I test for list or Cons?


lists are IPersistentList, and more generally seqs (ISeq) are logical lists, so even more abstract. all lists are seqs, not all seqs are lists

Jim Newton16:04:02

why does this return false?

(= 'clojure.lang.Cons (type (let [a 100] `(:or ~a))))


the type isn't a symbol. remove the '


because 'clojure.lang.Cons is a symbol but type returns a Class instance


user=> (= clojure.lang.Cons (type (let [a 100] `(:or ~a))))


but as a caution, it's never a safe thing to compare class instances for equality - the jvm uses a hierarchy of classloaders and class instances are unique per classloader


and classes loaded in different classloaders are not =

Jim Newton16:04:12

I need a scotch. now 🙂 Thanks for helping me understand. It is really surprising to a lisper that `(something something) does not return a list :-[


it does return a list

Jim Newton16:04:46

it doesn't return a list according to the list? function


I think for the question you're asking, seq? is actually more appropriate


user=> (seq? (let [a 100] `(:or ~a)))


it does return something that answers to car and cdr though. its a seq which has first and next


seqs are logical lists (a list abstraction). lists in Clojure are specifically persistent list collections, which is a narrower scope

Jim Newton16:04:41

but [1 2 3] also has a first and rest


it doesn't actually


first and rest take a seqable and coerce them to a seq

Jim Newton16:04:09

clojure-rte.core> (first [1 2])
clojure-rte.core> (rest [1 2])


vectors are seqable and coerced to a vector seq before the operation is applied


so vectors don't "have" a first and rest, they can produce a seq view which does


(as do maps, sets, etc)


concrete lists directly satisfy the logical list abstraction

Jim Newton16:04:15

So is the list? function simply poorly documented?

Jim Newton16:04:27

or poorly named?


no, it's very accurately documented


the gap here is in your prior knowledge of lists where list means something different


(I'm not saying you're wrong to be clear, I'm saying Clojure defines things in a subtly different way)

Jim Newton16:04:17

Alex, you said a minute ago that (something something) returns a list, but it is list for which list? returns false. So it appears that either the function has a bug, or is misnamed.

Jim Newton16:04:01

its ok for there to be bugs. the world is full of bugs. We just need to understand them and move on with creating beautiful programs.


@jimka.issy, there's a difference between a clojure PersistentList and a sequence, which is commonly also called a list.


Most of the time, when you're thinking of a "list", what you really want is a sequence.


A clojure list is a specific type of sequence.


yeah, seq? is a much more interesting predicate than list? is


there are two levels of "list" here, and Clojurists often talk about them ambiguously

Jim Newton17:04:51

@ordoflammae I think the list? is misnamed. it does not check for whether somethign is a list, rather it checks for whether something is a clojure.lang.IPersistentList


seqs are logical list abstractions, lists are persistent list collections


@jimka.issy,that's exactly what it's supposed to do.


both are often referred to generically as "list"


and both print the same


In technical terms, what you are thinking of is a sequence, but we just call it a list in every-day speech.


regardless of the ontological questions of what is or isn't a "list", pragmatically speaking the predicate people usually need is seq?


the list? predicate is specifically asking about the narrower persistent list collection, not the broader seq logical list

Jim Newton17:04:38

Am I the first person to be confused about this?\


I doubt it :)


it's a recurring topic from the #clojure IRC :D


XD, I was confused about it when I started learning clojure; no sweat.


if you haven't seen, it sounds like it might help

Jim Newton17:04:50

So I'm defining a DSL where the user will type in a ???list??? like the following (:* a b (:cat (:+ d e) (:+ (:or a b)))) So does my parser for this need to check for list or sequence to distinguish leaf nodes from tree nodes?


I would use seq? (or even more generically sequential? or coll? depending on whether vectors or sets etc are allowed)

Jim Newton17:04:11

the order is critically important so I'd say that I don't allow sets


coll? would work with that input - but use sequential if you don't allow sets


if scope is what you have there, I'd use seq?

Jim Newton17:04:41

are sets coll?

Jim Newton17:04:25

my liberally regulary uses `(this and ~that) during the descent

Jim Newton17:04:10

is a set a seq?


as I said above, vectors, maps, and sets are not seqs, but they are seqable (can produce a seq view by calling seq on them)

Jim Newton17:04:50

no, doesn't seem to be


(seq #{:a}) is (:a) but (seq? #{:a}) is false

Jim Newton17:04:38

Looking at my code, the thing that I'm assuming about the data structure is that I can destructure it with [first & rest] and I can build it with back-quote, paren, and @


I think he has a point about lists (identical? some-list (seq some-list)) 😉


Hum, to distinguish leaf from tree, you can also check for emtpyness or nil depending on your use of rest or next


calling rest on :or would blow up though


and :or is a leaf


Ah ya, nevermind, I see your need for seq? now

Jim Newton17:04:06

(:or x y z) is not a leaf because it is a ???list??? whose first element is in the syntax of my dsl. However (or x y z) would be a leaf because it doesn't match anything my parser is looking for. I would thus assume that (or x y z) would be something the user thinks is compatible with isa? , and if not, it's not my fault, it's a user error.


@jimka.issy oh I must have misunderstood - usually when walking nested lists the collections are branches and non-collections are leaves


if (:or x y z) isn't a leaf though, that means :or itself is right?

Jim Newton17:04:10

:or a syntax element in the DSL. it indicates which functions handle the x, y, and z depending on the operation we are performing. So the question of whether :or is a leaf never comes up.


From memory, list? is the predicate for things constructed with the constructor list

👍 1
Jim Newton17:04:46

if that's true, then it really does make sense.


But, because you also have Vectors, and Java ArrayList and LinkedList and all these other kind of conceptual list like things, though not the things created by the list function


Clojure Also has the concept of a sequence


And a sequential


Oh and seqable, and yes, at that points it gets tricky

Jim Newton17:04:03

I'm not sure whether it is a good idea or bad to allow the user to use other sequences for the dsl. for example should I treat (:or x (:and y z)) the same as [:or x [:and y z]] or even allow to mix and match? And if I want to disallow it, how would I?


list? should check only for the first


vector? only the second


coll? for both

Jim Newton17:04:38

list? does not check the first because it fails on something generated by backquote/tilde.


Hum.. are you sure?

Jim Newton17:04:40

yes, that was the beginning of the conversation.


You don't do any intermediate processing on it?

Jim Newton17:04:04

(let [a 100] `(:or ~a))

Jim Newton17:04:10

list? returns false on that


So ya, this gets tricky. The quote will return a list?


But it seems the backquote doesn't create a list? but a seq? I think

Jim Newton17:04:54

normal quote returns a list? and backquote sometimes returns a list? but not always


It's possible, I would say that's an artifact of the reader implementation


And backquote

Jim Newton17:04:42

Thanks everyone for the help. I'm quitting for the day. will start again tomorrow morning

Jim Newton17:04:46

in confinement in France


I don't think you can easily distinguish the two. Because seq? allows more than just what backquote might return. I don't know there is a supertype of just what backquote returns + list?


Good luck, I'm also really curious to see the result of what you're cooking up


I think it's a mistake to think of ' or ` as "returning" anything - these are syntax interpreted by the reader


you can use both of them on any data type. what that means, depends.


the fact that you're using quoting here should be irrelevant - define the syntax you want in terms of Clojure data


Hum, ya I guess that can make sense. Not to say that if backquote say on () returned a list?, his problem would be solved. but obviously, it does not. So he might be better of coercing things himself.


To the exact type he needs


don't coerce, just use the right predicate for what you are checking for


Though I expect ' to return me the literal that follows


But backquote is a weird one


using list? also means that you break everything if you preprocess your data with standard collection functions like map


Say you wanted to allow only things returned from backquote over a () and lists? , but not vector? ArrayList, etc.


doesnt that include vector?


vectors aren't seqs


Ah ya ok, I think I often get seq? and seqable? and sequential? mixed up as to what is which


So seq? is all the XXXSeq classes + IPersistentList ?


user=> (seq? [])


what people think are "lists" generically are seqs

Roger Amorin Vieira18:04:43

Hi, I'm have some problems when do a minus operation with doubles values like: (- 10.52 10.42) I'm get a number 0.09999999999999964 . Someone can explain why, and how to fix it?


that's just doubles being doubles isn't it?


you can ask for rounding with a specific precision iirc


Read about floating point arithmetic

Roger Amorin Vieira18:04:06

I see now, i was thinking this was a clojure error, but I test in others languages and I'm getting the same result


Here is a link to part of Clojure equality guide, that has a link to a widely referenced article on floating point representations and why they are approximations:


the answer btw is if possible use ratios, if not use BigDecimal user=> (- 1/3 2/3) -1/3


🙋 Roll call! Who else is here?


@luis.geniole There are 9,602 members in this channel 🙂


Quite a few eh


Feel free to ask Clojure-related (beginner) questions here but it's not a water-cooler for general chat.


can you see how many are online? can't find where


You can't get accurate numbers of the online members of a channel, just total.


Much depends on whether folks have Slack set to show them "away" after some idle time, as well.


Feel free to ask questions about Slack itself in #slack-help


darn slack! 😉


is it possible to have a multimethod for multiple dispatch values?


like (defmethod X [:foo :bar] ...) that catches both :foo and :bar values?


you can have multiple methods that invoke the same function

👍 1

and there are some helper macros in various utility libs that get rid of the boilerplate for that


as you can see, there's not much to it


cool, thank you