beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-01-10T06:35:13.269100Z

Discipline, good design, good test coverage, good variable names, documentation on functions and vars, always be using the REPL, that's mostly how

2021-01-10T06:36:20.269300Z

There's some refactoring support in editors, but I consider those "easy" refactors, harder ones where you change things in backward incompatible ways the editor won't do those for you πŸ˜›

popeye 2021-01-10T08:11:33.269900Z

(fn-name input-string [7 9 13] [25 26 29]) i am writing function where i am planning to apply substring of for each values of vactor example (sub input-string 7 25) (sub input-string 9 26) (sub input-string 13 29) How can I do it in clojure?

NPException 2021-01-10T08:43:24.270400Z

One way to do this would be to use map. It takes a mapping function and any number of collections. The mapping function needs to take as many parameters as there are collections passed to map .

NPException 2021-01-10T08:44:12.270600Z

The mapping function will then receive the first element of each collection as the its first set of arguments, then the second elements as the second set of arguments and so on.

NPException 2021-01-10T08:47:33.270900Z

So this

(map f [1 3] [2 4])
is roughly equivalent to
[(f 1 2)
 (f 3 4)]

NPException 2021-01-10T08:49:56.271200Z

Does this help you?

popeye 2021-01-10T08:50:23.271400Z

i will try on my code and let you know πŸ™‚

roelof 2021-01-10T10:26:24.272400Z

hmm, what did I not understood here :

; Use the list function, quoting, and read-string to create a list that, when 
; evaluated, prints your first name and your favorite sci-fi movie.

(list '(read-string str) "Roelof Wobben, Star Wars")

(eval  (list '(read-string str) "Roelof Wobben, Star Wars") )
error:
; Execution error (ClassCastException) at chapter7/eval16506 (form-init11571273748977578313.clj:9).
; class clojure.core$str cannot be cast to class java.lang.String (clojure.core$str is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')

roelof 2021-01-11T12:32:16.429200Z

now the most difficult ones

(defn defattrs [& functions]
  '(do .....))

(def c-int (comp :intelligence :attributes))
(def c-str (comp :strength :attributes))
(def c-dex (comp :dexterity :attributes))

(defattrs c-int :intelligence
  c-str :strength
  c-dex :dexterity)

NPException 2021-01-11T12:38:16.429400Z

I'm occupied with work atm, I'll probably be available in ~2 hours

roelof 2021-01-11T12:40:50.429800Z

Not a problem

roelof 2021-01-11T12:41:03.430Z

im just thinking how to proceed further

roelof 2021-01-11T12:41:31.430200Z

I never expect a quick answer. I expect a answer somewhere, sometime

NPException 2021-01-10T10:44:24.272500Z

'(read-string str) results in a list of the symbols read-string and str . When evaluated, it results in a function call to read-str with whatever is bound to str as its argument. So it's passing the function str into read-str .

roelof 2021-01-10T10:45:42.272700Z

oke, but this was also not right I think : (list '(read-string "my-text"))

NPException 2021-01-10T10:49:31.272900Z

The task is effectively to create a list of the symbol read-string and your text. (list '(read-string "my-text")) would result in the list: ((read-string "my-text")) , since you are quoting the list (read-string "my-text") already.

NPException 2021-01-10T10:49:48.273100Z

You only need to quote read-string .

NPException 2021-01-10T10:50:18.273300Z

So what it's asking for is this: (list 'read-string "my-text")

NPException 2021-01-10T10:51:15.273500Z

Getting used to quoting can take a while πŸ™‚

roelof 2021-01-10T10:52:29.273700Z

yep and figure out when something needs to be surrounded by parentheses also 😞

roelof 2021-01-10T10:55:54.274300Z

Am I right that only "Roelof" is printed here

(list 'read-string "Roelof Wobben, Star Wars")

(eval (list 'read-string "Roelof Wobben, Star Wars"))

NPException 2021-01-10T11:04:06.274500Z

oh, sorry I think I misunderstood the task a bit. So the list we now create is this: (read-string "Roelof Wobben, Star Wars") But read-string will only read the first form from a given string, which in this case will by the symbol Roelof . Is there a more detailed description to the task or any previous tasks that this one builds on top?

roelof 2021-01-10T11:05:39.274700Z

not that I know

roelof 2021-01-10T11:06:15.274900Z

but this is the page everything is explained : https://www.braveclojure.com/read-and-eval/

NPException 2021-01-10T11:07:34.275100Z

Ah, braveclojure! I learned the language from there about 3 years ago. πŸ™‚ Maybe I have my exercise code still lying around somewhere

roelof 2021-01-10T11:11:53.275300Z

I use it now for some 2 weeks to learn clojure but for every challenge I needed some help. Very frustating

NPException 2021-01-10T11:16:51.275500Z

Looking at the examples in that chapter, the exercise is just to get your familiar with those functions and concepts by combining them in some ways. One of my solutions was this:

(eval (read-string "(list 'Dirk 'Interstellar)"))

NPException 2021-01-10T11:19:22.275700Z

Don't beat yourself up if you don't get it right away. Especially all the macro related stuff can take some time. I also do remember that I found the second exercise in that chapter very tricky, so I skipped it at first and came back to it later.

roelof 2021-01-10T11:20:03.275900Z

yep, that prints out a list with the two data

roelof 2021-01-10T11:20:14.276100Z

yep, I know

roelof 2021-01-10T11:20:39.276300Z

I did try to make it and got the wrong answer

roelof 2021-01-10T11:21:30.276500Z

I thought this was equal (1Β +Β 3Β *Β 4Β -Β 5) and (-Β (*Β 4Β (+Β 1Β 3))Β 5) but it is not

roelof 2021-01-10T11:22:42.276700Z

and this one is given me the right output : (-Β (+Β (*Β 4Β 3)Β 1)Β 5)

roelof 2021-01-10T11:23:09.276900Z

so with the knowlegde that I have I never can make a general solution

NPException 2021-01-10T11:25:48.277100Z

(-Β (*Β 4Β (+Β 1Β 3))Β 5) does not equal (1 + 3 * 4 - 5) , * needs to take precedence over + .

roelof 2021-01-10T11:27:52.277300Z

yep, as I said I noticed

NPException 2021-01-10T11:28:30.277500Z

I can give you a link to my solution for the second exercise, if you want something to compare against.

roelof 2021-01-10T11:29:58.277700Z

Thanks, But first I will try it on my own

πŸ‘ 1
roelof 2021-01-10T11:30:31.277900Z

I think I have to start over again

roelof 2021-01-10T11:30:45.278200Z

make things to complicated

(defn infix [expr]
  (let [splitted (str/split (subs expr 1 (- (count expr) 1)) #" ")]
    ))

NPException 2021-01-10T11:31:10.278400Z

do you take the expression as a string?

NPException 2021-01-10T11:33:01.278600Z

try passing it as a list instead by just quoting it: (infix '(1Β +Β 3Β *Β 4Β -Β 5)) That way you can use all of Clojure's data manipulation functions directly.

roelof 2021-01-10T11:33:11.278800Z

yep, that was my idea and then split it on the space and delete the parentheses

roelof 2021-01-10T11:39:09.279Z

hmm, almost there I hope

(defn infix [expr]
   (let [first (first expr)
         second( nth expr 3)
         thirth (nth expr 5)
         fourth (nth expr 7)
         fifth (nth expr 9)
         sixth (nth expr 11)
         seventh (nth expr 13)]
     (list sixth(list second) )
     ))

(infix "(1 + 3 * 4 - 5)")
but that gives :
(\- (\+))

NPException 2021-01-10T11:45:03.279200Z

as expected. You are creating a list, consisting of the sixth element, and a nested list with the second element.

NPException 2021-01-10T11:45:33.279400Z

second element is + , sixth is -

roelof 2021-01-10T11:47:54.279600Z

I think I got it :

(defn infix [expr]
   (let [first (first expr)
         second( nth expr 3)
         thirth (nth expr 5)
         fourth (nth expr 7)
         fifth (nth expr 9)
         sixth (nth expr 11)
         seventh (nth expr 13)]
     (list (read-string (str sixth)) (list (read-string (str second)) 2 3)1)
     ))
this gives the right answer

roelof 2021-01-10T11:48:13.279800Z

I only have to adapt it to the whole formula

NPException 2021-01-10T11:48:55.280Z

are you still passing expr as a string?

roelof 2021-01-10T11:49:19.280200Z

yep (evalΒ (infixΒ "(1Β +Β 3Β *Β 4Β -Β 5)")Β )

NPException 2021-01-10T11:50:06.280400Z

do (evalΒ (infixΒ '(1Β +Β 3Β *Β 4Β -Β 5))) instead, then you can omit your read-string and str calls

NPException 2021-01-10T11:51:33.280600Z

you need to adjust your nth indices then, too.

roelof 2021-01-10T11:52:08.280800Z

yep, I see

roelof 2021-01-10T11:52:20.281Z

I know get a out of bounds error

NPException 2021-01-10T11:52:47.281200Z

I assume your indices are off by 1 now.

roelof 2021-01-10T11:53:33.281500Z

nope,

roelof 2021-01-10T11:53:42.281700Z

Still a out of bounds error

NPException 2021-01-10T11:53:47.281900Z

can you paste your current code ?

roelof 2021-01-10T11:53:49.282100Z

(defn infix [expr]
   (let [first (first expr)
         second( nth expr 2)
         thirth (nth expr 3)
         fourth (nth expr 4)
         fifth (nth expr 5)
         sixth (nth expr 6)
         seventh (nth expr 7)]
     (list (sixth  (list (second 2 3) )))))


(infix '(1 + 3 * 4 - 5))

NPException 2021-01-10T11:54:26.282300Z

off by 1. indices start at 0, so your second element will be at index 1 and so on.

roelof 2021-01-10T11:57:07.282500Z

still not well

(defn infix [expr]
   (let [first (first expr)
         second( nth expr 1)
         thirth (nth expr 2)
         fourth (nth expr 3)
         fifth (nth expr 4)
         sixth (nth expr 5)
         seventh (nth expr 6)]
     (list (sixth  (list (second 2 3) )))))



(eval (infix '(1 + 3 * 4 - 5)) )

roelof 2021-01-10T11:57:20.282700Z

; Syntax error (IllegalArgumentException) compiling at (chapter7.clj:28:1).
; Can't call nil, form: (nil)

NPException 2021-01-10T11:57:36.282900Z

which line is line 28?

roelof 2021-01-10T11:57:54.283100Z

the eval line

NPException 2021-01-10T12:03:12.283300Z

(list (sixth  (list (second 2 3) )))
That part needs fixing. sixth and second are now bound to the symbols - and + . Calling a symbol as function here will just return nil, so the list you return from infix ends up being (nil) , which when eval'd results in that error.

NPException 2021-01-10T12:05:23.283500Z

You want to construct lists with those symbols as the first element instead, so don't nest them in a function call

(list sixth (list second 2 3))

roelof 2021-01-10T12:18:46.283800Z

Thanks,

roelof 2021-01-10T12:18:57.284Z

This works :

(defn infix [expr]
  (let [first (first expr)
        second (nth expr 1)
        thirth (nth expr 2)
        fourth (nth expr 3)
        fifth (nth expr 4)
        sixth (nth expr 5)
        seventh (nth expr 6)]
    (list sixth (list second (list fourth thirth fifth) first) seventh)))

NPException 2021-01-10T12:19:49.284200Z

congrats!

NPException 2021-01-10T12:21:28.284400Z

Now next step would be to make it work for other formulas, like (3 * 2 - 1) and others

roelof 2021-01-10T12:22:05.284600Z

I do not know if I can make that work

roelof 2021-01-10T12:22:20.284800Z

then you have to make something that looks for a order

NPException 2021-01-10T12:26:57.285Z

yes. I made a function which takes two operators, and returns true if the first one takes precedence over the second. To determine that, I put priority values in a map (one for each of the basic operators + - * / ) and then looked up the values for both operators in the map. If the value for the first operator is higher than the second, I returned true.

NPException 2021-01-10T12:27:54.285200Z

This was my priority map, just to give you an idea: (def priorities {'+ 1, '- 1, '* 2, '/ 2})

NPException 2021-01-10T12:33:04.285400Z

To make your life easier, you can try to implement your infix function only for lists of exactly 5 elements first. (e.g (infix '(a op1 b op2 c)) ) That way you only have to worry about 2 operators for now.

popeye 2021-01-10T13:16:09.285700Z

I tried with map and that helped πŸ™‚ sorru for late reply, wanted to complete the functionality

roelof 2021-01-10T13:43:32.285900Z

this is I think a nice lesson

roelof 2021-01-10T13:44:53.286100Z

may I choose what op1 and op2 are

roelof 2021-01-10T13:47:09.286300Z

and maybe use a regex to split it into pieces ?/

roelof 2021-01-10T13:56:01.286900Z

(defn infix2 [expr]
  (let [splitted (re-matches #"((d+) (.) (d+) (.) (d+))" expr)]
    splitted))



(infix2 '(10 + 2 * 3))
error:
; Execution error (ClassCastException) at chapter7/infix2 (form-init6806598393956264445.clj:29).
; class clojure.lang.PersistentList cannot be cast to class java.lang.CharSequence (clojure.lang.PersistentList is in unnamed module of loader 'app'; java.lang.CharSequence is in module java.base of loader 'bootstrap')

NPException 2021-01-10T14:23:47.287100Z

you are trying to use strings again

NPException 2021-01-10T14:24:48.287300Z

keep in mind that expr is just a list of alternating values and operators.

NPException 2021-01-10T14:25:23.287500Z

so no. regex bad. (in this case at least πŸ˜„)

NPException 2021-01-10T14:25:56.287700Z

Also I'd like to point you at a section in a previous chapter: https://www.braveclojure.com/do-things/#Destructuring

NPException 2021-01-10T14:27:07.287900Z

you can destructure your expr in the parameter list of the function for easy access to the elements of it.

roelof 2021-01-10T14:43:10.288100Z

yep, I can do that , I did that in my former solution But it is then not a problem when there are more or less parameters

roelof 2021-01-10T14:43:48.288300Z

I mean I can do this again :

(let [first (first expr)
        second (nth expr 1)
        thirth (nth expr 2)
        fourth (nth expr 3)
        fifth (nth expr 4)

roelof 2021-01-10T14:44:25.288500Z

but what if I do (+ 1 2) or (1+2+3+4+5+6)

roelof 2021-01-10T14:44:48.288700Z

then this destructering does not work

Chase 2021-01-10T14:53:38.289200Z

A test in this exercism problem wants this: (is (thrown? IllegalArgumentException (nth-prime/nth-prime 0))) and so far my code has this: (if (< n 1) (throw (IllegalArgumentException.)) which seems to do what I want but the test results tell me: Exception in thread main, syntax error caused by ... java.lang.IllegalArgumentException. tests failed

NPException 2021-01-10T15:08:00.289400Z

It does work, but we can get to it after we made your approach work. πŸ™‚

roelof 2021-01-10T15:09:22.289600Z

oke

roelof 2021-01-10T15:09:57.289800Z

so I can start with this :

(defn infix [expr]
  (let [first (first expr)
        second (nth expr 1)
        thirth (nth expr 2)
        fourth (nth expr 3)
        fifth (nth expr 4)
        sixth (nth expr 5)
        seventh (nth expr 6)]

roelof 2021-01-10T15:10:19.290Z

and I know that 2 4 6 are the operators

roelof 2021-01-10T15:10:25.290200Z

the rest I do not see

NPException 2021-01-10T15:11:01.290400Z

Yes, but you need to adjust it. The minimum case for the infix is an expression of 3 elements. For example (1 + 3) . This means that you can't use nth for anything after the third element, since if there is no fourth, it will error with an IndexOutOfBounds.

roelof 2021-01-10T15:11:49.290600Z

oke, im curious which way this is going to

NPException 2021-01-10T15:13:24.290800Z

So how can you remove the first 3 elements from expr to get a (potentially empty) list of all remaining elements?

NPException 2021-01-10T15:14:46.291Z

If you have a list of remaining elements, you can check if it is empty. If it is, you have the base case and can just return a list of the second, first, and third element.

roelof 2021-01-10T15:15:04.291200Z

(drop 3 expr)

NPException 2021-01-10T15:15:16.291400Z

πŸ‘

roelof 2021-01-10T15:16:06.291600Z

oke

roelof 2021-01-10T15:16:22.291800Z

we have then this :

(defn infix2 [expr]
  (let [first (first expr)
        second (nth expr 1)
        thirth (nth expr 2)
        r (drop 3 expr)]
  ))

roelof 2021-01-10T15:16:32.292Z

so then a check if r is empty ?

NPException 2021-01-10T15:16:59.292200Z

yeah

roelof 2021-01-10T15:18:22.292400Z

oke we know then that second is the parameter and one and three the numbers

NPException 2021-01-10T15:18:30.292600Z

at this point I would suggest to use other names than first and second , because you are hiding the respective clojure core functions by doing that.

roelof 2021-01-10T15:18:49.292800Z

so we can do (list second first thirth)

NPException 2021-01-10T15:18:55.293Z

yes

roelof 2021-01-10T15:19:11.293200Z

oke , any recoomendations then for a better name ?

practicalli-john 2021-01-10T15:19:57.294Z

@chase-lambert try or instead of if

roelof 2021-01-10T15:20:43.294300Z

maybe a op1 b ?

NPException 2021-01-10T15:22:17.294500Z

Yeah. That's what I ended up using too. You can also be more explicit, like first-number, operator , second-number . It's totally up to you in the end, it just should be easy to read and understand when you come back to the code later.

Chase 2021-01-10T15:23:00.295400Z

hmm, but my else branch of the if is what solves the actual problem. I tried using a :pre condition but that didn't pass the test either.

roelof 2021-01-10T15:24:03.295500Z

oke, we have this :

(defn infix2 [expr]
  (let [first-number (first expr)
        operator (nth expr 1)
        second-number (nth expr 2)
        r (drop 3 expr)]
    (if (empty? r))
      (list operator first-number second-number)
      
    ))

roelof 2021-01-10T15:24:41.295700Z

for the second case we need the priorites variable

roelof 2021-01-10T15:24:44.295900Z

I think

NPException 2021-01-10T15:24:50.296100Z

correct

roelof 2021-01-10T15:25:15.296300Z

there I have to think well

roelof 2021-01-10T15:25:41.296500Z

Right now we do not know the second operator

roelof 2021-01-10T15:25:52.296700Z

so we cannot compare anything

NPException 2021-01-10T15:26:03.296900Z

if r is not empty, where will the second operator be?

roelof 2021-01-10T15:26:18.297100Z

in r

NPException 2021-01-10T15:26:38.297300Z

more precisely it will be the first element of r.

roelof 2021-01-10T15:27:20.297500Z

yep, you are right

NPException 2021-01-10T15:27:46.297700Z

Also I just noticed your if does not surround the (list .. below it

roelof 2021-01-10T15:28:06.297900Z

oke, then now I have to figure out how I can find the priorities

roelof 2021-01-10T15:28:47.298100Z

changed

roelof 2021-01-10T15:29:07.298300Z

BRB

NPException 2021-01-10T15:32:15.298600Z

you have some options to lookup the priorities, where these 2 would be the most commonly used: Call get with the priorities map and an operator or use the priorities map itself as the lookup function.

NPException 2021-01-10T15:33:38.299300Z

If I'm giving you too many directions at any point, let me know. I don't want to ruin the learning experience by just pushing a solution onto you πŸ˜…

Chase 2021-01-10T15:34:02.299900Z

huh, now that I've actually instituted the else branch (I was just returning n while seeing if my exception logic worked) all tests pass. Sorry for wasting your time @jr0cket

roelof 2021-01-10T15:53:16.300Z

I will say i to you iof you help me too much

roelof 2021-01-10T15:55:59.300200Z

oke

roelof 2021-01-10T15:56:09.300400Z

so like this :

(defn infix2 [expr]
  (let [first-number (first expr)
        operator (nth expr 1)
        second-number (nth expr 2)
        r (drop 3 expr)]
    (if (empty? r)
      (list operator first-number second-number)
      (if ( < (get priorities operator) (get priorities (first r)))
          "do something"
          "do something else"
        
        
        ))))

NPException 2021-01-10T15:56:22.300600Z

exactly

roelof 2021-01-10T15:57:00.300800Z

now I think I need to work on paper what schould happen now

roelof 2021-01-10T15:57:09.301Z

so I need some moments I think

βœ”οΈ 1
roelof 2021-01-10T16:00:30.301300Z

he, im i righht here 1 + 2 * 3 will be in clojure (+ ( * 2 3) 1) and 2 * 3 + 1 will also be (+ ( * 2 3) 1) `

roelof 2021-01-10T16:00:43.301500Z

so it does not matter

roelof 2021-01-10T16:02:36.301700Z

hmm, im still thinkimg I need to join the second-number back to r when r is not empty

NPException 2021-01-10T16:03:04.301900Z

partially correct. only if the second operator has a higher priority

roelof 2021-01-10T16:03:23.302100Z

hmm, Im stuck

roelof 2021-01-10T16:05:23.302400Z

in the first case I would do something like (list operator(list (infix2 r second) first-number)

roelof 2021-01-10T16:05:52.302600Z

but that would not work because then the first-number will be the operator and that is not good

NPException 2021-01-10T16:07:38.302800Z

let's first deal with the (in my opinion) easier case, which is the second case.

roelof 2021-01-10T16:07:46.303Z

oke

NPException 2021-01-10T16:07:49.303200Z

How would you do that?

roelof 2021-01-10T16:08:54.303400Z

(infix2 r (operator first-number second-number) `

roelof 2021-01-10T16:09:22.303600Z

but that cannot be good because infix2 wants only 1 argument and now there are 2

roelof 2021-01-10T16:10:05.303800Z

or I can do (infix2 (list r (operator first-number second-number)

NPException 2021-01-10T16:11:34.304Z

not quite. You need to prepend (operator first-number second-number) to r , and pass that into infix2

NPException 2021-01-10T16:12:00.304200Z

sorry I mean (list operator first-number second-number)

roelof 2021-01-10T16:14:01.304400Z

oke , so (infix2 (conj r (list operator first-number second-number)) ?

NPException 2021-01-10T16:15:07.304700Z

yeah, that should do it

roelof 2021-01-10T16:16:25.304900Z

now the second one

roelof 2021-01-10T16:17:38.305100Z

we need something like (list operator(list (infix2 r) second-number) first-number)` ?

roelof 2021-01-10T16:18:01.305300Z

because we do not have the operator and the other number

NPException 2021-01-10T16:18:36.305500Z

let's break it up. What would the nested call to infix2 look like?

roelof 2021-01-10T16:20:57.305700Z

im still thinking (infix r second-number)

roelof 2021-01-10T16:21:30.305900Z

bcause r has the operator and the number we are missing

NPException 2021-01-10T16:21:57.306100Z

yes, but infix2 only takes one argument, so you need to prepend second-number to r

roelof 2021-01-10T16:22:44.306400Z

oke so (index (conj r second-number))

NPException 2021-01-10T16:23:13.306600Z

infix2 instead of index, but yeah πŸ˜„

roelof 2021-01-10T16:23:23.306800Z

sorry

roelof 2021-01-10T16:23:40.307Z

I want to type faster then i can

NPException 2021-01-10T16:24:15.307200Z

brb

roelof 2021-01-10T16:25:19.307400Z

so the call will be (list operatotor (list (infix2 (conj r second-number))) first-number)

roelof 2021-01-10T16:25:40.307600Z

I hope I did not miss any parentheses

roelof 2021-01-10T16:33:39.307900Z

something not right with parentheses here :

(infix2 '(10 + 2 * 3))

(+ ((* 2 3)) 10)

roelof 2021-01-10T16:35:26.308200Z

code so far :

(defn infix2 [expr]
  (let [first-number (first expr)
        operator (nth expr 1)
        second-number (nth expr 2)
        r (drop 3 expr)]
    (if (empty? r)
      (list operator first-number second-number)
      (if (< (get priorities operator) (get priorities (first r)))
        (list operator (list (infix2 (conj r second-number))) first-number)
        (infix2 (conj r (list operator first-number second-number)))))))

NPException 2021-01-10T16:39:30.308400Z

there are 2 issues here

(list operator (list (infix2 (conj r second-number))) first-number)

NPException 2021-01-10T16:40:13.308600Z

1. you don't need to put the nested infix2 in another list

roelof 2021-01-10T16:41:39.308800Z

thanks, this seems to work

(defn infix2 [expr]
  (let [first-number (first expr)
        operator (nth expr 1)
        second-number (nth expr 2)
        r (drop 3 expr)]
    (if (empty? r)
      (list operator first-number second-number)
      (if (< (get priorities operator) (get priorities (first r)))
        (list operator (infix2 (conj r second-number)) first-number)
        (infix2 (conj r (list operator first-number second-number)))))))

roelof 2021-01-10T16:42:11.309Z

(infix2 '(10 + 2 * 3))  gives  (+ (* 2 3) 10)

πŸ™Œ 1
NPException 2021-01-10T16:42:23.309200Z

2. first-number should come after operator, not as the last element (it doesn't make a functional difference here, but it would if you want to expand the functionality to work with nested infix expressions like (3 * (1 + 2)))

roelof 2021-01-10T16:42:44.309500Z

(infix2Β '(2Β *Β 3Β +Β 10)) gives also (+Β (*Β 2Β 3)Β 10)

NPException 2021-01-10T16:43:07.309700Z

well done!

roelof 2021-01-10T16:44:14.309900Z

pff, still have the feeling that I have to learn a lot how to approach this sort of problems

roelof 2021-01-10T16:44:28.310100Z

and thanks for the patience with me for the whole day

NPException 2021-01-10T16:44:33.310300Z

That comes with time and practice

NPException 2021-01-10T16:44:59.310500Z

ah, no worries, I was only playing games on my main monitor most of the time πŸ˜„

NPException 2021-01-10T16:45:23.310700Z

I would like to quickly go back to the topic of destructuring if you have a few more minutes

roelof 2021-01-10T16:46:19.310900Z

hmm, one thing im still not happy

NPException 2021-01-10T16:46:33.311100Z

sure, what's it?

roelof 2021-01-10T16:46:58.311300Z

(infix2Β '(10Β +Β 2Β *Β 3)) gives (+Β 10Β (*Β 2Β 3))

NPException 2021-01-10T16:47:26.311500Z

which is correct

roelof 2021-01-10T16:47:31.311700Z

where (infix2Β '(2Β *Β 3Β +Β 10)) gives (+Β (*Β 2Β 3)Β 10)

NPException 2021-01-10T16:47:41.311900Z

which is also correct

roelof 2021-01-10T16:47:50.312100Z

why on the second one is the 10 in the last position

roelof 2021-01-10T16:48:03.312300Z

can we not look both the same

roelof 2021-01-10T16:48:11.312500Z

or am I overthinking ?

NPException 2021-01-10T16:50:02.312700Z

if you imagine replacing 2 * 3 with 6 ->

(10 + 6) -> (+ 10 6)
(6 + 10) -> (+ 6 10)

NPException 2021-01-10T16:51:14.312900Z

it's just keeping the order of arguments like they were in the original expression. Which is expected in my opinion.

NPException 2021-01-10T16:51:41.313100Z

You don't want it to accidentally re-order the arguments to a division or subtraction.

NPException 2021-01-10T16:52:37.313300Z

Now that I think about it, that is the actual important reason for the 2) issue I mentioned earlier. :thinking_face:

roelof 2021-01-10T16:59:37.313500Z

oke

roelof 2021-01-10T17:01:48.313700Z

and never knew that recursion could solve so many problems

NPException 2021-01-10T17:02:49.313900Z

yeah, I never used it much when I was working with Java, but now I use it quite regularly

roelof 2021-01-10T17:03:21.314100Z

oke, I know ik from haskelll where it is also used very often

roelof 2021-01-10T17:03:30.314300Z

java I do not have learned

roelof 2021-01-10T17:05:16.314500Z

pnl;y some haskell., some c# and some ruby

roelof 2021-01-10T17:07:00.314700Z

and for practice I do now the brave book and exercism

roelof 2021-01-10T17:07:23.314900Z

later on maybe 4 clojure and maybemuch later Advent of Code

NPException 2021-01-10T17:07:31.315100Z

That's more than I know. I only know Java and Clojure πŸ˜… So quickly back to destructuring: The infix function breaks expr into 4 parts: the first three elements and the rest after those. Which can be done with destructuring quite easily:

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator first-number second-number)
    (if (< (get priorities operator) (get priorities (first r)))
      (list operator first-number (infix2 (conj r second-number)))
      (infix2 (conj r (list operator first-number second-number))))))

roelof 2021-01-10T17:08:38.315300Z

oke and it still then works ?

roelof 2021-01-10T17:08:49.315500Z

I thougth I need a let to deconstruct

NPException 2021-01-10T17:09:33.315700Z

I thought that as well at first, but destructuring works in quite a few places

roelof 2021-01-10T17:09:34.315900Z

yep, it does

roelof 2021-01-10T17:10:13.316100Z

learned another "trick"

NPException 2021-01-10T17:10:28.316300Z

want a small extra challenge? πŸ˜„

roelof 2021-01-10T17:11:03.316500Z

always. as lomg as I can do it with the knowlegde I get from the book

roelof 2021-01-10T17:11:21.316700Z

I only do not know if I got it working today

roelof 2021-01-10T17:11:29.316900Z

almost dinner/supper here

NPException 2021-01-10T17:13:45.317100Z

I think that should be doable. The challenge would be to make your infix function work with arbitrarily nested expressions. Example

(infix2 '(3 * (2 + (5 - 3) / 2)))
=> (* 3 (+ 2 (/ (- 5 3) 2)))

NPException 2021-01-10T17:14:24.317300Z

there is only one spot that needs to be changed

NPException 2021-01-10T17:15:05.317500Z

In case the book did not mention it yet: To check if something is a list, you call (list? the-thing)

roelof 2021-01-10T17:17:55.317800Z

oke, from the c# time I learned on OOP its not good to ask a object what it is

NPException 2021-01-10T17:19:37.318Z

makes sense in OOP, since you rather use methods and inheritance there. But since we are just juggling data around here, we need to be able to check what kind of data we're dealing with.

roelof 2021-01-10T17:19:46.318200Z

i know

roelof 2021-01-10T17:20:00.318400Z

just thinking how to to solve this

roelof 2021-01-10T17:21:13.318600Z

I see what needs to be changed

; (* 3 (+ 2 (/ (- 5 3) 2))) => current outcome
; (* 3 (2 + (5 - 3) / 2))   => preffered outcome 

roelof 2021-01-10T17:24:14.318800Z

thinkingg I might need another if then to solve this

NPException 2021-01-10T17:25:09.319Z

technically correct, but maybe not in the way you think right now. Where would you put that if and what would it check for?

roelof 2021-01-10T17:27:29.319200Z

I was thinking just before the if then we have now and it would do a check if first number is a list

NPException 2021-01-10T17:28:54.319400Z

why do you want to check it there?

roelof 2021-01-10T17:30:39.319600Z

just a feeling what is the right place

NPException 2021-01-10T17:31:04.319800Z

now what would you do if the first argument is a list and not a number?

roelof 2021-01-10T17:31:19.320Z

because It think both cases which we have now could hit this problem

roelof 2021-01-10T17:31:39.320200Z

then we have a parse that again somehow

roelof 2021-01-10T17:32:25.320400Z

What we are making is a parser as far as I see it

NPException 2021-01-10T17:33:04.320600Z

not really

roelof 2021-01-10T17:34:23.320800Z

am I on the right track or not ?

NPException 2021-01-10T17:34:31.321Z

if an argument is a list, (so a nested expression) we want to turn it into its infix representation.

NPException 2021-01-10T17:38:54.321200Z

there's only one place in the function where all arguments are ultimately put into an infix format. At that place, you either put in the argument itself or the infix version of it if it's a list.

roelof 2021-01-10T17:43:39.321400Z

I think you mean like here : (listΒ operatorΒ first-numberΒ second-number)

roelof 2021-01-10T17:44:06.321600Z

be back after supper/dinner

roelof 2021-01-10T17:44:17.321800Z

I still miss something I think

roelof 2021-01-10T17:44:32.322Z

you want a if then into that part ?

NPException 2021-01-10T17:58:00.322300Z

yep exactly. one for each first-number and second-number

roelof 2021-01-10T17:59:28.322500Z

oke

roelof 2021-01-10T18:01:11.322700Z

so like this :

(list operator (if (list? first-number) ....) (if (list? second-number) ....)

roelof 2021-01-10T18:01:13.322900Z

??

NPException 2021-01-10T18:01:25.323100Z

yup

roelof 2021-01-10T18:01:45.323300Z

oke, then I have to think how to proceed then

roelof 2021-01-10T18:15:18.323500Z

chips, I does not know about match

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator (match [(list? first-number) (list? second-number)]
                     [true false] "do something"
                     [false true] "do something else"
                     [true true]  "do another something"))
    (if (< (get priorities operator) (get priorities (first r)))
      (list operator first-number (infix2 (conj r second-number)))
      (infix2 (conj r (list operator first-number second-number))))))

roelof 2021-01-10T18:15:37.323700Z

and this is not going to solve it

(ns chapter7
  (:require [clojure.core.match :refer [match]]))

NPException 2021-01-10T18:15:57.323900Z

you are thinking to complicated πŸ™‚

roelof 2021-01-10T18:16:20.324100Z

😒

NPException 2021-01-10T18:16:25.324300Z

match is a cool thing, but definitely not needed here

NPException 2021-01-10T18:17:36.324500Z

let's rename first-number to a and second-number to b for now, makes it easier to write about πŸ˜„

roelof 2021-01-10T18:18:11.324700Z

hmm

roelof 2021-01-10T18:18:23.324900Z

I had this :

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator (if (list? first-number) 
                     (list operator (infix2 firstnumber) second-number)         
                     ) 
          (if (list? second-number) 
            (list operator firstnumber (infix2 second-number))   
            )
    (if (< (get priorities operator) (get priorities (first r)))
      (list operator first-number (infix2 (conj r second-number)))
      (infix2 (conj r (list operator first-number second-number)))))))

roelof 2021-01-10T18:18:35.325100Z

but then I need on both cases a else branch

roelof 2021-01-10T18:21:26.325300Z

and witth this I get a null pointer exception

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator (if (list? first-number) 
                     (list operator (infix2 first-number) second-number)
                      (if (list? second-number)
                        (list operator first-number (infix2 second-number))
                        (list operator first-number second-number)
                        )         
                     ) 
   (if (< (get priorities operator) (get priorities (first r)))
      (list operator first-number (infix2 (conj r second-number)))
      (infix2 (conj r (list operator first-number second-number)))))))

NPException 2021-01-10T18:21:40.325500Z

you are already within (list operator ... , you don't need to call that again in the nested ifs. The nested ifs should only return either the number or the infixed nested list.

NPException 2021-01-10T18:23:29.325700Z

keep in mind that everything is an expression. Those nested ifs do not directly return from your infix2 function.

roelof 2021-01-10T18:24:56.325900Z

oke

roelof 2021-01-10T18:25:45.326100Z

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator (if (list? first-number)
                     (infix2 first-number)
                     (if (list? second-number)
                       (infix2 second-number)
                       (first-number second-number))))
          (if (< (get priorities operator) (get priorities (first r)))
            (list operator first-number (infix2 (conj r second-number)))
            (infix2 (conj r (list operator first-number second-number))))))

roelof 2021-01-10T18:25:59.326300Z

; Execution error (ClassCastException) at chapter7/infix2 (form-init6806598393956264445.clj:34).
; class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')

NPException 2021-01-10T18:26:24.326500Z

you also shouldn't nest the (if (list? second-number) in the check for the first one

NPException 2021-01-10T18:26:41.326700Z

instead:

(list operator
      (if (list? first-number)
        (infix2 first-number)
        )
      (if (list? second-number)
        (infix2 second-number)
        ))

roelof 2021-01-10T18:27:03.326900Z

so no else on the first if then

NPException 2021-01-10T18:27:09.327100Z

both ifs are independent of each other.

roelof 2021-01-10T18:27:11.327300Z

I thought that was needed

NPException 2021-01-10T18:27:16.327500Z

There is an else needed for both of them

NPException 2021-01-10T18:27:38.327700Z

I just don't want to give it to you straight away πŸ™‚

roelof 2021-01-10T18:27:52.327900Z

and im nowvery confused

roelof 2021-01-10T18:28:25.328100Z

if first-number is not a list then we cannot know if second-number is a list of not

roelof 2021-01-10T18:28:44.328300Z

so what schould then be in the else of that one ?

NPException 2021-01-10T18:29:06.328500Z

first-number and second-number can be lists or numbers completely independent of each other

NPException 2021-01-10T18:29:31.328700Z

(1 + 2) ((1 * 3) + 2) (1 + (5 *2))

NPException 2021-01-10T18:30:02.328900Z

in all those cases operator is the + , and first-number and second-number can be anything

NPException 2021-01-10T18:30:53.329100Z

if an argument is not a list, it's a number. If it's a number we don't need to do anything with it, so we can just return it.

roelof 2021-01-10T18:31:30.329300Z

or we must do something like this :

(defn infix2 [[first-number operator second-number & r]]
  (if (empty? r)
    (list operator
          (if (list? first-number)
            (infix2 first-number)
            first-number)
          (if (list? second-number)
            (infix2 second-number)
            second-number
            ))
    (if (< (get priorities operator) (get priorities (first r)))
      (list operator first-number (infix2 (conj r second-number)))
      (infix2 (conj r (list operator first-number second-number))))))

NPException 2021-01-10T18:32:15.329500Z

exactly :thumbsup:

roelof 2021-01-10T18:32:47.329700Z

so this is right

roelof 2021-01-10T18:32:51.329900Z

(* 3 (+ 2 (/ (- 5 3) 2)))

NPException 2021-01-10T18:33:00.330100Z

yes πŸ™‚

roelof 2021-01-10T18:33:06.330300Z

πŸŽ‰

roelof 2021-01-10T18:33:30.330500Z

lesson learned from today. Make problems even smalller then I do now

NPException 2021-01-10T18:34:40.330700Z

That's always the hardest part in my opinion. Breaking down the problem into the smallest pieces that can be individually solved.

roelof 2021-01-10T18:34:53.330900Z

yep

roelof 2021-01-10T18:35:07.331100Z

I still have to learn that on my "old" age

NPException 2021-01-10T18:35:32.331300Z

How old are you if I may ask?

roelof 2021-01-10T18:35:47.331500Z

53 and on the 21 I will be 54

NPException 2021-01-10T18:36:48.331700Z

A rare occasion where I don't feel old with my 34 then. πŸ˜„

roelof 2021-01-10T18:36:50.331900Z

I think I deserve a break and maybe tomorrow or later the chapter about writing macros

roelof 2021-01-10T18:37:34.332100Z

I hope this month I will finish the brave book and hopefully not feeling like a super beginner

roelof 2021-01-10T18:37:57.332300Z

and in the far future learn web development with clojure if I then still like it

roelof 2021-01-10T18:38:19.332500Z

again many thanks for the patience with a super beginner like me

NPException 2021-01-10T18:39:14.332700Z

Feel free to contact me directly anytime if you have any questions or need help again.

NPException 2021-01-10T18:40:30.332900Z

Also huge respect for your patience with that stuff. I think I took multiple breaks during those sections in the book.

roelof 2021-01-10T18:41:40.333100Z

o, this is I think the 5th or 6th time I try

roelof 2021-01-10T18:42:09.333300Z

and maybe I quit at chapter about functional programming

roelof 2021-01-10T18:42:45.333500Z

and I were several times on a point I would quit but because of persons like you I see and learn things

roelof 2021-01-10T18:43:16.333700Z

brave book is I think not the best learning book but it one of the best free ones

NPException 2021-01-10T18:44:58.333900Z

It's the only beginner clojure book I have read, so I can't really tell how good it is compared to others. But it is the one that ultimately got me to work with Clojure fulltime, so it can't be too bad πŸ˜„

NPException 2021-01-10T18:48:16.334100Z

There is currently a beginner meetup going on where participants read through the brave book, and then talk about it in occasional meetings to compare their exercise solutions and what they learned. Would this be something you'd be interested in?

roelof 2021-01-10T18:48:32.334300Z

could be

roelof 2021-01-10T18:48:42.334500Z

if I can fit into my schedule

NPException 2021-01-10T18:48:55.334700Z

if you are on Twitter: https://twitter.com/asamonek/status/1344913238933315585

roelof 2021-01-10T18:49:05.335Z

here is a lock-down so I have to play teacher for my daugther

NPException 2021-01-10T18:49:40.335300Z

same here, though I only have my cats to feed in between their sleep schedule

roelof 2021-01-10T18:50:32.335500Z

lucky you

roelof 2021-01-10T18:50:45.335700Z

for me clojure is hobby to train my brain

roelof 2021-01-10T18:51:05.335900Z

no idea if there are clojure jobs in the Netherlands

roelof 2021-01-10T18:51:33.336100Z

my special need daugther is more important then a well payed job

NPException 2021-01-10T18:53:39.336300Z

So you can probably just ask @asamonek here or on Twitter if you can join. Next meeting would be on 20.01. at 17:00 GMT+1. Topic for that meeting will be Chapter 3 of the book, so you are already ahead of the pack. πŸ™‚

NPException 2021-01-10T18:55:14.336500Z

> my special need daugther is more important then a well payed job Very true. Fortunately 2020 made it clear to pretty much every company that software developers can work from home. I worked from home with Clojure for a British company for the past 2 years.

roelof 2021-01-10T18:59:15.336700Z

I have done that

roelof 2021-01-10T18:59:33.336900Z

oke

roelof 2021-01-10T18:59:47.337100Z

we see what the future wil bring

roelof 2021-01-10T19:00:20.337300Z

my wife works now from March 2020 at home and she is not happy with it

roelof 2021-01-10T19:00:57.337500Z

She misses her collegues (i think I wrote it wrong, so I hope you understand

NPException 2021-01-10T19:03:39.337700Z

yeah understandable. Working from home is definitely less social than in office.

roelof 2021-01-10T19:04:11.337900Z

are you doing web or other things were you use clojure

NPException 2021-01-10T19:07:43.338100Z

backend for a website. Frontend was regular HTML+JS, but I didn't have to work on that.

NPException 2021-01-10T19:09:14.338300Z

so everything between incoming requests and the database.

NPException 2021-01-10T19:10:31.338500Z

and some smaller services around it, like for sending emails and notifications

roelof 2021-01-10T19:35:20.338700Z

oke, when Im that far I like to write back-end for a gallery where the data is coming from the rijksmuseum api and a second project is a sort of crm for a volunteer organisation

roelof 2021-01-10T19:35:54.338900Z

to keep track of payments, who has a subcription and if the subscriptions are payed or not

roelof 2021-01-10T19:36:02.339100Z

but that will be later in the year

roelof 2021-01-10T19:36:39.339300Z

first getting better in clojure and then look what I can use to make the two ideas work

roelof 2021-01-10T19:41:36.339500Z

tomorrow study this page : https://www.braveclojure.com/writing-macros/#Exercises

roelof 2021-01-10T19:41:48.339700Z

and I wil see if I also can make some challenges

roelof 2021-01-10T19:41:55.339900Z

no hurry

NPException 2021-01-10T19:48:01.340100Z

> I like to write back-end for a gallery where the data is coming from the rijksmuseum api and a second project is a sort of crm for a volunteer organisation sounds like great projects! I'd love to see them in action some day πŸ™‚

roelof 2021-01-10T19:48:27.340300Z

who knows

roelof 2021-01-10T19:49:00.340500Z

looked at the challenges of the writing macros and I hope I can solve them. right now I doubt it

roelof 2021-01-10T19:49:13.340700Z

but it is almost time to lseep

NPException 2021-01-10T19:50:44.340900Z

for me too. I'll be around in slack tomorrow again. see you πŸ‘‹

Christian 2021-01-10T20:00:47.343200Z

I have to supply a lot of functions that all do the same thing and was wondering how to make one function instead of a lot. Here is an example:

(defn count-a [s] (my-counter "a" s))
(defn count-b [s] (my-counter "b" s))
(defn count-c [s] (my-counter "c" s))
....
Is it possible to replace this somehow? Like having a function that can generate function names and if a user would call count-ß it would be replied with the correct function?

NPException 2021-01-10T20:03:14.344100Z

Why not call (my-counter "XYZ" s) directly?

βž• 1
roelof 2021-01-10T20:03:46.344300Z

see you

Christian 2021-01-10T20:05:35.344900Z

Because the tests want the functions to be there.

Christian 2021-01-10T20:05:51.345300Z

I think this might be my solution: https://stackoverflow.com/a/7854594/4919081 but I don't understand it

roelof 2021-01-10T20:08:20.345700Z

what do you then use for back-end writimng duct, pedestral or something else ?

NPException 2021-01-10T20:10:49.348200Z

So you would like to be able to do something like this?

(defcount "a")
;; now a function with the name count-a exists

Christian 2021-01-10T20:14:42.350100Z

yes!

alexmiller 2021-01-10T20:14:47.350200Z

(defmacro defcount [x]
  `(defn ~(symbol (str "count-" x)) [s#] (my-counter ~x s#)))

(pprint (macroexpand-1 '(defcount "a")))

(clojure.core/defn
 count-a
 [s__155__auto__]
 (user/my-counter "a" s__155__auto__))

πŸ‘€ 1
βž• 1
alexmiller 2021-01-10T20:16:49.351Z

of course, if you're going to write a macro to make one function, you might want it to make many too

Christian 2021-01-10T20:17:19.351500Z

Right, thats why the solution from the link with the doseq looks interesting

alexmiller 2021-01-10T20:17:33.351800Z

yeah, it's just wrapping a doseq around the body basically

NPException 2021-01-10T20:22:49.351900Z

we use a whole bunch of individual Clojure and Java libraries, not a prepackaged framework. I don't remember many of the libraries though, I don't have access to the code to check atm. The ones I remember are β€’ compojure β€’ ring and various middleware β€’ component β€’ jsonista β€’ clojure.java.jdbc β€’ clj-time

Christian 2021-01-10T20:29:03.353200Z

So, when something is accessing my name-space, every function inside will be called. So when the function is making functions, these will be available? what happens if I leave something that prints? will it be printed everytime someone uses my namespace?

2021-01-10T20:33:56.354600Z

All top level forms in a namespace are evaluated when you require or use a namespace. If some of those cause printing, then that will happen

2021-01-10T20:34:50.356200Z

Print statements inside of defn forms are not evaluated until the function is called, but print at top level, or in do doseq etc will all be evaluated at require time

2021-01-10T20:37:34.358100Z

If a top level form in a namespace executed a loop, and each iteration of that loop causes something to be defn’d, then that will happen at the time the namespace is required

πŸ™Œ 1
βœ… 1
roelof 2021-01-10T21:30:44.358700Z

oke, some I know , I seen more cheshire instead of jsonista

roelof 2021-01-10T21:31:57.358900Z

Im sure I need one of the two for the gallery project

yiorgos 2021-01-10T21:41:10.361300Z

I am currently learning about Components and while googling I came across this example app https://github.com/seancorfield/usermanager-example/ In the WebServer component they associate a promise in the map here https://github.com/seancorfield/usermanager-example/blob/develop/src/usermanager/main.clj#L165 What is the motivation of doing that?

dpsutton 2021-01-10T21:47:24.362700Z

when running from main that will block waiting for the promise to be delivered, which only happens when the component shutsdown. so in practice, this will just never be fulfilled and the webserver runs forever.

seancorfield 2021-01-10T21:49:15.363400Z

But it also allows you to shutdown the server via code if you need to.

yiorgos 2021-01-10T21:50:56.364100Z

I am not sure I understand. I thought in -main they start the server but the comment says the opposite

seancorfield 2021-01-10T21:52:42.364900Z

The component is started, which starts the web server, and then the promise is pulled out of that component and waited on.

πŸ‘ 1
seancorfield 2021-01-10T21:53:38.365900Z

In normal operation, it'll just wait forever. But you could deliver the promise via a REPL to shut it down.

seancorfield 2021-01-10T21:53:50.366600Z

Or you could just start/stop the component yourself in the REPL.

dpsutton 2021-01-10T21:53:54.366700Z

i don't see how you could shut it down in code though. you'd need access to the component that started to get access to that promise?

dpsutton 2021-01-10T21:54:08.367Z

(when invoked from -main and a repl is used i mean)

seancorfield 2021-01-10T21:55:43.368900Z

When we started out, we used this pattern, along with code that allowed a specific URL to be hit with certain params to deliver the promise (and shut the process down).

yiorgos 2021-01-10T21:55:44.369Z

> The component is started, which starts the web server, and then the promise is pulled out of that component and waited on. I think that makes sense now. Thanks!

dpsutton 2021-01-10T21:55:58.369400Z

ah, not this code but a similar pattern

dpsutton 2021-01-10T21:56:16.370Z

i was scouring it wondering what i was missing πŸ™‚

seancorfield 2021-01-10T21:56:31.370400Z

More recently, we tend to record the started component into a top-level Var so it can be manipulated via a remote REPL more easily.

seancorfield 2021-01-10T21:57:10.371100Z

I've been meaning to clean up how the usermanager example works to better match what we do at work.

seancorfield 2021-01-10T21:57:48.371900Z

It seems like having conditional logic to either start Jetty or http-kit is confusing for folks -- but it was done to show how easy it is to switch web servers.

yiorgos 2021-01-10T21:59:41.373200Z

Is Component the most popular library for that kind of pattern? I see there are Integrant, Mount, Clip that pop up when googling

seancorfield 2021-01-10T22:00:41.373700Z

I think Component is the most popular, yes. And certainly the simplest.

πŸ‘ 1
seancorfield 2021-01-10T22:01:48.375Z

Integrant has, I think, seven lifecycle hooks (compared to Component's two). Mount relies on global data (which just completely discounts it as a choice for me). I haven't looked at Clip.

yiorgos 2021-01-10T22:02:20.375200Z

Thank you very much!

seancorfield 2021-01-10T22:56:48.380400Z

Now that I think about it, the promise was added to make it easier to switch between Jetty and http-kit. Jetty by default blocks the main thread when you start it and you have to say :join? false to have it be non-blocking; http-kit is non-blocking by default. That's what you want for REPL usage. But for -main usage, you want some sort of blocking behavior -- otherwise you start the server and then immediately fall off the bottom of -main and the server shuts down. Adding the promise means that -main can wait on it, regardless of the web server in use. Shutting down the system doesn't matter much in -main since the process is most likely going to stay running until it is externally killed. But in the REPL you're going to start the component (and the web server in a non-blocking way) and then later shut the component down when you're done (and so the promise doesn't really matter). I'll clean up the docs around that when I simplify the example.