Fork me on GitHub
#beginners
<
2022-03-25
>
Dustin Paluch00:03:21

cljs.user> (.endsWith "hello" "o")
true
cljs.user> (.length "hello")

Execution error (TypeError) at (<cljs repl>:1).
"hello".length is not a function
:repl/exception!
cljs.user> 
Why does one work but not the other?

Nitin01:03:18

In javascript, .length is a property of an object, and not a function.

➜  ~ node
Welcome to Node.js v14.17.4.
Type ".help" for more information.
> "hello".endsWith("o")
true
> "hello".length
5
> "hello".length()
Uncaught TypeError: "hello".length is not a function
> 

πŸ‘ 1
okwori01:03:11

(.-length "hello")

πŸ™Œ 1
gratitude 1
Dustin Paluch02:03:00

Yeah, I was looking at the Java docs for String. Thanks!

flowthing13:03:28

tuple expects a vector, but the function parameter list isn't a vector:

(defn f
  [& args]
  (class args))
;;=> #'user/f

(f 1 2 3)
;;=> clojure.lang.ArraySeq
Also, you wouldn't be able to use tuple spec things like varargs. You probably want s/cat: (s/fdef hi :args (s/cat :number int?)).

πŸ™ 1
Nom Nom Mousse13:03:08

What is wrong with my specs? My minimal example fails

andrewzhurov14:03:13

Is there a clj-file-path->edn?

walterl14:03:08

Do you mean like (edn/read-string (slurp "/path/to/file.edn"))?

andrewzhurov15:03:05

yup. I tried that and it returns only the first expression. how would you read the rest?

walterl15:03:15

I don't think EDN supports multiple top-level values. If you have that, it should probably be wrapped in a top-level vector.

walterl15:03:21

Or, if you want to hack it: (edn/read-string (str "[" (slurp "path/to/file.edn") "]"))

walterl15:03:30

But you should probably fix the EDN

andrewzhurov15:03:24

ha, that's a clever hack.:)

andrewzhurov15:03:31

I need that utility in order to read a .clj file, so it won't have a top-level collection

andrewzhurov15:03:33

I'm thinking perhaps a file can be read expression-after-expression via https://clojuredocs.org/clojure.edn/read

walterl15:03:23

Ah. If you're reading Clojure source, https://clojuredocs.org/clojure.core/read is the tool for the job

andrewzhurov15:03:15

Thanks!:) I stumbled upon this piece of code for reading a Clojure program via read:

(with-open [in (java.io.PushbackReader. ( "foo.txt"))]
  (let [edn-seq (repeatedly (partial edn/read {:eof :theend} in))]
    (dorun (map println (take-while (partial not= :theend) edn-seq)))))
Looks good

delaguardo15:03:13

(require '[ :as io]
         '[clojure.tools.reader.edn :as edn]
         '[clojure.tools.reader.reader-types :refer [push-back-reader]])

(with-open [rdr (-> "/path/to/edn/file"
                    (io/reader)
                    (push-back-reader))]
  (loop [acc []]
    (let [exp (edn/read {:eof ::eof} rdr)]
      (if (= ::eof exp)
        acc
        (recur (conj acc exp))))))

πŸ‘ 1
❀️ 1
andrewzhurov15:03:31

Can a Clojure program be read as edn? edn is a subset of Clojure data, as said https://clojuredocs.org/clojure.edn/read so the rest of Clojure data set should fail to be captured as edn, but I can't think of what that rest may be.. I.e., what is clojure.set/difference(Clojure data, edn)?

ghadi15:03:06

@brownmoose3q not comprehensive but: regexes deref @ unquote splicing ` anonymous functions vars #? conditional forms

βœ… 1
andrewzhurov16:03:48

Ahh, I see. Many of these exist at macro-time and result in some edn or run-time values. E.g., @ => (deref) E.g., #() =>"#function[clojure-multisets-sandbox.main/eval5976/fn--5977]"

andrewzhurov16:03:06

Interestingly, reader conditionals can be preserved while reading via read-string

(read-string {:read-cond :preserve}
             "#[email protected](:clj [3 4] :cljs [5 6])")
=> #[email protected](:clj [3 4] :cljs [5 6])
as shown https://clojure.org/reference/reader#_reader_conditionals, at the bottom

quoll17:03:45

I've found most of the reader macros cause issues. I first encountered this with regex literals.

andrewzhurov17:03:37

@U051N6TTC same here when using edn readers, and then I stumbled upon clojure.tools.reader and it seems to read all kinds of stuff just fine

(require '[ :as io]
         '[clojure.tools.reader.edn :as edn]
         '[clojure.tools.reader.reader-types :refer [push-back-reader]])
(require '[clojure.tools.reader :as r])

(with-open [rdr (-> "src/clj/clojure_multisets_sandbox/main.clj"
                    #_"resources/simple.clj"
                    (io/reader)
                    (push-back-reader))]
  (let [result (loop [acc []]
                 (let [exp (r/read {:eof ::eof} rdr)]
                   (println (pr-str exp))
                   (if (= ::eof exp)
                     acc
                     (recur (conj acc exp)))))]
    (spit "derived/main.clj" result)))
I did just a small tweak to https://clojurians.slack.com/archives/C053AK3F9/p1648223353207799?thread_ts=1648217533.109439&amp;cid=C053AK3F9 @U04V4KLKC kindly provided for reading edn and now it seems to munch Clojure programs! My tests were not exhaustive though, but it reads ns with that code no prob. (the tweak is edn/read => r/read)

ghadi15:03:18

namespaced maps/kws

andrewzhurov15:03:46

(clojure.edn/read-string (pr-str #:ns{:key :val}))
=> #:ns{:key :val}

(clojure.edn/read-string (pr-str :ns/key))
=> :ns/key
hmm, seems edn preserve ns in maps and kws

ghadi15:03:45

some of this is accidental/undocumented

andrewzhurov16:03:37

I see they use :my/fred as an example of keyword in edn doc, https://github.com/edn-format/edn#keywords, perhaps ns is supported for keywords. :: is not allowed, however.

andrewzhurov16:03:05

no mention of namespaced maps, indeed

ghadi16:03:56

namespaced keywords are ok, but not :: alias resolution

sheluchin15:03:00

Given a seq of maps, is there a better way to return the first map where :x is :y than the (some #(when (...) %) s) thing?

andrewzhurov15:03:00

some seems fine although I found it rare to need the first, in my experience usually it's a filter what are criteria of 'better'?

sheluchin16:03:14

@brownmoose3q Seems like an fairly common operation and I'd expect a find-first thing somewhere in core, but for sure there's nothing stopping me from writing a little helper for it.

teodorlu16:03:19

There's also filter and first

bb -e '(->> [{:x :x} {:x :y}] (filter #(= :y (:x %)) ) first)'
{:x :y}

andrewzhurov17:03:34

I thought filter is lazy and will resolve values as they are being asked, one-by-one, but it seem to resolve not only the asked values, but all of them:

(->> (range 5)
     (filter (fn [el] (println el) true)) ;; if element is printed it indicates that it has been processed
     first ;; asking to resolve only first
     with-out-str)
;; => "0\n1\n2\n3\n4\n" ;; getting all of them resolved
;; whereas expected to get resolved only the first one, having result of "0\n"

❌ 1
andrewzhurov17:03:28

But fret not, transducers to the resque!

(def xf (comp (take 1)
              (filter (fn [el] (println el) true))))

(with-out-str (transduce xf conj (range 5)))
;; => "0\n"
Not an overkill in the slightest. πŸ˜„

πŸ™‚ 1
teodorlu17:03:59

you might be seeing chunking -- if filter was fully realizing the sequence, this shouldn't work!

bb -e '(->> (range) (filter #(< 10 %)) (take 20))'
(11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30)

andrewzhurov17:03:15

Ah, it seems filter is lazy, it was fully resolved because (range 5), which I used to feed into filter, is not lazy! (whereas (range) is E.g.,

(with-out-str (str (take 1 (filter (fn [el] (println el) el) (range)))))
;; => "0\n"
;; resolved just one ^

madstap15:03:32

@brownmoose3q (range 5) is also lazy. The effect you're seeing is an optimization called chunking where lazy seq realize 32 elements at a time. Try (range 50) .

πŸ’‘ 1
❀️ 1
Fredy Gadotti18:03:39

Hey guys, do you know other real world applications (not just libraries) with Clojure that has open source code? https://github.com/metabase/metabase is a good example but I'd like to see other applications as well.

Drew Verlee02:03:27

Oynx is a big open source project.

πŸ™Œ 1
ahungry18:03:47

http://riemann.io/ is a great clojure tool for infrastructure

πŸ™Œ 1
domparry18:03:28

And of course, penpot and xtdb.

ahungry18:03:20

I'm not sure the code would live up to any reviewer expectations - I wrote it when new to clojure - but AHUBU is a web browser written in clojure I did a few years ago leveraging openJFX built in browser (I added ad filtering code + vim like keybindings and some other UI stuff to it): https://github.com/ahungry/ahubu

πŸ‘ 2
πŸ™Œ 2
Ian20:03:24

Hiya, not sure which channel to post in, but I want to get back into clojure, used it for a few years ending a year ago and miss it. Is there a user group (London or remote) or a project that I can help contribute to?

Drew Verlee02:03:24

This slack is the largest clojure community, just answering questions here goes a long way.

practicalli-john10:03:34

https://londonclojurians.org/ is a Clojure user group in London, although all our events are online during the pandemic (and many may remain online after, as they have been more popular online) There are several ways to get help from the community, although slack arguably has the large audience, with #beginners typically the most active for questions/answers (sizes does not guarantee quality though) https://practical.li/blog/posts/cloure-community-getting-help/

seancorfield21:03:26

#london-clojurians is a pretty active bunch with a lot of meetups (and a lot of recordings already posted to YouTube). If you're in the UK, join #clojure-uk if you haven't already and you can find out where folks are near you and get local help/encouragement etc @ianrvaughan

πŸ‘ 1
Ian22:03:13

I didn’t even search for those channels, thanks for that, I’ve not joined and will checkin with them, cheers.

John Bradens22:03:50

Hey I'm trying to follow this sidebar example, but when I click to open the html page, it's just a blank page with no sidebar. Any idea why it's not working for me? https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/simple-sidebar If you have any other suggestions for sidebar tutorials I'm open to new ideas as well.

βœ… 1
dgb2322:03:59

Does the console spit anything out?

John Bradens22:03:48

Good question. I'm going to try it with the source code. I did

cd Downloads/reagent-cookbook-master/recipes/simple-sidebar
then
lein clean
lein cljsbuild once prod

John Bradens22:03:04

I get

Compiling ["resources/public/js/compiled/app.js"] from ["src/cljs"]...
Mar 25, 2022 3:38:06 PM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: /Users/username/Downloads/reagent-cookbook-master/recipes/simple-sidebar/target/cljsbuild-compiler-0/reagent/core.js:984: WARNING - [JSC_UNREACHABLE_CODE] unreachable code
return null;
^^^^^^^^^^^^

Mar 25, 2022 3:38:06 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 0 error(s), 1 warning(s)
Successfully compiled ["resources/public/js/compiled/app.js"] in 17.056 seconds.

dgb2322:03:34

the example has an error

dgb2322:03:17

change the menu-toggle-did-mount function like so:

(defn menu-toggle-did-mount [this]
  (.click (js/$ (rdom/dom-node this))
          (fn [e]
            (.preventDefault e)
            (.toggleClass (js/$ "#wrapper") "toggled") ;#wrapper will be the id of a div in our home component
            )))

dgb2322:03:42

note its rdom/dom-node instead of reagent/dom-node

dgb2322:03:04

if you are using Calva with VSCode or Cursive this should throw an linting error

gadfly36123:03:26

@U01EFUL1A8M thanks for the correction, I think the recipe was made back when dom-node was in reagent ns

πŸ‘ 1
gadfly36123:03:05

Looks like the example code is updated but the readme is outdated

gadfly36123:03:16

Just updated the readme πŸ‘

dgb2323:03:12

The css download might be incompatible

dgb2323:03:32

Not the same as in the repo

John Bradens23:03:52

I changed rdom/dom-node to reagent/dom-node and now I get

WARNING: Use of undeclared Var reagent.core/dom-node at line 17 src/cljs/simple_sidebar/core.cljs
Any thoughts on this?

John Bradens23:03:51

I also saw the css download that's linked in bootstrap is different than what is in the repo, so I'm just using what's in the repo for now. I'm new to CSS as well

John Bradens23:03:53

I misread your earlier message @U01EFUL1A8M, I had drom/dom-node already. Once I got errors trying it on my own, I switched to trying a clone of the repo directly

dgb2300:03:57

Btw if you’re completely new to CSS and some of the other web fundamentals then I can highly recommend using the MDN docs. There are some really well made comprehensive guides there and a full blown reference with examples and links. The search is also very good. Similarly Iearned a lot of clojure just with http://clojuredocs.org also has a good search, links to the source, examples and comments.

John Bradens00:03:05

@U01EFUL1A8M Awesome resources, thanks for sharing!

John Bradens00:03:50

@U01EFUL1A8M @U0522BZ1R Any idea why I get a blank html page when I try to compile the simple-sidebar repo? I get the same error as before:

Compiling ["resources/public/js/compiled/app.js"] from ["src/cljs"]...
Mar 25, 2022 5:33:20 PM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: /Users/username/Downloads/reagent-cookbook-master/recipes/simple-sidebar/target/cljsbuild-compiler-0/reagent/core.js:984: WARNING - [JSC_UNREACHABLE_CODE] unreachable code
return null;
^^^^^^^^^^^^

Mar 25, 2022 5:33:20 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 0 error(s), 1 warning(s)
Successfully compiled ["resources/public/js/compiled/app.js"] in 17.952 seconds.
not sure what it means or if I'm doing something wrong on my end. All I did was change directories, then lein clean, and lein cljsbuild once prod :thinking_face:

gadfly36100:03:29

@U02387J8EKG I am away from a computer atm, so unfortunately can't look into this any further. Next time I am tho I'll see if I can reproduce what you are seeing

John Bradens00:03:55

That's great, thanks! @U0522BZ1R

gadfly36123:03:08

@U02387J8EKG did you open the resources/public/index.html file in a browser? I did and it works for me. Note: I saw the same warning when compiling, but it looks like it works.

John Bradens23:03:17

Hey I just checked it and it works for me now! Not sure why it didn't before. Thanks for responding!

πŸ‘ 2