Fork me on GitHub
#beginners
<
2021-05-07
>
seancorfield00:05:21

(if (seq cols) (apply map + cols) <whatever other value you want>)

seancorfield00:05:39

Or throw an exception perhaps if it “shouldn’t happen”.

zackteo00:05:18

Okay! Thank you! 😄

seancorfield00:05:54

If you want an exception and you don’t care about getting a lazy seq of sums, you could just (apply mapv + cols) — it will throw an arity error if cols is empty.

zackteo00:05:24

Also by any chance do you have example projects using clojure.tools.cli ? Am trying to use it but another reference might help

seancorfield00:05:16

I don’t know what will be more useful than the examples in the README but clj-new still uses it (even though the old -m command-line is no longer documented). See https://github.com/seancorfield/clj-new/blob/develop/src/clj_new/helpers.clj#L264 for the opts definitions and https://github.com/seancorfield/clj-new/blob/develop/src/clj_new/helpers.clj#L381 for the point of use.

seancorfield00:05:41

(although that uses :assoc-fn in places where I’d use :update-fn now)

seancorfield00:05:30

See this example from tools.cli’s README for what I mean about that:

["-f" "--file NAME" "File names to read"
    :multi true ; use :update-fn to combine multiple instance of -f/--file
    :default []
    ;; with :multi true, the :update-fn is passed both the existing parsed
    ;; value(s) and the new parsed value from each option
    :update-fn conj]

marciol00:05:36

Hi, I'm trying to apply the bean function over java.net.URL but I'm getting this error:

(bean (java.net.URL. ""))
Error printing return value (ConnectException) at java.net.AbstractPlainSocketImpl/doConnect (AbstractPlainSocketImpl.java:399).
Connection refused (Connection refused)
Anyone can say why this is happening?

dpsutton00:05:05

(bean (.URL. "")) shows it has :content on it. If you look at the error thrown by your function you'll see [java.net.URL getContent "URL.java" 1177] in it. And you presumably don't have a webserver running locally on port 80

marciol00:05:39

hmmmm, thank you @dpsutton

dpsutton00:05:56

(slurp (.getContent (.URL. ""))) is the contents of the resource

marciol00:05:35

Yes, the bean function walks over every getter and returns a map.

marciol00:05:00

This is why I'm getting this error. Thank you again @dpsutton

zackteo00:05:50

I think i'm generally just a bit confused about how to package my project into a binary (?) or rather I need to read up more cause I have been pretty much only been using lein run

zackteo00:05:24

@seancorfield I think me asking this would help. Is

my-program -vvvp8080 foo --help --invalid-opt
the equivalent of running the following in the repl ?
(-main "-vvvp8080 foo --help --invalid-opt")

zackteo00:05:46

This is from the quickstart example. I've been particularly confused about how to get that working

seancorfield00:05:41

They should be separate strings.

seancorfield00:05:10

(-main "-vvvp8080" "foo" "--help" "--invalid-opt")

seancorfield00:05:29

-main expects to be called with a sequence of zero or more strings

zackteo00:05:50

Right right :face_palm: i recall a similar confusion I had when working with clojure.java.shell/sh

zackteo00:05:12

Thank you!

Rob Haisfield01:05:42

Just describing my dog in Clojure. Not totally sure if I’m doing this right lol. One area is I want to also describe his reaction to the :triggers but not sure what to do there

zackteo01:05:52

@rob370 seems fine ? Are you perhaps thinking of the triggers being functions?

zackteo01:05:03

Is there a way to print out a table when you do lein run ? I know there is clojure.pprint/print-table but is there a direct that to cli output?

zackteo02:05:32

nvm I just realised it is because I was getting a clojure not found error from not requiring the namespace

zackteo03:05:18

How do I compile a leiningen project? Like I can do lein run to use my program. And I understand I can do lein uberjar but have a feeling that's not what I want exactly?

hiredman03:05:41

What do you want?

zackteo03:05:46

I think I want a simple way to allow someone to package my repo and run it as an executable. I think https://github.com/BrunoBonacci/lein-binplus comes close

zackteo03:05:10

Oh i think I can just include it in my project.clj hmm

hiredman03:05:22

It depends on your audience then, I usually take an uberjar to mean that, but if your audience is less technical then you will need something additional like that lein plugin

zackteo03:05:42

How do you run an uberjar actually?

solf03:05:33

java -jar uberjar.jar

hiredman03:05:03

That depends too

hiredman03:05:44

You can build jar files that launch like that

hiredman03:05:24

But java only knows how to run jvm bytecode, so you either have to hand it jvm bytecode (by aot compiling clojure) or bootstrap (run some bytecode that knows how to load clojure)

zackteo03:05:27

Hmmmm, will have to dig deeper into that but lein bin works well for now java -jar worked too for the standalone.jar that was produced

siva10:05:04

what is the meaning of :* in Clojure?

delaguardo10:05:26

it is a normal keyword, nothing special about it

👍 3
Christian13:05:55

I have a map with thousands of entries and want to find a value of an entry that has my search-value in a nested structure. for example this json:

{
    "id": "nord-finance",
    "symbol": "nord",
    "name": "Nord Finance",
    "platforms": {
      "ethereum": "0x6e9730ecffbed43fd876a264c982e254ef05a0de",
      "binance-smart-chain": "0x6e9730ecffbed43fd876a264c982e254ef05a0de"
    }
  },
  {
    "id": "norse-finance",
    "symbol": "nfi",
    "name": "Norse Finance",
    "platforms": {
      "binance-smart-chain": "0x43f001914c7d347d152f296e8539086fe49f8bd6"
    }
  },
  {
    "id": "northern",
    "symbol": "nort",
    "name": "Northern",
    "platforms": {}
  },
  {
    "id": "nosturis",
    "symbol": "ntrs",
    "name": "Nosturis",
    "platforms": {
      "ethereum": "0xeccf15a4b5976a1365baed5297058b4ca42777c0"
    }
  },
I want to search for the value "0x43f001914c7d347d152f296e8539086fe49f8bd6" in all etherum platform entries and have the id where this unique value is matched. Do I have to iterate through the whole thing?

ghadi13:05:32

unless you build an index data structure that allows for faster access

ghadi13:05:59

aka stick it in a database and let the database do the heavy lifting

Christian13:05:19

I did this with the list for now:

(get (first (filter #(= (get-in % ["platforms" "binance-smart-chain"])
                 "0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82")
             all-coingecko-coins)) "id")
while all-coingecko-coins is the json turned map from chesire. Is this a lot slower than a database, when I do this a lot?

andy.fingerhut14:05:29

Besides using a database, you can also create a Cloure map in memory with the keys being the strings you want to search for, and the values being the entire original map {"id": ...} (including the "ethereum" key -- there isn't really any reason to remove that)

andy.fingerhut14:05:09

That would be one concrete example of 'building an index data structure that allows for faster access' that ghadi mentioned.

ghadi14:05:40

iterating through a list that is in the thousands is not going to be an issue

ghadi14:05:17

it all depends on the wider use-case. Doing this in a service? cardinality is actually in the millions+? etc.

Christian14:05:49

I though about scaling this up. This is for the translation of one api-id-value into another. so I could just do it once, save it and be done

Christian14:05:43

I could transfrom the whole json to "contractAdress" as a key and the id as a value map. Is this what you mean @U0CMVHBL2?

ghadi14:05:00

yes, an index

ghadi14:05:07

txid -> tx

ghadi14:05:21

a map of ^

andy.fingerhut14:05:52

You can change the JSON file if you wish, and have that option, but it is straightforward in Clojure to create the in-memory map with whatever key you want, or even multiple maps with the same Val’s but different keys - whatever you want to search on most often

Endre Bakken Stovner15:05:19

I have the following let in hiccup:

(let [jobinfo @(rf/subscribe [:jobinfo])
       [:div
        [:h4 (.now js/Date)]
        [:pre (with-out-str (pp/pprint jobinfo))]])
The jobinfo updates just fine in re-frame, but the js/Date is not updated when the jobinfo is updated. How do I fix this?

manutter5116:05:31

React might be caching the h4, I’d try

(let [jobinfo @(rf/subscribe [:jobinfo])
      now (.now js/Date)]
       [:div
        ^{:key (str "jobinfo-date-str-" now)}
        [:h4 now]
        [:pre (with-out-str (pp/pprint jobinfo))]])
or something similar

Endre Bakken Stovner15:05:52

Did not work. I remember reading about this in some book about Clojure web programming - will find the answer 🙂

Edward Ciafardini20:05:54

I am trying to figure out a way to use [cheshire "5.10.0"] in my REPL. Is there a best way of doing this? Can I add it as a global dependency? I want to be able to do this in the REPL:

(cheshire/parse-string
  (slurp ""))
Any help would be appreciated

andy.fingerhut20:05:44

Do you know if you are using Leiningen, e.g. you have a file named project.clj in your project? Or perhaps the Clojure CLI tools, e.g. there is a deps.edn file in your project?

Edward Ciafardini20:05:42

I am using leiningen - should have mentioned that

Edward Ciafardini20:05:24

I tried using lein repl and it worked. I was using clj to start the repl for no real reason. Thanks!

andy.fingerhut20:05:06

They use different files to specify the dependencies of your project, but they can also be started even if the file they look for is not present. It is just in that case it will not notice the file of the other tool

andy.fingerhut20:05:49

You could choose to sometimes use one tool for a project, sometimes the other, but it would be your responsibility to keep their dependencies consistent between those two files in that case.

👍 2
seancorfield20:05:17

clj -Sdeps '{:deps {cheshire/cheshire {:mvn/version "5.10.0"}}}'
if you just want a quick REPL anywhere with Cheshire without worrying about deps.edn

Edward Ciafardini20:05:09

clj -Sdeps '{:deps {cheshire/cheshire {:mvn/version "5.10.0"}}}' This command creates a temporary dependency that only lasts until you close the REPL?

seancorfield21:05:12

It will pick up anything from deps.edn if present as well, but it can also be used in a directory without deps.edn.

Edward Ciafardini01:05:44

thank you for all you do

seancorfield20:05:09

There’s a useful plugin for Leiningen called lein-try that lets you do a similar thing: Add this to the :user profile in your ~/.lein/profiles.clj file:

:user {:plugins [[lein-try "0.4.3"]]}
and then you can do:
(! 1418)-> lein try cheshire/cheshire 5.10.0
...
user=> (require '[cheshire.core])
nil

Edward Ciafardini20:05:31

all very useful - I'll save these to my terminal commands .txt file 🌝

Stuart20:05:33

Can someone please help explain what is going on here? I have some tests and assertions defined in (deftest) My file has (run-tests) at the end and I'm running the test by doing Load Current File and Dependencies IF I run the tests I see this:

; Evaluating file: interpreter-tests.cljs

Testing test.interpreter-tests

Ran 2 tests containing 16 assertions.

0 failures, 0 errors.
If I make one of them so that it fails I see this:
FAIL in () (interpreter-tests.cljs:90:9)

add adds

expected: (= {:registers {:a 17, :b 7}, :internal-registers {:par 0}} (math-func :add {:registers {:a 5, :b 7}} [:a 9]))

  actual: (not (= {:registers {:a 17, :b 7}, :internal-registers {:par 0}} {:registers {:a 14, :b 7}, :internal-registers {:par 0}}))


Testing test.interpreter-tests


Ran 2 tests containing 16 assertions.

0 failures, 0 errors.
Why does it still say at the end ran 2 tests containing 16 assertions. 0 failures, 0 errors ? Why doesnt it class my failing test as a failure?

seancorfield20:05:13

You probably want (test-ns *ns*) instead of (run-tests).

seancorfield20:05:24

The clojure.test API is pretty strange in terms of what each (similar) function does in terms of fixtures and reporting. Many of the public functions are really low-level pieces that the other functions call — and are more useful to 3rd party test runners.

seancorfield20:05:14

One of the differences here is that (test-ns *ns*) “Internally binds *report-counters* to a ref initialized to *initial-report-counters*. Returns the final, dereferenced state of *report-counters*.” which I don’t believe (run-tests) does.

Stuart21:05:03

yes, thaats perfect, thank you

seancorfield21:05:06

(that said, I don’t see the behavior you’re seeing when I try (run-tests) in a REPL so I may be wrong)

Stuart21:05:35

changing it to use (test-ns), I now see it reporting failure count i would expect

emilaasa21:05:25

Wouldn't (run-tests) probably just map (test-ns) over the namespaces?

seancorfield21:05:36

Interestingly, run-tests seems to call test-ns… yes @emilaasa

Stuart21:05:52

actually no, I'm being dumb It isn't. It doesnt report the counts at all. But it shows the fails.

seancorfield21:05:14

I’m just looking at the source… so many of these functions call each other with different setups 😐

Stuart21:05:56

ok, i restarted my repl and now i see correct counts. So maybe my file wasn't synced correctly or something.

Stuart21:05:59

How should I run tests?

emilaasa21:05:01

There are plenty of earmuffs in that file - still if you reload your buffer I'd expect it to work

Stuart21:05:25

my problem is, I add tests and I want to run them. But sometimes I forget to evaluate them in the repl, then i dont see the pass / fails as I would expect

Stuart21:05:48

so I put (run-tests) or now (test-ns) at the end and just evaluate whole file

Stuart21:05:56

but maybe this isnt best way

seancorfield21:05:11

Yeah, I think I have it backwards — I actually use run-tests when running tests in a namespace, sorry.

emilaasa21:05:32

What editor are you using? The ones I've used have had some hooks that probably call (run-tests) under the hood

Stuart21:05:44

i'm using calva

emilaasa21:05:08

Hm and you were doing cljs?

emilaasa21:05:32

Maybe wont work then

Stuart21:05:00

Is it more normal to run tests via repl or via terminal / CLI ?

practicalli-johnny07:05:02

There is great value in running tests via the REPL and externally via the command line (possibly by a watcher). I run selective tests (specific namespace, individual deftest) predominantly in the REPL during development and run all tests (including integration tests) via the command line before pushing commits (or if I get unexpected errors or longer running test suite) I run tests within the REPL using a connected editor. This avoids context switching to an external tool, although does require changes to be evaluated before they can be tested. You must manually ensure the REPL is in sync with the saved source code before committing changes. I use Kaocha test runner to run tests via the command line, which always tests code saved to disk, so uses a clearly defined state. This clearly defined state is especially valuable for integration tests. The CLI approach is also more robust for longer running tests than running within an editor. Running tests on the should be able to emulate the test step of a CI/CD service, providing a means to debug issues with such a service.

ghadi21:05:06

REPL

2
ghadi21:05:15

everyone who disagrees is wrong

Stuart21:05:20

I come from C# where tests would be automatically run when a file changes

seancorfield21:05:22

I run tests via my editor (which uses the REPL, of course).

Stuart21:05:22

I kinda miss that

emilaasa21:05:49

Ghadi coming out swinging I like it 😛

🔥 2
seancorfield21:05:13

I have hot keys bound to “run this namespace’s tests”, “run the current test”, and “run the tests in the associated test namespace” — used when I’m working in a source file, so I don’t have to switch to the test file or anything.

Noah Bogart21:05:45

run tests through the editor/repl as you develop, and then at the end of a "session", run the whole test suite from the command line to verify your work

seancorfield21:05:55

Yup ☝️:skin-tone-2:

Noah Bogart21:05:57

only have to do that last step once or twice a day

seancorfield21:05:22

(but that all may be harder with cljs?)

Stuart21:05:52

> “run this namespace’s tests” Calva has this but I think this is what emilaasa pointed out not working for cljs as the repl says this:

; Evaluating file: interpreter.cljs
nil
; Running tests for exfn.interpreter...
; No tests found. 😱, ns: 0, vars: 0
cljs꞉exfn.interpreter꞉> 

emilaasa21:05:52

I think you had the right idea @qmstuart with evaluating (run-tests). I'd probably have it as an expression in the file and just run it from there - maybe with marks or something if VSCode supports it

ghadi21:05:16

As a beginner, you're going to want to focus on avoiding doing the easy, lazy thing: jumping out of your live environment to run your tests from the cli

💯 2
emilaasa21:05:47

I think this is key, every time (atleast that I can remember) I've done things the slower more familiar way I've regretted it and it just took longer to learn the right way. 🙂

ghadi21:05:24

this takes practice

emilaasa21:05:27

Or maybe there's some REPL command abstraction that you can bind a keystroke to

seancorfield21:05:16

(comment
  (run-tests)
  ...)

☝️ 2
👍 2
seancorfield21:05:38

So you can eval it when you want to, rather than having it run every time you eval the file.

emilaasa21:05:32

@qmstuart I'm not a calva / vscode user but: https://calva.io/custom-commands/ might work

👍 2
emilaasa21:05:53

Hm is that even the code btw that you are supposed to run cljs tests with?

Stuart21:05:50

you mean I shouldn't be using (deftest) and (run-tests) to write cljs tests?

emilaasa21:05:55

I have no experience writing cljs at all but I've been surprised before - sec

emilaasa21:05:27

(ns my-project.tests
  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))

emilaasa21:05:33

Is that how you require it?

emilaasa21:05:51

I went and read the source for clojure test code 🙂

emilaasa21:05:05

Instead of cljs.test

emilaasa21:05:47

But it looks like the same deal

Stuart21:05:48

I have this

(ns test.interpreter-tests
  (:require [cljs.test :refer [deftest is testing run-tests test-ns]]
            [exfn.interpreter :refer [interpret build-symbol-table mov math-func get-parity]]))

Stuart21:05:16

yeah, that looks the same

emilaasa21:05:37

I'm out of my depth - I think you're doing the right thing and it's hopefully some REPL state messing you up before

emilaasa21:05:24

Seems to be quite a bit more complicated the code in cljs 😄

practicalli-johnny07:05:02

There is great value in running tests via the REPL and externally via the command line (possibly by a watcher). I run selective tests (specific namespace, individual deftest) predominantly in the REPL during development and run all tests (including integration tests) via the command line before pushing commits (or if I get unexpected errors or longer running test suite) I run tests within the REPL using a connected editor. This avoids context switching to an external tool, although does require changes to be evaluated before they can be tested. You must manually ensure the REPL is in sync with the saved source code before committing changes. I use Kaocha test runner to run tests via the command line, which always tests code saved to disk, so uses a clearly defined state. This clearly defined state is especially valuable for integration tests. The CLI approach is also more robust for longer running tests than running within an editor. Running tests on the should be able to emulate the test step of a CI/CD service, providing a means to debug issues with such a service.