beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
suren 2020-10-06T01:40:09.332700Z

$ lein ring server-headless
2020-10-06 12:36:28.980:INFO::main: Logging initialized @1474ms
Exception in thread "main" Syntax error compiling at (/private/var/folders/9d/3zkfrpnj15j6j2qnr53jqsmw0000gn/T/form-init2589101478955306490.clj:1:125).
	at clojure.lang.Compiler.load(Compiler.java:7647)
	at clojure.lang.Compiler.loadFile(Compiler.java:7573)
	at clojure.main$load_script.invokeStatic(main.clj:452)
	at clojure.main$init_opt.invokeStatic(main.clj:454)
	at clojure.main$init_opt.invoke(main.clj:454)
	at clojure.main$initialize.invokeStatic(main.clj:485)
	at clojure.main$null_opt.invokeStatic(main.clj:519)
	at clojure.main$null_opt.invoke(main.clj:516)
	at clojure.main$main.invokeStatic(main.clj:598)
	at clojure.main$main.doInvoke(main.clj:561)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.main.main(main.java:37)
Caused by: java.lang.AssertionError: Assert failed: self-referential dependency
(not (= x dep))
	at ns_tracker.dependency$depend.invokeStatic(dependency.clj:54)
	at ns_tracker.dependency$depend.invoke(dependency.clj:48)
	at ns_tracker.dependency$depend$fn__1319.invoke(dependency.clj:59)
	at clojure.core.protocols$naive_seq_reduce.invokeStatic(protocols.clj:62)
	at clojure.core.protocols$interface_or_naive_reduce.invokeStatic(protocols.clj:72)
	at clojure.core.protocols$fn__8144.invokeStatic(protocols.clj:169)
	at clojure.core.protocols$fn__8144.invoke(protocols.clj:124)
	at clojure.core.protocols$fn__8099$G__8094__8108.invoke(protocols.clj:19)
	at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
	at clojure.core.protocols$fn__8129.invokeStatic(protocols.clj:75)
	at clojure.core.protocols$fn__8129.invoke(protocols.clj:75)
	at clojure.core.protocols$fn__8073$G__8068__8086.invoke(protocols.clj:13)
	at clojure.core$reduce.invokeStatic(core.clj:6828)
	at clojure.core$reduce.invoke(core.clj:6810)
	at ns_tracker.dependency$depend.invokeStatic(dependency.clj:59)
	at ns_tracker.dependency$depend.doInvoke(dependency.clj:48)
	at clojure.lang.RestFn.applyTo(RestFn.java:146)
	at clojure.core$apply.invokeStatic(core.clj:669)
	at clojure.core$apply.invoke(core.clj:660)
	at ns_tracker.core$add_to_dep_graph$fn__1784.invoke(core.clj:53)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:343)
	at clojure.core$reduce.invokeStatic(core.clj:6827)
	at clojure.core$reduce.invoke(core.clj:6810)
	at ns_tracker.core$add_to_dep_graph.invokeStatic(core.clj:50)
	at ns_tracker.core$add_to_dep_graph.invoke(core.clj:49)
	at ns_tracker.core$update_dependency_graph.invokeStatic(core.clj:62)
	at ns_tracker.core$update_dependency_graph.invoke(core.clj:59)
	at ns_tracker.core$ns_tracker.invokeStatic(core.clj:90)
	at ns_tracker.core$ns_tracker.invoke(core.clj:79)
	at ns_tracker.core$ns_tracker.invokeStatic(core.clj:84)
	at ns_tracker.core$ns_tracker.invoke(core.clj:79)
	at ring.middleware.reload$reloader.invokeStatic(reload.clj:8)
	at ring.middleware.reload$reloader.invoke(reload.clj:7)
	at ring.middleware.reload$wrap_reload.invokeStatic(reload.clj:34)
	at ring.middleware.reload$wrap_reload.invoke(reload.clj:21)
	at ring.server.standalone$add_auto_reload.invokeStatic(standalone.clj:61)
	at ring.server.standalone$add_auto_reload.invoke(standalone.clj:59)
	at ring.server.standalone$add_middleware.invokeStatic(standalone.clj:72)
	at ring.server.standalone$add_middleware.invoke(standalone.clj:69)
	at ring.server.standalone$serve.invokeStatic(standalone.clj:95)
	at ring.server.standalone$serve.doInvoke(standalone.clj:75)
	at clojure.lang.RestFn.invoke(RestFn.java:423)
	at ring.server.leiningen$serve.invokeStatic(leiningen.clj:19)
	at ring.server.leiningen$serve.invoke(leiningen.clj:16)
	at user$eval4205.invokeStatic(form-init2589101478955306490.clj:1)
	at user$eval4205.invoke(form-init2589101478955306490.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7176)
	at clojure.lang.Compiler.eval(Compiler.java:7166)
	at clojure.lang.Compiler.load(Compiler.java:7635)
	... 12 more
Subprocess failed (exit code: 1)

suren 2020-10-06T01:40:09.332800Z

I am clueless as this stack trace points no where in my code. Not sure whats wrong. Any help is appreciated. Thanks

suren 2020-10-06T02:03:36.333100Z

Answering my own question in the hope it will be helpful to others. Turns out two of my clojure files were having save namespace. Apparently ring checks all the clojure files to make sure everything is alright.

seancorfield 2020-10-06T04:12:43.333400Z

For future reference, you can see that in the stacktrace:

...
Caused by: java.lang.AssertionError: Assert failed: self-referential dependency
(not (= x dep))
	at ns_tracker.dependency$depend.invokeStatic(dependency.clj:54)
...
	at ns_tracker.core$ns_tracker.invoke(core.clj:79)
	at ring.middleware.reload$reloader.invokeStatic(reload.clj:8)
So you can see the Ring reload middleware function is calling into the ns-tracker code and that's what raised the "self-referential dependency"

seancorfield 2020-10-06T04:15:43.333600Z

My recommendation would be: 1) do not use the ring plugin for lein -- learn how to start Jetty from your -main and use lein run to start it 2) do not use reloading middleware -- learn to develop a "REPL-driven" workflow so you don't need any of these auto-reload/refresh plugins etc Both of these will make you a better Clojure developer and you'll be relying less on "magic" -- when those "easy" things go wrong, you won't know how to fix them; if you can do this without the "magic" pieces, you'll have more control and more insight into the process.

seancorfield 2020-10-06T04:16:55.333800Z

In particular, if you had a tight REPL-driven workflow, you would probably have caught the namespace problem immediately, in your editor, via the REPL -- before even trying to run the code from the command-line.

practicalli-john 2020-10-06T04:33:44.334100Z

I also concur with Sean about the lein-ring plugin, it's quite simple to define a sever that can be managed by the repl in just a few lines of simple code https://practicalli.github.io/clojure-webapps/app-servers/simple-restart.html#code-example

practicalli-john 2020-10-06T04:35:34.334300Z

Using this kind approach approach should make it easier to understand libraries like mount, integrant for managing the lifecycle of services (database, app server, etc)

seancorfield 2020-10-06T04:37:16.334500Z

And if you do want to "look ahead" at some simple web apps that avoid lein-ring (in fact, avoid Leiningen altogether), that use Component, Compojure or Integrant, Reitit, along with some database access and and HTML templating, take a look at https://github.com/seancorfield/usermanager-example and https://github.com/PrestanceDesign/usermanager-reitit-integrant-example

Ping 2020-10-06T04:46:57.336Z

Is it normal to see a DevTools message i prod?

Ping 2020-10-06T04:47:06.336200Z

Is it normal to see a DevTools message i prod? How can I resolve this?

DevTools failed to load SourceMap: Could not parse content 
for 
<https://xxx/js/Loading.js.map>: 
Unexpected token &lt; in JSON at position 0

Ping 2020-10-06T04:48:04.336800Z

I also have this error. I am stuck here.

Ping 2020-10-06T04:49:01.337Z

Warning: React.createElement: type is invalid -- expected a 
string (for built-in components) or a class/function (for 
composite components) but got: undefined. You likely forgot 
to export your component from the file it's defined in, or 
you might have mixed up default and named imports.

Check the render method of `lba`.
in lba (created by mba)
in Suspense (created by M4)
in M4 (created by mba)
in mba (created by $$)
in $$
in Unknown (created by class_1)
in class_1

seancorfield 2020-10-06T05:31:47.339600Z

@flora.makgaba "Unexpected token < in JSON" sounds like the HTTP request for the source map is returning an HTML page, but I don't know what "DevTools" you're referring to. If the source map isn't available, I'd expect a 404 Not Found error so perhaps your apps is not set up correctly? No idea about React. Depending on what specific tech you are using, there may be a more relevant channel to ask than here?

phronmophobic 2020-10-06T05:33:22.339900Z

we're discussing in this thread: https://app.slack.com/client/T03RZGPFR/C03S1L9DN/thread/C03S1L9DN-1601960028.287200

phronmophobic 2020-10-06T05:33:48.340300Z

in #clojurescript

seancorfield 2020-10-06T05:34:33.340500Z

Thanks. They also posted on StackOverflow (but no one has answered yet).

suren 2020-10-06T06:42:02.340700Z

Thanks guys I will keep these in mind.

Mark Wardle 2020-10-06T14:15:11.346600Z

Hi all. I am looking into configuration management - blending environmental variables, defined configuration files and system property files, perhaps command-line stuff - both properties (-D) and maybe arguments. There are many libraries here, which is fine for a single application, but what about when building libraries themselves? My initial thought on this, as a clojure beginner, is to build some kind of facade config pattern to decouple getting configuration data from the way it is set when used in a specific application? The facade simply presents configuration data as a map, obviously… but how that map is initialised would then depend on runtime - and not whether one uses mount or component or a specific config library or something else… A bit like tools.logging / slf4j facade and then a concrete implementation? Or is this a crazy thing and am I overthinking this?

practicalli-john 2020-10-07T12:37:24.438800Z

I typically use aero for managing configuration https://juxt.pro/blog/aero

Mark Wardle 2020-10-07T21:18:46.489100Z

Thanks. I did look at that, but one of the issues was having that as a dependency for something that’s logically a library - hence the thinking about facade pattern. But in retrospect, I think I was overthinking the whole thing, as its so trivially easy to switch. Thanks for the tip!

ghadi 2020-10-06T14:21:36.348500Z

@mark354 you are correct to want a map as config. I would decouple the config data from the components themselves. The components should never "reach outwards" to discover config, config should be provided as an argument to the component's constructors

👍 1
Mark Wardle 2020-10-06T14:25:15.348900Z

Thanks. That’s what I’ve done so far but even things like security credentials - feels messy once you have more than one or two configuration details for a specific function call.

ghadi 2020-10-06T14:26:14.349100Z

elaborate?

ghadi 2020-10-06T14:29:41.349300Z

another useful pattern is making config a first class system component

Mark Wardle 2020-10-06T14:29:43.349500Z

Well… I have multiple modules that might have 4-5 configuration parameters that, in java, I’d use system properties to define. URLs for production, security credentials, etc.. Here’s some code as example:

(defn resolve!
  "Performs an EMPI fetch using the identifier as defined by `system` and `value` and
  the defined configuration.

  - url : the URL of the EMPI endpoint
  - processing-id : one of P (production) U (testing) or T (development) for type of server.
  - proxy-host : if required, proxy hostname as per clj-http
  - proxy-port : if required, proxy port as per clj-http"
  [system value {:keys [url processing-id proxy-host proxy-port] :as opts}]
  (-&gt; (make-identifier-request system value opts)
      (do-post!)
      (parse-pdq)))

(deftype EmpiService [url processing-id opts]
  Resolver
  (resolve-id [this system value] 
    (resolve! system value (merge {:url url :processing-id processing-id} opts))))
So I’d much prefer to call out to some central configuration, but instead I’ve defined a type that can take those configurations and then allow a call to resolve! but that feels a bit OO-like and unnecessary… a style question really…

ghadi 2020-10-06T14:29:53.349700Z

and providing the config component to your other components

ghadi 2020-10-06T14:30:16.349900Z

heh, I used to work with EMPIs back in the day

ghadi 2020-10-06T14:31:32.350100Z

you shouldn't care about whether your config comes from Java properties, environment variables, files, or S3

ghadi 2020-10-06T14:31:59.350300Z

something should aggregate the application's config, and perform validation -- then provide the checked config map to things that need it

Mark Wardle 2020-10-06T14:32:35.350500Z

That’s a good idea. Thanks.

Mark Wardle 2020-10-06T14:32:59.350700Z

So I can isolate the config implementation, draw it together, and then inject into modules as necessary…

ghadi 2020-10-06T14:33:05.350900Z

yes

ghadi 2020-10-06T14:33:12.351100Z

the config is a module itself

Mark Wardle 2020-10-06T14:33:45.351300Z

So you used clojure in healthcare, or was that in a past life? 😉

ghadi 2020-10-06T14:33:54.351500Z

yes and yes

👍 1
ghadi 2020-10-06T14:34:28.351800Z

i first started using Clojure as an analyst at an academic medical institution

👍 1
Mark Wardle 2020-10-06T14:35:21.352Z

All my work in java until 3 years ago… halved the codesize and doubled my speed of development using golang… and now have done the same again moving to clojure, and yet get to use all my old libraries/ecosystem!

Mark Wardle 2020-10-06T14:35:41.352300Z

Thanks for your help.

ghadi 2020-10-06T14:35:51.352500Z

my pleasure

Matias Francisco Hernandez Arellano 2020-10-06T14:50:18.354900Z

Hey folks.. I have a beginner question about maps. I have a api request that I do using clj-http.client and then parse the json with chesire So I get something like

(client/get url {:async? true} (fn [response] (let [items (get-items response)] ) )```

Matias Francisco Hernandez Arellano 2020-10-06T14:50:41.355500Z

where get-itemsis just a wrapper around (:data (json/parse-string (:body response) true))

Matias Francisco Hernandez Arellano 2020-10-06T14:52:06.357200Z

the issue comes after get-items this returns an array like structure with multiple items that have things like:

{ attributes: { title: '', company: { data: { attributes: { name: '' } } } }, links: { public_url: '' } }```

Matias Francisco Hernandez Arellano 2020-10-06T14:52:23.357700Z

and I need to access all of that nested attribute.. what is the clojure way of doing it?

Matias Francisco Hernandez Arellano 2020-10-06T14:52:52.358400Z

I know that I need to do something like (map parse-items items) and define parse-items

Matias Francisco Hernandez Arellano 2020-10-06T14:53:13.359Z

I was looking at select-keys but not sure how to used in this particular case

ghadi 2020-10-06T14:56:57.360700Z

look at get-in

ghadi 2020-10-06T14:57:29.361700Z

or destructuring https://clojure.org/guides/destructuring

sova-soars-the-sora 2020-10-06T14:57:34.361900Z

Hey @matiasfh nested data access can be done with clojure and there are also a couple of libraries invented to make this easier, one called Specter and another the name escapes me. Anyway, if I understand your question right, you want to traverse this nested structure? You can do it in pure clojure, other hats here can provide code, but you may want to check out Specter. There's a HN discussion about it from recently here: https://news.ycombinator.com/item?id=18578920

Matias Francisco Hernandez Arellano 2020-10-06T14:58:27.362600Z

Yeah I want to traverse the array-like structure to get a few of the attributes of it so then i can use it for format a string that will be pushed back to output

Matias Francisco Hernandez Arellano 2020-10-06T14:58:35.362900Z

will check the thread and Specter library

sova-soars-the-sora 2020-10-06T15:00:41.363500Z

There's a really great comment in that thread that says "Specter solves a problem you should aim to avoid" x) but if you have no choice about the data coming in you may want it

ghadi 2020-10-06T15:02:00.364Z

I'm not a fan of giving beginners Specter

ghadi 2020-10-06T15:02:33.364700Z

the marketing around Specter is hyperbolic

ghadi 2020-10-06T15:03:24.365500Z

for a #beginner, focus on learning the core library

Matias Francisco Hernandez Arellano 2020-10-06T15:07:50.366500Z

Yeah.. in fact I want to learn the clojure way. And @sova yes.. I can't fix the way the data is returned by the api is a 3rd party server

Matias Francisco Hernandez Arellano 2020-10-06T15:08:26.367100Z

The goal of this is to retrieve some of the attributes of this structure to create a set of strings based on that attributes

dpsutton 2020-10-06T15:10:26.367700Z

so you already know how to map. and your question is how to define a function parse-item which works on the following map:

{:attributes {:title "title"
              :company {:data {:attributes {:name "company name"}}}}
 :links {:public-url "public url"}}

dpsutton 2020-10-06T15:10:58.368Z

given this map, what would you like parse-item to return?

Matias Francisco Hernandez Arellano 2020-10-06T15:13:06.369400Z

the map is bigger.. will have more items inside the attributes level so what I want is to map an get a easier structure like

{:title: "title", :companyName: "some", 🔗 "public_url" }```

Matias Francisco Hernandez Arellano 2020-10-06T15:13:58.370400Z

I use to do this with JS by just mapping over the array of objects to create a new array of objects with the new shape.. but that is the JS way.. i figure that is somehow similar with Clojure in terms of the approach. map the map

dpsutton 2020-10-06T15:15:18.370500Z

`

dpsutton 2020-10-06T15:15:21.370700Z

(let [data {:attributes {:title "title"
                         :company {:data {:attributes {:name "company name"}}}}
            :links {:public-url "public url"}}]
  {:title (get-in data [:attributes :title])
   :company-name (get-in data [:attributes :company :data :attributes :name])
   :link (get-in data [:links :public-url])})

dpsutton 2020-10-06T15:15:38.370900Z

shows how to get this data

dpsutton 2020-10-06T15:16:07.371100Z

so you could do

(defn parse-item [data]
  {:title (get-in data [:attributes :title])
   :company-name (get-in data [:attributes :company :data :attributes :name])
   :link (get-in data [:links :public-url])})

(map parse-item response)

Matias Francisco Hernandez Arellano 2020-10-06T15:17:26.371300Z

you know what.. I had that in mind but was unsure of the idea of how that is written.. Thanks!

👍 2
sova-soars-the-sora 2020-10-06T15:23:18.371700Z

Looking good. and as @ghadi says it's sage advice to learn your way around core 😃 many many useful scissors, snips, and pocket knives in there.

💪 2
Santiago 2020-10-06T16:28:24.373700Z

In which situations would (:key coll) return nil if coll is a map? and :key is def not nil because (vals coll) returns the non-nil values and (keys coll) returns :key

Santiago 2020-10-06T16:30:54.374Z

If anyone is interested this is my full script. I’m scratching my head as to why the final lines don’t give me the value of :comments for each map in the vector. (map map?) is true, (map vals) gives me the correct values.. 🤷

Santiago 2020-10-06T16:31:05.374200Z

#!/usr/bin/env bb

(ns jcpsantiago.controltower.airportsscript
  (:require [babashka.curl :as curl]
            [clojure.string :as s]
            [babashka.pods :as pods]))


(pods/load-pod "bootleg")
(require '[pod.retrogradeorbit.bootleg.utils :refer [convert-to]]
         '[pod.retrogradeorbit.hickory.select :as hs])


;; Airline data ;;
(def wiki-airlines 
  (-&gt; "<https://en.wikipedia.org/wiki/List_of_airline_codes>"
      curl/get
      :body))


(defn deepest-text
  "Drill down to the deepest text node(s) and return them as a string."
  [node]
  (cond (vector? node) (apply str (mapcat deepest-text node))
        (map? node) (deepest-text (:content node))
        :else node))


(defn extract-tables [html]
  "Takes an html page and extracts a table element."
  (mapv (fn [table]
          (mapv #(mapv deepest-text
                       (hs/select (hs/or (hs/tag :th) (hs/tag :td)) %))
                (hs/select (hs/tag :tr) table)))
        (-&gt;&gt; (convert-to html :hickory) 
             (hs/select (hs/tag :table)))))


(defn to-keyword
  "This takes a string and returns a normalized keyword."
  [input]
  (-&gt; input
    s/lower-case
    (s/replace \space \-)
    (s/replace "/.+" "")
    keyword))


(defn html-&gt;map 
  "Extracts an html table and turns it into a map."
  [wiki-airlines] 
  (let [table (first (extract-tables wiki-airlines))
        headers (-&gt;&gt; table
                     first
                     (map to-keyword)
                     vec)
        rows (-&gt;&gt; table
                  (drop 1)
                  (mapv #(mapv s/trim-newline %)))]
    (println "Joining rows and headers...")
    (map #(zipmap headers %) rows)))


(defn complete?
  [k coll]
  (every? true? (map not [(= (k coll) "\n")
                          (= (k coll) "n/a")])))

(defn not-defunct?
  [coll]
  (let [c (s/lower-case (:comments coll))]
    (println c)
    (not (s/includes? c "defunct"))))


(def complete-icao? (partial complete? :icao))
(def complete-iata? (partial complete? :iata))


(-&gt;&gt; (html-&gt;map wiki-airlines)
     (filter (every-pred complete-iata? complete-icao?)) 
     (map :comments))

dpsutton 2020-10-06T16:33:38.374400Z

does it return :key: (with a trailing colon)?

Santiago 2020-10-06T16:34:20.374600Z

no sorry, that’s a typo:sweat_smile:

Karo 2020-10-06T16:54:24.376200Z

Hi, what tool can be used to automate creation and update of openAPI documentation in clojure?

Karo 2020-10-07T07:11:52.423400Z

Thank you

2020-10-06T16:56:48.376300Z

what you can do is (doseq [[k _] some-map :when (= (vec (.getBytes (name k))) (vec (.getBytes (name :key))))] (prn k))

2020-10-06T16:57:52.376500Z

which will print out true if any keyword key in the map has a name that is byte for byte the same as the name of your :key

2020-10-06T16:58:01.376700Z

er, print out the key

2020-10-06T16:59:25.376900Z

if it doesn't the keyword you are using as a key in your map (by calling keyword on data you pull from the internet) contains characters that aren't printing, either because of your terminal setup, or because they are some kind of funky whitespace

2020-10-06T17:00:07.377100Z

you are stripping out the space character, but there are many other kinds of whitespace

Santiago 2020-10-06T17:05:25.377300Z

interesting… saving to a text file as edn and reading it back works fine. Wouldn’t this also carry over any whitespace characters?

Santiago 2020-10-06T17:06:19.377500Z

I saved it using pr-str and spit

Santiago 2020-10-06T17:11:57.377700Z

(-&gt;&gt; (html-&gt;map wiki-airlines)
     pr-str
     edn/read-string
     (map :icao))
works fine, is this a sign of something strange happening with character encoding @hiredman?

2020-10-06T17:12:31.377900Z

no idea what works find means

2020-10-06T17:12:54.378100Z

ah, I see, no, my guess is there is some other kind of whitespace character that is not a space

2020-10-06T17:13:40.378300Z

so your :icao keywords all contain an extra character that is not visible when printed, which means it doesn't round trip

sova-soars-the-sora 2020-10-06T17:34:51.378600Z

great question! 😃 bump.

Tzafrir Ben Ami 2020-10-06T18:06:47.378800Z

if you’re using https://github.com/metosin/reitit, it comes with “built it” swagger support. See an example: https://github.com/metosin/reitit/tree/master/examples/http-swagger

👍 1
João Galrito 2020-10-06T18:20:44.379800Z

hello, why is the output of this:

(defn create-es-bulk-writer []
  (let [es-write-chan (async/chan)]
    (println 1)
    (async/go
      (println 2))
    (println 3)
    es-write-chan))
this:
1
3

João Galrito 2020-10-06T18:24:46.380200Z

default thread pool is full (and blocked)?

marshall 2020-10-06T18:30:42.380600Z

put a do around the printlns:

marshall 2020-10-06T18:30:47.380900Z

(defn create-es-bulk-writer []
  (let [es-write-chan (async/chan)]
    (do 
     (println 1)
     (async/go (println 2))
     (println 3) )
    es-write-chan))

marshall 2020-10-06T18:30:58.381200Z

user=&gt; (create-es-bulk-writer )
1
3
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x6c26e588 "clojure.core.as2y
nc.impl.channels.ManyToManyChannel@6c26e588"]
user=&gt;2

João Galrito 2020-10-06T18:31:27.381600Z

i think the problem was threads

João Galrito 2020-10-06T18:31:32.381800Z

i restarted the repl and now it works

marshall 2020-10-06T18:31:50.382500Z

that said, you’re not actually using the channel you make

João Galrito 2020-10-06T18:31:59.383Z

i know

marshall 2020-10-06T18:32:03.383200Z

ok

João Galrito 2020-10-06T18:32:09.383400Z

i changed the code before posting

João Galrito 2020-10-06T18:32:12.383600Z

but left some stuff

João Galrito 2020-10-06T18:32:23.383800Z

the go block was waiting on the channel

João Galrito 2020-10-06T18:32:53.384600Z

and I was using "stop execution" on the repl but I guess the go threads were still running waiting for messages on the channel

Artem 2020-10-06T19:09:58.385500Z

Hello, I have more than 100 files in my lein project that describe the tasks, the data for them and their solution to make sure that the solution meets the described data I am testing the call of the solve function in another test file. For example, I have namespace task-one and task-two and files task_one.clj and task_two.clj, to test them I need to create a separate task_one_test.clj and task_two_test.clj inside test directory, inside test files the same test function is launched, only test data and solution functions differ. Since the task files are more than 100, the test files are also more than 100, but I want to run tests for all the tasks inside one common file, without having to create additional files. I have understood that the deftest macro is tied to the namespace in which it runs, so the test will run only once for this common file, which does not solve my problem with a large number of files describing the same tests. How this problem can be solved?

Santiago 2020-10-06T19:12:08.385600Z

seems like that ws the issue.. string/trim fixed it geez.. thanks!

2020-10-06T22:36:24.388Z

I am not sure I followed all of your description, but you can put all of the tests for a project into a single file of code if you want, in a single namespace, with as many separate deftest forms as you want (or as few as one, but having separate deftest forms can make it easier later to run only a subset of the tests.

2020-10-06T22:37:08.388800Z

No matter how many namespaces your production code is spread across, a single test file can call functions in all of them. There is no requirement that task_one.clj is tested by code in a file named task_one_test.clj

Artem 2020-10-06T23:28:31.389900Z

My main goal is to get rid of the heap of files and avoid copying the deftest to each task, I would like to run tests dynamically for each task, for example by getting a list of namespaces and run a function like this for every task:

(defn run-test [result data solution task-name]
  (deftest task-name
    (is (= result (apply solution data)))))
but for now I can’t figure out how to do it 😞

practicalli-john 2020-10-07T12:45:20.439900Z

If it is the assertions, eg. is expressions, that are repetative, the are function can streamline tests https://practicalli.github.io/clojure/testing/unit-testing/writing-unit-tests.html#testing-assertions-with-a-data-set

👍 1
Artem 2020-10-07T23:56:09.001400Z

Thanks for the link! Solved my problem, that was more easy than I thought!