beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-05-25T03:19:50.355400Z

Ah that’s unfortunate to hear

2021-05-25T03:25:40.358100Z

Would someone be able to recommend a good walkthrough on testing in Clojurescript? I can’t for the life of me figure out how to require and run even the simplest tests from the REPL.

2021-05-25T03:33:34.358900Z

I’m really struggling to grasp reduce but every single example I see is just addition. Are there any really good, simple practical examples?

2021-05-26T15:04:55.476600Z

Thank you for the string example!

2021-05-25T04:20:29.359800Z

So I have a function (check-code some-vector) that checks a vector against a bunch of rules. If they all return true, then the function returns true The screenshot I sent is code to generate x number of vectors of 5 digits. Then at the end, I want to filter it down to find just the results that are true Only problem is that this isn’t super useful How would I set it up to find the code vectors that returned the true value when they were passed in as an argument to check-code?

Lance Erickson 2021-05-25T04:23:40.359900Z

I think you just want to take out the (map check-code call. Use (filter check-code (... instead. check-code can act as the predicate function for filter.

Lance Erickson 2021-05-25T04:30:22.360100Z

When you map with check-code, you are applying a transformation and creating a new vector of booleans, where using filter will just admit any values that pass the predicate function unchanged.

2021-05-25T04:34:52.360300Z

That’s perfect, thank you

seancorfield 2021-05-25T04:58:50.360600Z

How about this:

user=> (reduce (fn [s w] (if (re-find #"[aeiou]" w) (conj s (first w)) s)) #{} ["the" "dry" "wind"])
#{\t \w}
Given a sequence of words, it produces a set of the first letters of any words that contain vowels.

seancorfield 2021-05-25T04:59:58.360800Z

To do that "long hand", you'd filter the words to just those that contain vowels, then map first across the result to get all the letters, then into #{} or similar to produce just the unique set of first letters.

dabrazhe 2021-05-25T10:28:17.364300Z

What is the canonical way to write this condition chain, without chaining if ?

(zero? ask-price)  then preMarketPrice, but if preMarketPrice is zero again then lastprice

dabrazhe 2021-05-27T09:52:48.011900Z

Thanks guy. I enjoyed both your solutions

dabrazhe 2021-05-27T09:53:27.013Z

Cool trick with some-> @delaguardo !

Aron 2021-05-25T10:43:20.364600Z

pattern matching : )

jkxyz 2021-05-25T10:49:09.365700Z

Personally I’d write a function like (defn non-zero [n] (when-not (zero? n) n)) and then it’s just (or (non-zero ask-price) (non-zero preMarketPrice) lastprice)

jkxyz 2021-05-25T10:50:51.366200Z

But for an isolated case I don’t think there’s anything wrong with nested ifs, either

Aron 2021-05-25T10:53:38.366900Z

And it looks like something that might be applicable in different situations, so it might worth speccing it and that opens up possibilities with regard to default value handling

dabrazhe 2021-05-25T11:00:38.367400Z

Pattern matching feels like overkill and not overly functional : )

Aron 2021-05-25T11:01:13.367900Z

but it's extensible : D you can add further conditionals later : D

2021-05-25T11:07:21.368200Z

try some-> or some

2021-05-25T11:07:49.368400Z

it can “short-circuit out” if result is not nil

2021-05-25T11:08:54.368600Z

but you will need to make few separate functions to obtain corresponding price and return nil if result is zero

Ivan Koz 2021-05-25T11:14:58.369100Z

create a seq of all prices, choose first which is not 0 (some #(when (pos? %) %) prices)

2021-05-25T11:16:30.369300Z

but that will make (potentially) unnecessary side effects

Ivan Koz 2021-05-25T11:18:16.369500Z

like?

2021-05-25T11:26:05.369700Z

(defn get-price []
  (http/request ...))

(def prices 
  [(get-price)
   (get-price)
   (get-price)])

(some #(when (pos? %) %) prices)
like this

Ivan Koz 2021-05-25T11:27:13.369900Z

wrap requests in a delay, make it lazy

Ivan Koz 2021-05-25T11:27:58.370300Z

or fetch all prices at once, not even a problem is prices are parsed or queried from database

2021-05-25T11:28:33.370500Z

(defn get-price-1 [args] ...)

(defn get-price-2 [args]
  (http/request ...))

(defn get-price-3 [args] ...)

(some-> args (get-price-1) (get-price-2) (get-price-3))
this one ^ will not make http request if the result of get-price-1 is not nil

Ivan Koz 2021-05-25T11:29:13.370700Z

why would anyone need 3 http requests to get 3 numbers

2021-05-25T11:30:42.370900Z

it depends, sometimes it might be required. I don’t think you understand completely the problem, do you?

2021-05-25T11:32:12.371100Z

also http request is just for illustrative purposes. It can be anything else - executing of db statement, fetching from file, asking user to enter price from stdin

2021-05-25T11:32:40.371300Z

anything that falls into huge space of IO operations

Ivan Koz 2021-05-25T11:33:09.371500Z

again if laziness is a concern there is delay

2021-05-25T11:33:59.371700Z

the laziness is not a concern

Ivan Koz 2021-05-25T11:35:45.371900Z

you just said: this one ^ will not make http request if the result of get-price-1 is not nil that is exactly about laziness and delayed evaluation

2021-05-25T11:36:25.372100Z

nono, it is about executing or not of some IO operations.

Ivan Koz 2021-05-25T11:39:14.372300Z

Lazy evaluation, is an evaluation strategy which delays the evaluation of an expression until its value is needed.
So since some is a short-circuit operation, making source of lazy calls will not evaluate more than needed.

2021-05-25T11:39:45.372500Z

try this expression (first (map prn [1 2 3 4 5 6 7])) map returns lazy sequence, prn is doing side effects I expect it to print only one number but in reality it will print entire collection

2021-05-25T11:41:18.372700Z

only some-> can stop the chain (some zero? (map (fn [i] (prn i) i) [1 2 3 0 5 6 7]))

gibi 2021-05-25T11:47:28.373300Z

hi, how would you refactor this handler function to be more idiomatic?

(fn [request]
             (let [todo-list (:body-params request)
                   conn (db/db-connection!)
                   saved-todo-list (db/insert-todo-list! conn todo-list)
                   _ (db/close! conn)]
               {:status 201
                :body   saved-todo-list}
               ))

Ivan Koz 2021-05-25T11:47:45.373400Z

(some #(when (pos? @%) @%) [(delay (side-effect 0))
                            (delay (side-effect 1))
                            (delay (side-effect 2))])
0
1
=> 1

2021-05-25T11:49:02.373600Z

right, but that implies a certain interface for every element in a sequence

2021-05-25T11:56:37.373800Z

you could create a wrapper similar to with-open to open connection, do something with it and close at the end.

(defmacro with-open-conn [[conn open-expr] & body]
  `(let [~conn ~open-expr]
     (try
       (do ~@body)
       (finally (db/close! ~conn)))))

👍 1
Joni Hiltunen 2021-05-25T12:00:22.375200Z

New to everything... Is it possible to use spec to say that if one thing is X then other thing must be Y or else etc... Hard to explain, I have a gist https://gist.github.com/Sose/6df4962cf02c5a10aba43559ad9f5519#file-spec-cljs-L11

2021-05-25T12:01:43.375300Z

maybe you are looking for https://clojuredocs.org/clojure.spec.alpha/multi-spec

Joni Hiltunen 2021-05-25T12:03:38.375500Z

Hmm, that might be it.. Just need to figure out how to use it 😄

2021-05-25T12:07:45.375800Z

(defmulti by-command (fn [[command _]] command))

(defmethod by-command :move [_]
  (s/tuple ::command ::move-arguments))

(defmethod by-command :turn [_]
  (s/tuple ::command ::turn-arguments))

(defmethod by-command :repeat [_]
  (s/tuple ::command ::repeat-arguments))

(s/def ::instruction (s/multi-spec by-command :instruction))
something like this should work

Joni Hiltunen 2021-05-25T12:08:13.376Z

thank you for the example!

Joni Hiltunen 2021-05-25T12:45:38.376200Z

tbh I didn't fully understand the multi-spec thing but I managed to do what I wanted with s/or... (I think) https://gist.github.com/Sose/b4b319baacc219ba03b919f5b5ad0014

Joni Hiltunen 2021-05-25T13:50:00.377200Z

I wonder if there's already a function that does this?

(defn run-script [turtle [instr & script]]
  (if instr
    (recur (step-turtle turtle instr) script)
    turtle))

Joni Hiltunen 2021-05-25T13:56:11.377500Z

ahh.. that's reduce I think

☝️ 1
Audrius 2021-05-25T15:39:33.378700Z

Hi, what would be the Wordpress of Clojure?

alexmiller 2021-05-25T15:45:56.379Z

probably https://github.com/cryogen-project/cryogen

👍 1
alexmiller 2021-05-25T15:46:13.379200Z

http://cryogenweb.org/

2021-05-25T16:27:16.381100Z

Suppose I want to use partition-by, but I want the logic to depend on some already seen values (not only the “next” value). Do I need to implement my own via reduce?

2021-05-25T16:32:49.381700Z

that would be the simplest thing - either reduce or a function using lazy-seq surrounding a self call to build the values

2021-05-25T16:40:19.382400Z

(defn filter-weird
  ([coll]
   (filter-weird #{} coll))
  ([seen [x & xs :as coll]]
   (lazy-seq
    (cond (empty? coll)
          nil
          (contains? seen (inc x))
          (filter-weird seen xs)
          :else
          (cons x
                (filter-weird (conj seen x)
                              xs))))))
user=> (filter-weird (range 10 0 -1))
(10 8 6 4 2)
@jeffrey.wayne.evans - I totally spaced the "partition" thing, but it's a simple demo of having a state accumulator (as you would in reduce) inside a lazy function

2021-05-25T16:46:28.382900Z

could also do it as a stateful transducer, I suppose

2021-05-25T16:46:40.383300Z

and just have the fn passed to partition-by accept two args

2021-05-25T16:47:51.384100Z

yeah - these recursive lazy-seq building idioms are straightforward to build as a transducer - the main question I guess is whether laziness is useful in your use case

2021-05-25T16:49:03.384600Z

yeah not so much

2021-05-25T16:49:09.384800Z

the “real application” is for tiny structures

Joni Hiltunen 2021-05-25T16:51:20.385600Z

This isn't quite reduce is it? I wonder if there's a function for this

(defn- repeat-turtle
  [turtle [n subscript]]
  (loop [i 0
         res turtle]
    (if (>= i n)
      res
      (recur (inc i) (run-script res subscript)))))

2021-05-25T16:53:28.386200Z

it's iterate plus a side effect (which means clojure.core/iterate isn't safe for this kind of usage I think)

Joni Hiltunen 2021-05-25T16:54:26.386800Z

there isn't a side effect. run-scriptis a function of type turtle -> script -> turtle

Joni Hiltunen 2021-05-25T16:57:46.389300Z

(defn- repeat-turtle
  [turtle [n subscript]]
  (last (take (inc n) (iterate #(run-script % subscript) turtle))))
this seems to be equivalent... is there a better way than (last (take ..))?

2021-05-25T17:00:44.391800Z

(-> turtle
    (->> (iterate (fn [step]
                    (run-script step subscript))))
    (nth (inc i))) 
maybe?

Joni Hiltunen 2021-05-25T17:01:44.392300Z

right.. nthlol 😄 thanks

2021-05-25T17:02:23.393200Z

if you flip the args to subscript you can use partial:

(-> turtle
    (->> (iterate (partial flipped-run-scropt subscript)))
    (nth (inc i)))

Joni Hiltunen 2021-05-25T17:03:33.393500Z

mm, thanks

haywood 2021-05-25T17:30:11.397500Z

(read-string "(rf/dispatch [::events/some-event 1])")

=> Invalid token: ::events/some-event
Anyone know what I need to provide so read-string doesn’t throw here? I’m not sure which opts read-string takes, some Java Object opts down in the clojure.lang.RT class. I’m thinking I need to do something with a wrapping (bindings form?

2021-05-25T17:34:12.398Z

there isn't an option you can provide to read string

2021-05-25T17:35:17.398900Z

when reading keywords with '::' the namespace part is resolved against the value of *ns*

2021-05-25T17:37:08.400300Z

so what you would have to do is create namespace, add an alias to that namespace for events, then bind *ns* to that namespace, and call read-string

haywood 2021-05-25T17:43:12.401800Z

dang, ok. just to expand on what I’m trying to do, ::events is imported at the top but read-string doesn’t ‘ingest’ that so to speak.. fuller example:

(read-string (str "[(ns <http://my.app|my.app> (:require [my.app.events :as events]))\n\n"
                    "(rf/dispatch [::events/some-event 1])]"))
so I guess I’d have to like, use regexes to read the imports and construct the lookup map with aliases for the reader?

haywood 2021-05-25T17:48:17.402200Z

ok, this worked

(do
    (create-ns 'my.app.events)
    (alias 'events 'my.app.events)
    (read-string (str "[(ns <http://my.app|my.app> (:require [my.app.events :as events]))\n\n"
                      "(rf/dispatch [::events/some-event 1])]")))

dpsutton 2021-05-25T17:49:17.402700Z

what are you trying to do? why problem are you solving?

haywood 2021-05-25T17:50:50.403400Z

I have a build step that generates a routes.cljs file based on what is in the pages directory of the app

haywood 2021-05-25T17:51:18.404Z

part of that is reading in those files and parsing out a few things

dpsutton 2021-05-25T17:54:10.405200Z

if you ditch the reader expanded aliases it might be easier. how much benefit do you get from :my.app.events/some-event vs :event/some-event?

haywood 2021-05-25T17:54:18.405500Z

yea none

haywood 2021-05-25T17:54:26.405800Z

I was looking for something like that

haywood 2021-05-25T17:54:35.406Z

I actually want it to not care

dpsutton 2021-05-25T17:55:51.406800Z

the reader will always care if you ask it for "some-event from the thing called events". but if you are using read-string why not just put those files on the classpath and require them?

haywood 2021-05-25T17:59:47.407200Z

great question….

haywood 2021-05-25T18:00:52.407800Z

well, the script is clojure but the files are clojurescript

haywood 2021-05-25T18:02:27.409100Z

the whole thing is pretty messy, I don’t want to hold y’all up and I really appreciate the tips, I’m going to work on adding aliases from the (ns form in each file iteration

dpsutton 2021-05-25T18:17:10.409200Z

Scratch that :)

Erik B Good 2021-05-25T19:10:34.413100Z

Hello again, I am once again hitting a wall with what seems like a pretty easy situation. Given an arbitrary nested sequence, I want to recreate it with the same nested structure. I am able to do it fairly easily with normal recursion, but I was wondering whether anyone could think of an answer using (recur). I am surprised how hard it can be to convert a recursive function to the loop/recur construct in some context.. (= [1 2 [3 [4 5] 6] 7] ((*fn* recreate-struct [ds recreated-ds] (*if-not* (instance? clojure.lang.Seqable ds) (conj recreated-ds ds) (into recreated-ds (map #(*if-not* (instance? clojure.lang.Seqable %) % (recreate-struct % recreated-ds)) ds)))) [1 2 [3 [4 5] 6] 7] []))

haywood 2021-05-25T19:16:24.413600Z

you could learn to harness this magic https://clojuredocs.org/clojure.walk/postwalk

haywood 2021-05-25T19:17:36.414100Z

sorry, that’s not super helpful but if you weren’t aware of that namespace it’s awesome

phronmophobic 2021-05-25T19:19:52.415500Z

for nested sequences, I'll often use clojure.zip. A common starting point is:

(defn clj-zip [obj]
  (z/zipper #(and (seqable? %)
                  (not (string? %)))
            identity
            (fn [node children]
              (if (map-entry? node)
                (vec children)
                (into (empty node) children)))
            obj))
you can emulate prewalk with:
(defn zip-walk
  "Depth first walk of zip. edit each loc with f"
  [zip f]
  (loop [zip zip]
    (if (z/end? zip)
      (z/root zip)
      (recur (-&gt; (z/edit zip f)
                 z/next)))))
it's pretty easy to also emulate postwalk and I find it a little more flexible than clojure.walk example usage:
(-&gt; {:a 2
     :b [3 4 5]
     :c {:d 10}
     11 12}
    clj-zip
    (zip-walk (fn [x]
                (if (number? x)
                  (inc x)
                  x))))
;; {:a 3, :b [4 5 6], :c {:d 11}, 12 13} 

Erik B Good 2021-05-25T19:23:25.416100Z

Alright I will talk a look into these two namespaces at once. Thanks both of you dearly for your help

phronmophobic 2021-05-25T19:24:21.416200Z

you may also be interested in something like specter, https://github.com/redplanetlabs/specter

Matheus Silva 2021-05-25T19:51:33.417Z

Does anyone use clojure in wsl with intellij can help me with REPL?

2021-05-25T19:56:44.417300Z

Hi, where can I ask about Compojure

2021-05-25T19:56:45.417500Z

?

2021-05-25T19:57:47.417600Z

You might try the #cursive channel.

Matheus Silva 2021-05-25T19:58:43.417800Z

thanks

seancorfield 2021-05-25T20:08:21.418300Z

@d.ian.b You can ask here

2021-05-25T20:08:58.419Z

there's some default middleware to assoc the request to a system-configuration ?

2021-05-25T20:09:07.419300Z

or something like this?

2021-05-25T20:09:25.419900Z

to make something like a context that interceptors have

seancorfield 2021-05-25T20:09:37.420200Z

Can you explain in a bit more detail what problem you’re trying to solve?

seancorfield 2021-05-25T20:09:47.420500Z

What do you mean by “system-configuration”?

2021-05-25T20:11:05.422900Z

I have a default configuration for the things that are external from my system, then I need to start connections and etc, this "started-config" is what I call a system. I want to make my handlers dependent from my system

seancorfield 2021-05-25T20:11:10.423300Z

(defn wrap-config [handler config]
  (fn [req]
    (handler (assoc req :system/configuration config))))
That would be all you’d need to add a data structure to the request.

2021-05-25T20:11:16.423500Z

yup

2021-05-25T20:11:40.424100Z

that's what I thought when I was talking here hahahah

2021-05-25T20:11:49.424600Z

thanks @seancorfield!

2021-05-25T20:11:57.424900Z

sorry about ruber-ducking here

2021-05-25T20:12:01.425100Z

🙂

seancorfield 2021-05-25T20:12:08.425300Z

:duckie:

😆 1
gibi 2021-05-25T22:23:57.428500Z

hi, I'm using monger and specifically the function find-maps this way

(let [conn (connect-with-credentials &lt;.....&gt;)]
               (try
                 (find-maps (mg/get-db conn "todo-lists") "collection")
                 (finally (disconnect conn))
                 )
               )
it seems find-maps already closes the connection so I get an error in the finally

gibi 2021-05-25T22:25:03.429600Z

this seems to be inconsistent with the other function find-one-as-map that doesn't close the connection. It seems this feature has been introduced with https://github.com/michaelklishin/monger/pull/47 not sure why