Fork me on GitHub
#beginners
<
2021-01-26
>
solf04:01:48

Is there a way to setup default :jvm-opts on deps.edn? It seems you can only do it under an alias

seancorfield05:01:28

@dromar56 There is currently no way to have a default set of JVM opts.

seancorfield05:01:20

I'm curious about your use case? I don't see how you'd always want the same JVM opts no matter what aspect of the project you're running?

solf07:01:15

I don't actually have a use-case that requires it. But I also very seldom use jvm options (I think today was the first time I used them for something other than setting the heap size). When I tried searching for how to set it using deps.edn, I found you could set them using :jvm-opts through an alias, but I didn't expect it would the only way.

solf07:01:06

Without prior knowledge about when/how someone would want to use jvm opts, I assumed that it also worked as a top level option. This is actually related to an issue I have with the documentation of deps.edn: there's no succinct reference to it. I've read the manual on http://clojure.org, but most of the time I already know how to use it (more or less) and am just trying to find the exact syntax to do it. With leins, I used this: https://github.com/technomancy/leiningen/blob/master/sample.project.clj I haven't found an alternative to deps.edn, and that made my discovery that :jvm-opts is only an alias setting more difficult than it could have been

seancorfield17:01:39

From the deps/CLI reference page: "JVM arguments may either be passed on the command line (with -J) or by using data stored in an alias under :jvm-opts and passed with -X or -A or -M" and also "The configuration file format (in deps.edn files) is an edn map with top-level keys :deps, :paths, and :aliases, plus provider-specific keys for configuring dependency sources." -- so it says there are three top-level keys and it also says :jvm-opts can be stored in an alias. I guess if you have suggestions for making it clearer, you could post that on http://ask.clojure.org

seancorfield17:01:42

The closest equivalent to Leiningen's sample.project.clj is the example-deps.edn in the CLI install, which is copied to ~/.clojure on first use (and also remains in the installation). But that currently refers to -R and -C options which are both deprecated (or maybe even removed at this point). And it does not show :jvm-opts... I'll post a Q on http://ask.clojure.org about that...

solf02:01:24

Thanks a lot!

blak3mill3r05:01:09

@dromar56 One thing you could do is use a shell alias, for any options to clj that you use very frequently while developing

roelof06:01:14

good morning all

😃 3
roelof07:01:44

any shadow-expert who can help me with this How to solve this one :

cljs꞉cljs.user꞉>  @state/orders
nil
; No available JS runtime.
clj꞉cljs.user꞉>  @state
shadow-cljs.edn
{:source-paths ["src"]

 :dependencies [[binaryage/devtools "0.9.10"]
                [proto-repl "0.3.1"]
                [reagent "0.8.0"]]

 :nrepl        {:port 3333}

 :builds
 {:app {:target :browser
        :output-dir "public/js"
        :asset-path "/js"

        :modules
        {:main
         {:entries [giggin.core]}}

        :devtools
        {:after-load  giggin.core/main
         :http-root   "public"
         :http-port   3000}}}}

Mno07:01:02

The repl needs to something that runs js so it can run stuff

Mno07:01:32

Since you're targeting a browser, you need to open the browser

Mno07:01:52

Localhost:3000 it seems.

niveauverleih11:01:25

I just found out that the Duffer brothers (stranger things) were from Durham NC. What is it that makes people from Durham special?

Alex Miller (Clojure team)13:01:40

I think it's the Cheerwine

niveauverleih13:01:37

Sounds appealing. They have cherry beer here in Belgium.

andy.fingerhut18:01:22

Having just moved to the area recently, I suspect it may also have to do with the vinegar based barbecue, which I never heard of before: https://www.youtube.com/watch?v=6ubTQfr_tyY&amp;feature=youtu.be

roelof11:01:07

@hobosarefriends I have a browser open

Mno11:01:29

if you do (js/alert "test") does the alert window pop up?

Mno11:01:15

(have you made sure that nothing else is running on that port?)

roelof12:01:50

yep, I see then a popup with the text test on it on my browser

Mno12:01:51

huh… then it is connected.. that’s pretty weird

Mno12:01:10

maybe ask in #shadow-cljs

Mno12:01:35

no probs, sorry I couldn’t solve it

roelof13:01:57

it is solved

roelof13:01:18

I had to use the namespace before the call

roelof13:01:27

stupid beginners error

Mno13:01:06

Good to hear my dude, and you seem to understand why it happened so that’s even better.

roelof14:01:33

yep I understand now after soeme help of the shadow-cljs channel

Claudio Ferreira14:01:03

Study Algo & Data Struc. in Java will help me become a better Clojure dev?

dpsutton14:01:17

studying algo and data structures in any language will usually help you become a better developer in every other language you use

👍 16
Stuart14:01:04

I agree with @dpsutton,I work with devs where everything is either an object (as in C# object or a string, and every data structure is list. Then they wonder why everything is so slow. Learning data structures and algorithms will never not be a good idea.

roelof14:01:34

is there a better idomatic way to turn for example 123 into (1 2 3) then this :

(map #(rem % 10) (take-while pos? (iterate #(quot % 10) 123)))

tschady14:01:14

you could go via strings.

(map #(Character/getNumericValue %) (str 123)) ; => (1 2 3)

tschady14:01:25

not sure if that’s more idiomatic

roelof14:01:40

thanks, Was hoping i could do it without parse to a string and then back from a string

tschady14:01:31

concise v. fast tradeoff

Christian15:01:08

Maybe you can use partition?

(partition 1 (str 123))
;; => ((\1) (\2) (\3))

roelof15:01:05

could be a idea

Max Deineko15:01:11

@U0EGWJE3E is it required to work on positive integers only?

roelof15:01:34

I think so

👍 3
Malik Kennedy15:01:29

;; I took a try as well: 
(pr-str
 (map #(Integer/parseInt %)
      (str/split "123" #"")))

Malik Kennedy15:01:40

I use (str/split s #"") to split a string into strings on 1 character often, dunno if thats the best way

Malik Kennedy15:01:33

;; Didn't notice this:
;; > positive integers only?
(fn [s]
  {:pre (pos-int? (Integer/parseInt s))}
  (pr-str
   (map #(Integer/parseInt %)
        (str/split s #""))))

tschady15:01:40

@U010A2QSG9H you don’t need to split on #“”. Mapping a function over a string applies it to each character in turn automatically.

tschady15:01:56

(map #(Integer/parseInt %) s) is fine.

Malik Kennedy15:01:18

Thanks for letting me know!

Malik Kennedy16:01:17

Hrm...

1. Caused by java.lang.ClassCastException
   java.lang.Character cannot be cast to java.lang.String

Malik Kennedy16:01:57

;; from
(map #(Integer/parseInt %) "123")

Malik Kennedy16:01:47

AIUI, when you map over a String the function receives a value of type Character, not of String.

Malik Kennedy16:01:04

And Integer/parseInt expects and only accepts a String

Malik Kennedy16:01:08

;; coerce Character to String
(fn [s]
    {:pre (pos-int? (Integer/parseInt s))}
    (pr-str
     (map (comp #(Integer/parseInt %) str) s)))

tschady16:01:54

whoops, sorry, use #(Character/getNumericValue %) instead

roelof16:01:32

oke, but the inout is a number not a string

Mno17:01:47

I mean.. you can also count the length of the number.. and make a list that long by getting the remainders of the number and 10^x but that’s a bit convoluted

noisesmith17:01:11

I like the original version - eg. to get a base other than 10 it only requires changing a constant

roelof17:01:07

he my posts is gone

roelof17:01:22

I have used the code like this :

(->> number
       (iterate #(quot % 10))
       (take-while pos?)
       (map #(rem % 10)))

noisesmith18:01:47

you need a reverse on that though

roelof19:01:53

oke, accordingt o the test I do not. All tests are green with this code

noisesmith19:01:20

user=> (map #(rem % 10) (take-while pos? (iterate #(quot % 10) 123)))
(3 2 1)

roelof19:01:13

but I have to calculate if a number is a amstrong number and those tests are still green

roelof19:01:34

so it seems that this is reversed does not make a difference

tschady20:01:53

i think i solved all those exercism-clojure problems, most anyway, if you want a reference.

tschady20:01:10

https://github.com/tschady/exercism-clojure wouldn’t want to post spoilers, up to you.

tschady20:01:42

but my armstrong is pretty concise.

tschady20:01:54

my clojure was more naive then, so YMMV

roelof20:01:58

oke, and are all your answers approved by a mentor ?

tschady20:01:41

i don’t understand

roelof20:01:30

in exercism you can do the mentored track and a practice track

roelof20:01:42

which one did you do ?

tschady21:01:22

neither. it was 4 yrs ago, I just downloaded all the separate _test.clj , put them in 1 project and made em pass. from e.g. https://github.com/exercism/clojure/blob/master/exercises/armstrong-numbers/test/armstrong_numbers_test.clj

❤️ 3
roelof21:01:20

aha,I do the mentored one so mine soutions get looked at my a xp person in clojure

didibus06:01:15

That's a good question, I think number to string conversion is actually implemented similar to your solution, so it's probably optimal

roelof10:01:15

oke, but the mentor wanted a solution where I did not first convert it to a string and then convert back

didibus18:01:59

Yes that's what I'm talking about

didibus18:01:06

The one where you use mod

noisesmith18:01:53

or the near-substitute, rem

💯 3
didibus19:01:39

(defn num->list
 [num]
 (loop [acc '() q num r 0]
  (if (zero? q)
   acc
   (let [r (rem q 10)
         q (quot q 10)]
    (recur
     (conj acc r)
     q
     r)))))

(num->list 123)
;; => (1 2 3)

didibus19:01:09

Or like you had it:

(defn num->list
 [num]
 (->> num
  (iterate #(quot % 10))
  (take-while pos?)
  (map #(rem % 10))
  (reverse)))

(num->list 123)
;; => (1 2 3)

didibus19:01:25

Ya rem is what you want so it works on negative numbers as well.

roelof19:01:19

I had the last one

Sibelius Seraphini15:01:19

is there a prettier for clojure?

Sibelius Seraphini15:01:49

I’ve found this https://github.com/brandonbloom/fipp, but not sure how to run this in a cli to pretty print my code

delaguardo16:01:38

there is also an awesome zprint library https://github.com/kkinnear/zprint

3
Christian16:01:49

I have once seen a nice youtube? demo of clojure where the presenter is counting words of moby dick to demonstrate clojure. Does anyone know what I'm talking about?

practicalli-johnny10:01:27

Yes, James did some great live coding sessions like this a while ago, great to bring them together. I did a short version of one of his examples to show how to use Cider and the Cider inspector https://www.youtube.com/watch?v=rQ802kSaip4

👀 3
sova-soars-the-sora18:01:18

So is there something special I have to do to make sure my clojure / lein program can access all my linux box environment variables? I am trying to run google translate on my remote box and I keep getting 403 invalid API key even though I have run export GOOG_APP_CREDS = /path/to/file ... the api key works on my local box ;/

noisesmith18:01:42

System/getenv can see everything that your process sees, it shouldn't even be an issue on the java / clojure side

sova-soars-the-sora18:01:59

That's what I was thinking.

noisesmith18:01:47

for debugging: (pprint (into {} (System/getenv)))

noisesmith18:01:14

it might be that it needs the System property to be set

🙌 3
noisesmith18:01:28

or that it's using some config instead of the environment

Alex Miller (Clojure team)18:01:56

depending on how you start an application, it may not be running your shell startup environment

💯 6
sova-soars-the-sora18:01:48

gasp. is no there in the pprint list.

noisesmith18:01:02

"export" is for the current shell and child shells, you need the export to happen in the parent of the java process - I usually prefer to add the env var as a prefix on the java command itself

sova-soars-the-sora18:01:22

Hmmm okay... what's that look like?

noisesmith18:01:38

FOO=bar java ...

noisesmith18:01:02

or env $(cat env_file) java ...

sova-soars-the-sora19:01:29

you saved me a lot of headscratching

sova-soars-the-sora19:01:42

maybe 2 miles worth of headscratching if calculated by finger travel

😂 6
noisesmith19:01:53

you can also access the environment of other processes if you have permission

user=> (-> (slurp "/proc/self/environ") (s/replace (String. (byte-array [0])) "\n") println)

noisesmith19:01:13

("self" is the magic directory for the current pid, you can use an arbitrary pid there)

GGfpc19:01:08

How do you deal with async methods in repl based development? Let's say I have a method that returns immediately and calls a callback when done, I can't evaluate it in the repl because I won't be able to access what is passed to the callback

Daniel Stephens20:01:55

You could always setup a function (I've called mine spy) that is able to wrap any other function and logs inputs and outputs. No reason you couldn't also get it to reset! some atoms of input and output if it's not a nice readable results.

(defn spy [f]
  (fn [& args]
    (println "--------------------------")
    (println "calling callback" f "with:")
    (clojure.pprint/pprint args)
    (println "--------------------------")
    (let [o (apply f args)]
      (println "--------------------------")
      (println "callback" f "returned:")
      (clojure.pprint/pprint o)
      (println "--------------------------")
      o)))
=> #'user/spy

(defn async-method [millis callback-fn]
  (future 
    (Thread/sleep millis)
    (callback-fn millis)))
=> #'user/async-method

(defn callback [millis] (println "In callback after" millis))
=> #'user/callback

(async-method 1000 (spy callback))
=>
#object[clojure.core$future_call$reify__8439
        0x4f45e549
        {:status :pending, :val nil}]
--------------------------
calling callback #object[user$callback 0x4ac10f16 user$callback@4ac10f16] with:
(1000)
--------------------------
In callback after 1000
--------------------------
callback #object[user$callback 0x4ac10f16 user$callback@4ac10f16] returned:
nil
--------------------------

Daniel Stephens20:01:24

oops, just seen this is basically what was already suggested in another thread!

noisesmith19:01:59

@ggfpc12495 you can call def, or deliver to a promise, or swap! on an atom

noisesmith19:01:04

(cmd)user=> (def p (promise))
#'user/p
(ins)user=> (.start (Thread. (fn [] (Thread/sleep 10000) (deliver p 42))))
nil
(ins)user=> @p
42

noisesmith19:01:17

that ten second delay should be long enough to see the pause happen in a repl

noisesmith19:01:07

@ggfpc12495 if your app design is consistently async, core.async can help keep things a little simpler (but it also imposes a number of constraints)

GGfpc19:01:43

Your approach makes sense to me, but then are we not changing our code to fit a specific development process?

GGfpc19:01:00

I don't have much experience with Lisps but it feels weird coming from a Java world to do that

noisesmith19:01:26

java is full of bizarre "patterns" that shoehorn models into a dev process

noisesmith19:01:39

@ggfpc12495 on a slightly less glib note, clojure does tend to encourage a specific kind of design that makes repl usage easier, but in most cases this can be done in a way that is also decoupling concerns

noisesmith19:01:37

the real thing to avoid is coupling things because it makes dev simpler without regard for your domain (DI / factories etc. can do this as easily as decomposing for repl usage does)

noisesmith19:01:07

your adaptor might look like a function that takes a callback and returns a new one that also sets a promise, for example

GGfpc19:01:17

Thanks will look into your suggestions

noisesmith19:01:19

here's a minimal function which takes a promise and a callback, and creates a new cb that captures the value the callback sees

(ins)user=> (defn tracked-cb [p f] (fn [& args] (deliver p args) (apply f args)))
#'user/tracked-cb
(ins)user=> (defn printing-cb [x y] (println "callback:" x y))
#'user/printing-cb
(ins)user=> (def p (promise))
#'user/p
(ins)user=> (def cb (tracked-cb p printing-cb))
#'user/cb
(ins)user=> (.start (Thread. #(cb :a :b)))
nil
user=> callback: :a :b

(ins)user=> @p
(:a :b)
in general a lot of mocks / stubs / dependency injections can be replaced with regular functions

noisesmith19:01:43

a promise (as a let binding rather than a def most likely) can similarly be used in tests - dual benefit that the value isn't ready until the promise is delivered to so the test won't do its comparison until the async result is ready

roelof19:01:41

are there more free courses . I find this one also a lot about clojure and not much about components and so on

Sibelius Seraphini20:01:57

I’m trying to make log/info and log/debug to show in my terminal, but I’ve got this error: ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console... this is the code/project https://github.com/runopsio/sequence/blob/master/src/decimals/dynamodb.clj#L55

noisesmith20:01:51

java logging config is severely brittle and counterintuitive, the big picture answer is "you need to pick a logger, configure it, and ensure code you care about is hooked up to it", but the specifics are full of gotchas. The best answers will probably be java specific in presentation.

noisesmith20:01:51

the two stable outcomes I've seen are "magic .properties fill in resources that nobody touches" and "complex clojure.tools.logging code that nobody touches"

hiredman20:01:26

You need to look at the deps tree, but my guess is something is pulling in log4j2, and tools.logging is defaulting to using that, where it looks like the project is trying to use logback

Sibelius Seraphini20:01:51

is there a simple print or console.log (from js) but in clojure?

Sibelius Seraphini20:01:04

I just wanna introspect some variables to understand this code

hiredman20:01:36

There are many

hiredman20:01:52

prn or println are maybe the most common

hiredman20:01:08

*out* gives you access to a PrintWriter that writes to stdout by default, *err* to stderr

👍 3
Old account21:01:31

Hello, are records in use in the wild or maybe maps are more popular these days?

noisesmith21:01:34

there's a really good flowchart about this, but the tl;dr is that everything is designed so you can write code using maps, and convert to records / types / generated classes etc. when you know you need it

seancorfield21:01:27

It's worth noting that Clojure Applied talks up records fairly heavily but the author (Alex Miller) has said that if they do a 2nd Ed he would deemphasize records quite a bit and lean more heavily on plain hash maps.

blak3mill3r22:01:00

Records are in use in the wild, and maps are more popular, there are good reasons for both. Use maps, and switch to records when you have millions of maps with the same keys.