beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
grazfather 2021-04-05T00:32:38.073900Z

what’s the proper way to check if a value is a sequence? seq? doesn’t work on vectors

seancorfield 2021-04-05T00:34:24.075200Z

seq? tests whether something is a seq (not a sequence). And a vector is not a seq. It depends on exactly what types of data you're trying to select for, but I suspect sequential? is probably what you want @grazfather

seancorfield 2021-04-05T00:35:14.075600Z

FYI:

user=> (doc seq?)
-------------------------
clojure.core/seq?
([x])
  Return true if x implements ISeq
nil
user=> (doc sequential?)
-------------------------
clojure.core/sequential?
([coll])
  Returns true if coll implements Sequential
nil
user=> (doc seqable?)
-------------------------
clojure.core/seqable?
([x])
  Return true if the seq function is supported for x
nil

grazfather 2021-04-05T00:35:25.075800Z

that works. Why are lists seqs but vectors are not?

grazfather 2021-04-05T00:35:35.076100Z

I thought seq just meant an ordered collection

grazfather 2021-04-05T00:36:01.076500Z

i guess not. How is ISeq different from Sequential, then?

seancorfield 2021-04-05T00:36:45.076800Z

ISeq is this interface: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java

seancorfield 2021-04-05T00:37:37.077400Z

Sequential is a "marker" interface -- it has no methods.

grazfather 2021-04-05T00:37:52.077900Z

Right, I guess I just thought that vector would implement that interface

seancorfield 2021-04-05T00:38:39.078500Z

user=> (->> [1 2 3] type ancestors (sort-by str))
(clojure.lang.AFn clojure.lang.APersistentVector java.lang.Object clojure.lang.Associative clojure.lang.Counted clojure.lang.IEditableCollection clojure.lang.IFn clojure.lang.IHashEq clojure.lang.IKVReduce clojure.lang.ILookup clojure.lang.IMeta clojure.lang.IObj clojure.lang.IPersistentCollection clojure.lang.IPersistentStack clojure.lang.IPersistentVector clojure.lang.IReduce clojure.lang.IReduceInit clojure.lang.Indexed clojure.lang.Reversible 
clojure.lang.Seqable ; vector is seqable (you can call seq on it)
clojure.lang.Sequential ; vector is sequential
java.io.Serializable java.lang.Comparable java.lang.Iterable java.lang.Runnable java.util.Collection java.util.List java.util.RandomAccess java.util.concurrent.Callable)

seancorfield 2021-04-05T00:39:43.079600Z

Clojure tries to avoid providing inefficient ways to access data. Vectors are efficient for conj at the end, lists are efficient for conj at the start, which is what cons does.

grazfather 2021-04-05T00:40:13.079900Z

cool. thank you!

grazfather 2021-04-05T00:40:18.080200Z

and til ancestors

seancorfield 2021-04-05T00:40:36.080600Z

So vector has peek and pop instead of first and next:

user=> (peek [1 2 3])
3
user=> (pop [1 2 3])
[1 2]

seancorfield 2021-04-05T00:40:50.080900Z

(and they operate on the end of the vector, not the start)

grazfather 2021-04-05T00:41:10.081100Z

first works on vectors

seancorfield 2021-04-05T00:41:36.081600Z

Right, but it calls seq first and so you are coercing the vector into a sequence.

grazfather 2021-04-05T00:41:41.081900Z

ah

seancorfield 2021-04-05T00:41:55.082400Z

map etc also work on vector by coercing it to a sequence first.

grazfather 2021-04-05T00:42:28.083Z

alright. Thank you. I see seq? used a lot to test if something is a sequence, I was pretty suprised to see it not work on vectors. What’s the proper way to test that a value is iterable?)

seancorfield 2021-04-05T00:44:24.083600Z

It depends what you mean by "iterable". Vectors implement java.lang.Iterable but I suspect that's not what you mean?

seancorfield 2021-04-05T00:45:35.084600Z

I agree. I would say that if code is using seq? it is either doing something very specific or it is wrong 🙂

grazfather 2021-04-05T00:45:36.084700Z

I mean an ordered collection

grazfather 2021-04-05T00:46:09.085Z

ok

grazfather 2021-04-05T00:46:23.085500Z

but seq crashes if its a different type like true

seancorfield 2021-04-05T00:46:26.085600Z

Sounds like Sequential then.

grazfather 2021-04-05T00:46:37.086100Z

works for me

seancorfield 2021-04-05T00:46:47.086600Z

There's seqable? to test for things that can be seq'd.

➕ 1
seancorfield 2021-04-05T00:47:01.086900Z

user=> (seqable? true)
false

grazfather 2021-04-05T00:47:41.087200Z

alright, thanks again

phronmophobic 2021-04-05T00:47:41.087300Z

Although maps and sets aren't sequential?, but they are seqable?

phronmophobic 2021-04-05T00:48:47.087500Z

> (sequential? {})
false
> (sequential? #{})
false
> (seqable? {})
true
> (seqable? #{})
true

seancorfield 2021-04-05T00:49:43.087800Z

user=> (for [coll [(list 1 2 3) [1 2 3] #{1 2 3} {1 2, 3 4}] f '[seq? sequential? seqable?]] [((resolve f) coll) f coll])
([true seq? (1 2 3)] [true sequential? (1 2 3)] [true seqable? (1 2 3)] [false seq? [1 2 3]] [true sequential? [1 2 3]] [true seqable? [1 2 3]] [false seq? #{1 3 2}] [false sequential? #{1 3 2}] [true seqable? #{1 3 2}] [false seq? {1 2, 3 4}] [false sequential? {1 2, 3 4}] [true seqable? {1 2, 3 4}])
user=> (clojure.pprint/pp)
([true seq? (1 2 3)]
 [true sequential? (1 2 3)]
 [true seqable? (1 2 3)]
 [false seq? [1 2 3]]
 [true sequential? [1 2 3]]
 [true seqable? [1 2 3]]
 [false seq? #{1 3 2}]
 [false sequential? #{1 3 2}]
 [true seqable? #{1 3 2}]
 [false seq? {1 2, 3 4}]
 [false sequential? {1 2, 3 4}]
 [true seqable? {1 2, 3 4}])

seancorfield 2021-04-05T00:50:39.088Z

This might be helpful: https://clojure.org/reference/sequences

seancorfield 2021-04-05T00:51:01.088200Z

And also: https://clojure.org/reference/data_structures#Collections

alexmiller 2021-04-05T01:17:01.089200Z

Seqs are a logical list abstraction

alexmiller 2021-04-05T01:17:46.090400Z

Vectors (and maps and sets etc) can provide a seq view (a logical list) over those collections

zackteo 2021-04-05T03:19:47.093Z

I realise I'm not too sure what functions I can use to combine 2 lists together but anyway I have a list like so ...

`((171) (0 0 0 0 0 0)
  (147) (0 0 0 0)
  (183) (0 0 0 0 0 0 0))
how do I transform the list into something like
`((171 0 0 0 0 0 0)
  (147 0 0 0 0)
  (183 0 0 0 0 0 0 0))
Like to merge pairs of elements successively

paulocuneo 2021-04-05T03:30:05.093200Z

(Im not a clojure expert) maybe this way?

(->> `((171) (0 0 0 0 0 0)
       (147) (0 0 0 0)
       (183) (0 0 0 0 0 0 0))
     (partition-all 2)
     (map (fn [[left right]]
            (concat left right))))

zackteo 2021-04-05T03:32:19.093400Z

Right! That's definitely 1 way 🙂

raspasov 2021-04-05T05:23:12.094200Z

Transducer version (into [] (comp (partition-all 2) (map flatten)) [[1 2] [3 4] [5 6] [7 8]])

raspasov 2021-04-05T05:25:19.095700Z

@zackteo as a general tip, stick to vectors rather than lists or sequences unless there’s a specific need; easier to reason about IMO

Endre Bakken Stovner 2021-04-05T05:27:35.097900Z

Is there a way to make Clojure always print seqs as a literal? I am copy-pasting a lot of output into the REPL and I always forget to add ' in front of seqs. (`(:hi :there)` triggers an error as you know.)

teodorlu 2021-04-05T07:16:58.105Z

You might be able to simply quote everything you print. Quoted maps and vectors read back "correctly" too. Are you just printing random stuff with all the print functions? Or are you using tap?

Endre Bakken Stovner 2021-04-05T07:27:47.105200Z

I am not using tap. I've just heard the term. How is it applicable here?

teodorlu 2021-04-06T06:39:41.166100Z

You might be able to add your quotes with add-tap https://clojuredocs.org/clojure.core/add-tap

yuhan 2021-04-05T05:28:53.098300Z

Note that flatten recursively flattens nested sequences - I would go with (map #(apply concat %))

👌 2
raspasov 2021-04-05T05:29:23.098900Z

Prefer vectors where possible

raspasov 2021-04-05T05:31:03.100900Z

mapv, vec functions come in handy

Endre Bakken Stovner 2021-04-05T05:35:47.101100Z

I should make my own print that uses Specter or some such to find and turn seqs into vecs.

Endre Bakken Stovner 2021-04-05T05:36:21.101300Z

But sometimes I want the colls to actually be seqs 🙂

raspasov 2021-04-05T05:41:05.103600Z

Almost everything you can do with lists/seqs you can do with vectors, but you avoid the copy paste problem

piyer 2021-04-05T06:07:56.104600Z

(concat '(171) '(0 0 0 0 0 0)) ;; '(171 0 0 0 0 0 0)

Endre Bakken Stovner 2021-04-05T08:50:06.109700Z

I'd like to make selmer.parser/render join lists of strings before rendering, but leave strings as is:

(render "{{input}}" {:input ["a.txt" "b.txt"]}) => "a.txt b.txt"
(render "{{input.1}}" {input ["a.txt" "b.txt"]}) => "a.txt"
Currently the first would print "["a.txt" "b.txt"]". I'd like to avoid having to call {{input|join\" \"}} or do it implicitly.

Endre Bakken Stovner 2021-04-05T08:57:14.111500Z

This is the code selmer uses to render:

(defn render-template [template context-map]
  " vector of ^selmer.node.INodes and a context map."
  (let [buf (StringBuilder.)]
    (doseq [^selmer.node.INode element template]
        (if-let [value (.render-node element context-map)]
          (.append buf value)
          (.append buf (*missing-value-formatter* (:tag (meta element)) context-map))))
    (.toString buf)))
And node is
(deftype TextNode [text]
  INode
  (render-node [this context-map]
    (str text))
  (toString [_]
    (str text)))
Does this make it possible to inject my desired code or override the existing implementation? Never made or extended protocols before. https://www.braveclojure.com/multimethods-records-protocols/.

Endre Bakken Stovner 2021-04-05T10:19:08.111700Z

(deftype L [l]
  clojure.lang.IPersistentCollection
  (toString [self] (str/join " " l)))

(render "all: {{lst}} one: {{lst.1}}" {:lst (L. [1 2 3])})
"all: 1 2 3 one: "
Now I need to find out how to implement whichever method is needed to pick out elements.

Endre Bakken Stovner 2021-04-05T10:23:34.113600Z

I have the following deftype:

(require '[clojure.string :as str])
(deftype L [l]
  clojure.lang.IPersistentCollection
  (toString [self] (str/join " " l)))
What is the minimal code needed to support get/index lookups?
(def l (L. [1 2 3]))
(l 0) ;; class user.L cannot be cast to class clojure.lang.IFn
([1 2 3] 0) ;; 1

raspasov 2021-04-05T10:43:53.113700Z

Taking a step back, and because you’re posting in #beginners - is there a specific reason you’re trying to use deftype apart from pure learning? For real-world problems, I would stay away from them, unless you have a specific reason (usually related to low-level high-performance code)

Endre Bakken Stovner 2021-04-05T10:45:31.113900Z

See my previous two questions immediately above this one 🙂 I need a vec which works like this:

(.toString [1 2 3]) ;; "1 2 3"

raspasov 2021-04-05T10:46:25.114100Z

Why not just:

(str [1 2 3])

raspasov 2021-04-05T10:46:33.114300Z

=> “[1 2 3]”

Endre Bakken Stovner 2021-04-05T10:48:46.114500Z

Because I need selmer.parser/render to behave thusly:

(render "all: {{lst}} one: {{lst.2}}" {:lst [1 2 3]}) => "all: 1 2 3 one: 3"

raspasov 2021-04-05T10:54:29.115Z

If I am understanding right, one of your goals is for:

(.toString [1 2 3])
… to output: “123” Rather than the current: “[1 2 3]”

Endre Bakken Stovner 2021-04-05T10:54:53.115200Z

"1 2 3" yes 🙂

Endre Bakken Stovner 2021-04-05T10:58:31.115400Z

Of course,

[1 2 3]
should probably be a custom type of some sort. I do not want to override the toString for all vecs.

raspasov 2021-04-05T11:03:48.115600Z

Yeah… that’s probably not a good idea (global override)

raspasov 2021-04-05T11:05:34.115800Z

I am 95%+ certain that you’re trying to do this the hard way. There should be no issue pre-processing the input rather than trying to achieve some sort of polymorphism based on types; it is definitely possible in Clojure, but not the recommended way.

raspasov 2021-04-05T11:06:01.116Z

In 8+ years in Clojure, I’ve never felt the need to do this (and I’ve done quite some years of OOP before that)

Endre Bakken Stovner 2021-04-05T11:07:04.116300Z

Okay, the alternative I can see is to write my own render-function. Which I am sure would be more work than implementing a dinky type with two methods.

raspasov 2021-04-05T11:09:19.116500Z

Well, in one case you’re writing something to the effect of: 1. look for vectors in your render fn arguments 2. transform those arguments via (apply str [1 2 3]) => “123” 3. call your render fn In the other, you’re creating a brand new type, which chances are you’re not gonna use anywhere else.

raspasov 2021-04-05T11:10:11.116700Z

Sorry if I’m misunderstanding something 🙂

raspasov 2021-04-05T11:11:31.116900Z

From my experience in Clojure, creating a new type of vector just to have a specific custom toString function is VERY uncommon.

Endre Bakken Stovner 2021-04-05T11:12:01.117100Z

If I transform the vector then ""{{input}}"" would give the correct result but not ""{{input.1}}"" (the latter would be a single char).

Endre Bakken Stovner 2021-04-05T11:12:36.117300Z

Can you help me do it instead?

Endre Bakken Stovner 2021-04-05T11:13:14.117500Z

Creating a dink custom type is going to be much less work than rewriting someone else's library.

raspasov 2021-04-05T11:15:04.117700Z

Actually I don’t know how to do it on top of my head, it’s pretty uncommon; I’ll let you know if I figure it out 🙂

Endre Bakken Stovner 2021-04-05T11:16:58.117900Z

Perhaps I should ask this in the regular Clojure channel. But then I would be cross-posting 😕

raspasov 2021-04-05T11:17:04.118100Z

Just FYI, you’ll also be creating the vector in a custom way, via a new “constructor” etc

raspasov 2021-04-05T11:17:17.118300Z

Like in a library like this one: https://github.com/clojure/core.rrb-vector

raspasov 2021-04-05T11:17:53.118700Z

(but a lib like that has a reason to be a new type because it adds capabilities to a vector that it didn’t have before, rather than just customizing .toString)

Endre Bakken Stovner 2021-04-05T11:18:04.118900Z

I only need an object that supports indexed lookups. That is all. Does not need to be a vector really.

yuhan 2021-04-05T11:28:09.119100Z

You could define your own print method based on the :type metadata:

(defmethod print-method ::my-thing
  [x writer] (.write writer "hello"))

(print-str
  (with-meta [1 2 3]
    {:type ::my-thing}))
;; => "hello"

Endre Bakken Stovner 2021-04-05T11:30:58.119300Z

How do I get the internals of selmer to use my custom print-method?

Endre Bakken Stovner 2021-04-05T11:34:49.119600Z

Here is the line that calls toString: https://github.com/yogthos/Selmer/blob/master/src/selmer/parser.clj#L105 (It happens within the invocation of .render-node).

yuhan 2021-04-05T11:42:45.119900Z

ah.. I didn't realize you needed to override toString tself, not printing

Endre Bakken Stovner 2021-04-05T11:45:30.120100Z

No that is okay. A lot of context was hard to see :)

raspasov 2021-04-05T11:54:24.120300Z

Perhaps take a look at: https://github.com/clj-commons/potemkin It does a decent job of explaining why what you’re trying to do is not so easy (I believe)… When you say “I just need something that supports indexed lookups” - that’s not a straightforward thing in Clojure; there’s a multitude of ways in Clojure to access things in an “indexed” way: nth, get, first, etc; those are all different functions which work with different protocols, interfaces, etc

raspasov 2021-04-05T11:54:59.120700Z

This is for maps, but I believe relevant “A Clojure map implements the following interfaces: `clojure.lang.IPersistentCollection`, `clojure.lang.IPersistentMap`, `clojure.lang.Counted`, `clojure.lang.Seqable`, `clojure.lang.ILookup`, `clojure.lang.Associative`, `clojure.lang.IObj`, `java.lang.Object`, `java.util.Map`, `java.util.concurrent.Callable`, `java.lang.Runnable`, and `clojure.lang.IFn`. Between them, there’s a few dozen functions, many with overlapping functionality, all of which need to be correctly implemented.”

Endre Bakken Stovner 2021-04-05T11:56:32.121100Z

But can't I just copy all methods from another implementation and override the few I need?

Endre Bakken Stovner 2021-04-05T11:56:45.121300Z

Starting to think OOP wasn't such a bad idea XD

raspasov 2021-04-05T11:57:59.121500Z

You definitely can: rrb-vector does it https://github.com/clojure/core.rrb-vector

raspasov 2021-04-05T12:00:20.121900Z

But instead of doing all of those things, I would just do:

(let [v     ["a.txt" "b.txt"]
      input {:input-vec v :input-str (apply str v)}]
 (render "{{input-str}}" input)
 (render "{{input-vec.1}}" input))

raspasov 2021-04-05T12:00:34.122100Z

And be done with it… I don’t really understand what’s the ceremony here.

raspasov 2021-04-05T12:01:39.122300Z

(I haven’t tested the code above or used selmer, but I suppose that’s how it would work)

Endre Bakken Stovner 2021-04-05T12:06:43.122600Z

This is in the user-facing part of a language I am writing. So that uglyness won't be hidden away in the internals somewhere, but users would have to write it all the time.

"samtools mpileup -g -f {{file.genome}} {{input.sorted}} | bcftools call -mv - > {{output.1}}"
would suddenly become
"samtools mpileup -g -f {{file.genome}} {{input-str.sorted}} | bcftools call -mv - > {{output-vec.1}}"})

raspasov 2021-04-05T12:10:25.123Z

I see; now I understand the reason behind it; Perhaps you might want to look at the “hard” way then; For whatever it’s worth, strings in Clojure do support indexed lookup via (nth…) (nth “123" 0 :not-found) => \1 (nth “123” 42 :not-found) => :not-found

raspasov 2021-04-05T12:11:03.123200Z

But again, that depends on the implementation of the render library; is it using (nth …) when doing that *.1 magic? I don’t know

raspasov 2021-04-05T12:18:51.123600Z

I am sorry, there might be some super concise way to achieve what you’re trying to do via deftype, etc but I just don’t know it; I am guessing there isn’t but I would like to be proven wrong;

2021-04-05T13:04:04.123900Z

why not to use for from the library iteself?

(render "all: {% for item in lst %}{{item}} {% endfor %}one: {{lst.2}}" {:lst [1 2 3]})
this one will give you exactly what you are trying to do

👆 1
alexmiller 2021-04-05T13:43:09.126500Z

is that your actual goal?

alexmiller 2021-04-05T13:43:32.126900Z

if so, you can do that by overriding the print-method for the type

alexmiller 2021-04-05T13:44:23.128500Z

for creating custom collections, there are a variety of different interfaces you might need to implement to replicate different parts of collection functionality

raspasov 2021-04-05T13:44:50.129400Z

No; I went on a Java interface/class rabbit hole exploration 🙂 And trying to figure out if there’s a generic “proper” way to do it; or it would involve re-writing everything as protocols;

alexmiller 2021-04-05T13:45:06.129700Z

(in general, I'd say this topic is not a #beginners topic and probably better asked in #clojure instead)

raspasov 2021-04-05T13:45:44.130400Z

Yes… It stemmed from a #beginners conversation… I agree

raspasov 2021-04-05T13:46:38.130700Z

That’s what I thought. So the short answer is: no, there’s no “one liner” way to extend vectors….

alexmiller 2021-04-05T13:46:48.130900Z

no

alexmiller 2021-04-05T13:46:59.131100Z

you can see what normal vectors implement for example:

alexmiller 2021-04-05T13:47:02.131300Z

user=> (ancestors clojure.lang.PersistentVector)
#{clojure.lang.IPersistentCollection java.lang.Iterable clojure.lang.Sequential clojure.lang.ILookup clojure.lang.APersistentVector java.util.List java.lang.Runnable java.io.Serializable clojure.lang.Indexed clojure.lang.IPersistentVector java.lang.Comparable clojure.lang.IReduce clojure.lang.Associative clojure.lang.IMeta clojure.lang.IEditableCollection clojure.lang.IObj clojure.lang.IFn java.util.concurrent.Callable clojure.lang.AFn java.lang.Object java.util.Collection java.util.RandomAccess clojure.lang.Reversible clojure.lang.IKVReduce clojure.lang.IHashEq clojure.lang.Counted clojure.lang.Seqable clojure.lang.IReduceInit clojure.lang.IPersistentStack}

raspasov 2021-04-05T13:47:20.131500Z

Ah, that’s neat to know; never knew of that fn

alexmiller 2021-04-05T13:48:49.131700Z

if you're interested in this topic, I wrote a section in Clojure Applied about it with a picture that maps Clojure api functions to methods in the internal interfaces

alexmiller 2021-04-05T13:49:23.132200Z

you might find https://insideclojure.org/2016/03/16/collections/ helpful too

raspasov 2021-04-05T13:49:48.132700Z

Very cool, will check it out. Thank you for your input Alex, always the trusted source :clj: 🙂

alexmiller 2021-04-05T13:49:52.132900Z

this is kind of a cool helper function too: https://gist.github.com/semperos/3835392

alexmiller 2021-04-05T13:50:26.133500Z

will create a deftype scaffold with a lot of the necessary stuff for a custom type (you will still need to tailor it appropriately but can help a lot)

👍 1
Lukas 2021-04-05T13:59:27.135500Z

Hi 👋, I'm learning about macros.  After doing the basic conditional tutorials, I now want to write some more "advanced" macros to wrap my head around the topic. My goal is to write a macro that returns a function that combines str/replace functions.

;; It should later work like this:
((combine-replace #"a" "A" #"b" "B") "ab") => "AB"
I started with the base case
(defmacro combine-replace [x y & xs]
   `(fn [s#]
      (-> s#
          (str/replace ~x ~y))))

 ((combine-replace #"a" "A") "ab") => "Ab"
what I now want is to "write"  (str/replace ~x ~y) n times for all pairs in xs. The generated code should look something like this
(-> s#
    (str/replace ~x ~y)
    (str/replace ~x2 ~y2)
    ...) 
Currently, I'm sitting on this
(defmacro combine-replace [x y & xs]
   `(fn [s#]
      (-> s#
          (str/replace ~x ~y)
          ~@(loop [xs# xs]
              (when xs#
                `(str/replace ~(first xs#) ~(second xs#))
                (recur (nnext xs#)))))))
can someone help me to understand what I actually have to do, to make this work?

paulocuneo 2021-04-05T14:33:11.136300Z

maybe this will hint what your a looking for:

(let [xys [#"1" "2" #"3" "4" #"5" "6"]]
  (assert (= (mod (count xys) 2) 0) "Expression must be multiple of 2")
  (->> xys
       (partition 2)
       (map (fn [[left right]]
              `(some-fun ~left ~right)))))

NoahTheDuke 2021-04-05T14:36:33.136500Z

you gotta move the xs handling outside of the syntax unquote:

(defmacro combine-replace [x y & xs]
  (let [replaces (for [[x1 y1] (partition 2 xs)]
                   `(str/replace ~x1 ~y1))]
    `(fn [s#]
       (-> s#
           (str/replace ~x ~y)
           ~@replaces))))

NoahTheDuke 2021-04-05T14:38:01.136900Z

@paulocuneo good call with the assert. I forgot that partition handles odd-count seqs

✌️ 1
Lukas 2021-04-05T14:40:16.137100Z

Thank you both so much 🙏❤️

👍 2
Scott Starkey 2021-04-05T16:15:19.142600Z

OK, I seem to be having Java “classpath” problems when trying to load external libraries. Am I doing something wrong? 1. First I add to the :dependencies section of my project.clj file. 2. Then I do a lein deps. It seems to load the files from clojars. 3. Then I add the library line(s) in my (ns … (:require … )) . But I get a classpath error: Could not locate ring/middleware/json__init.class, ring/middleware/json.clj or ring/middleware/json.cljc on classpath. Probably a dumb newbie mistake, but what am I doing wrong? (Images included.) It makes me think that my classpath is missing something.

2021-04-05T16:57:06.144400Z

you don't need to run lein deps

2021-04-05T16:57:52.145200Z

my guess is whatever repl your editor is connected to is either not based on your project.clj, or hasn't been restarted since you added the dependencies

West 2021-04-05T17:04:29.145700Z

Hey guys, so I'd like to use something datomic like for a desktop application I was building. Apparently datomic is not free software, but there are libraries out there that behave like datomic. What are some of the lesser known options out there? So far I know about... • Datahike • Datascript • Datalevin

walterl 2021-04-05T17:06:18.145800Z

https://github.com/juxt/crux

Scott Starkey 2021-04-05T18:00:50.147400Z

@hiredman - You are totally right. I exited completely out of Emacs, and then back in, opened up a REPL, and magic! 🎩 Thanks for your help.

Oliver 2021-04-05T18:09:24.150700Z

I am just making my first attempts with Clojure (Linux, Spacemacs). Now I would like to use data.json (https://github.com/clojure/data.json) but cannot figure out how to install it. Any help very appreciated.

Dimitar Uzunov 2021-04-05T18:15:07.150900Z

You need to look up leiningen or tools deps. Here is the guide for the latter: https://clojure.org/guides/deps_and_cli

Dimitar Uzunov 2021-04-05T18:16:38.151100Z

You need to specify your dependencies in a file of a format specific to each of the tools and then use it to download your dependencies and add them to your class path. They can also do other tasks.

Oliver 2021-04-05T18:20:35.151300Z

This part here? "To work with this library, you need to declare it as a dependency so the tool can ensure it has been downloaded and add it to the classpath. The readme in most projects shows the name and version to use. Create a deps.edn file to declare the dependency:"

Dimitar Uzunov 2021-04-05T18:24:22.151500Z

There are some examples in the text, you can copy the snippets from the data.json page for your deps.edn and your source file

Oliver 2021-04-05T18:25:28.151700Z

I see this file in /usr/share/clojure. Should I add it there?

Dimitar Uzunov 2021-04-05T18:27:08.151900Z

No, you create a new one in the folder you are working in

Oliver 2021-04-05T18:27:41.152100Z

Ok. Let me try.

Oliver 2021-04-05T18:34:31.152700Z

Still get: Clojure 1.10.3 user=> (ns example (:require [clojure.data.json :as json])) Execution error (FileNotFoundException) at example/eval138$loading (REPL:1). Could not locate clojure/data/json__init.class, clojure/data/json.clj or clojure/data/json.cljc on classpath. example=>

Dimitar Uzunov 2021-04-05T18:35:04.152900Z

you need to run clj first so it can setup your classpath

Dimitar Uzunov 2021-04-05T18:36:08.153100Z

{:paths ["src"]
 :deps {cheshire/cheshire {:mvn/version "5.10.0"}
        org.clojure/data.json {:mvn/version "1.0.0"}
        org.clojure/data.csv {:mvn/version "1.0.0"}}
 :aliases {:depstar
              {:extra-deps
                 {seancorfield/depstar {:mvn/version "1.1.104"}}}}}
here is a deps.edn I used for a small project

Oliver 2021-04-05T18:43:29.153400Z

> >clj > Please install rlwrap for command editing or use "clojure" instead.

Dimitar Uzunov 2021-04-05T18:43:54.153600Z

yep, you need rlwrap too

👍 1
Oliver 2021-04-05T18:46:14.153800Z

Cool, now it works:<

Oliver 2021-04-05T18:46:32.154Z

Thanks so much!

vlad_poh 2021-04-05T22:18:14.158400Z

how would i do the following in clojure (reading a js textbook but can't help myself thinking what the clojure equivalent would look like) ... It finds the first number that is both greater than or equal to 20 and divisible by 7.

for (let current = 20; ; current = current + 1) {
  if (current % 7 == 0) {
     console.log(current);
     break;
  }
}
best I could come up with is
(first (filter #(zero? (mod % 7)) (iterate inc 20)))
doesn't "feel" right

2021-04-05T22:20:11.159200Z

a literal translation: (loop [current 20] (if (zero? (mod current 7)) current (recur (inc current))))

vlad_poh 2021-04-05T22:22:31.159900Z

ah loop recur! i rarely use it. Still looks verbose

paulocuneo 2021-04-05T22:25:07.160300Z

(println 21) ?

vlad_poh 2021-04-05T22:25:24.160500Z

:rolling_on_the_floor_laughing: love it

😆 3
2021-04-05T22:30:09.161200Z

regarding verbosity, I can't think of the higher level construct that would reduce the size of the code significantly

2021-04-05T22:31:16.162300Z

in either the filter or the loop version, there's not much noise - every expression does something meaningful

vlad_poh 2021-04-05T22:32:35.163100Z

agreed but i feel i'm overlooking something take, some, take-while, for etc

2021-04-05T22:34:30.164500Z

nope

vlad_poh 2021-04-05T22:35:58.165300Z

i like this one but

(some #(when (zero? (mod % 7)) %) (iterate inc 20))
just replaces first, filter with some, when

2021-04-05T22:38:26.165700Z

right, some just makes it more complicated