beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Aaron Bell 2021-01-08T00:44:26.065100Z

boop.core> (def m {:username "sally" :profile {:name "Sally Clojurian" :address {:city "Austin" :state "TX"}}}

boop.core> (get-in m [:profile :address :state])
"TX"
boop.core> (:state (:address (:profile m)))
"TX"

Aaron Bell 2021-01-08T00:45:08.065300Z

You have everything right except 'adress'. It's likely, as @caumond says, the spelling.

practicalli-john 2021-01-08T00:55:37.065800Z

All the books can be found here https://practicalli.github.io/

👍 1
seancorfield 2021-01-08T00:56:52.066Z

Ah I didn't see it as a title in that big cluster of graphics! Yes, here's the web apps link directly for @mircoporetti https://practicalli.github.io/clojure-webapps/

👍 1
2021-01-08T00:59:22.066200Z

Great list. I’ll add “Joy of Clojure” - one of my favorites. https://www.manning.com/books/the-joy-of-clojure-second-edition

practicalli-john 2021-01-08T01:15:25.066700Z

Keep asking questions, the Clojure community is one of the biggest advantages to learning Clojure https://practicalli.github.io/blog/posts/cloure-community-getting-help/

💯 1
2021-01-08T01:34:18.067Z

I think most languages are niche, until one of three things happen: * A killer app in the language blows up: for example Rails put Ruby on the map. Spark put Scala on the map. Numpy put Python on the map. * A large company becomes the shepherd of the language. Google most famously pushed Python and Go. Mozilla pushed Rust. Twitter pushed Scala. Microsoft pushed TypeScript. * A platform forces its use. Swift and ObjectiveC for Apple. C for linux. JavaScript for browsers. Java/Koltin for Android. C# for Windows and Unity.

practicalli-john 2021-01-08T01:49:42.067400Z

All very good points. JavaScript is a particular good example. I don't think JavaScript was considered a serious language for a long time. Then jQuery came along (which still seems the most used library). Then more business got behind the language (even Microsoft) and of course every companies started using JavaScript for front end websites. Then node and mom came along... Although there are no guarantees that a language grows even with a 'killer app` or company support (i.e Dart from Google) or enviable platform changes. I am enjoying the diversity in languages we have experienced, even though it can add a burden to keep up. This diversity does encourage developers to thing differently about the software they write. This thinking is beneficial to Clojure as there are many subtle and important differences to discover

👍 1
Daniel Tobias 2021-01-08T03:08:51.068800Z

hello all, I am trying to make an app in cljs (with reagent) and it needs to interact with an API that's being hosted by a django backend. Is there a way to do the neat little development environment but somehow proxy all my requests to the django backend?

dumrat 2021-01-08T03:22:36.073400Z

In this video, there's a quote from Rich Hickey and the presenter says that if there's one thing to be taken away from the talk, it should be that:

When you combine two pieces of data you get data. When you combine two machines you get trouble.
I understand what this means (I think). But can someone explain why this has to be stated explicitly? Or what's the context in which this was quipped by Rich Hickey? https://www.youtube.com/watch?v=C-kF25fWTO8

euccastro 2021-01-08T03:24:07.074200Z

@dan.yb.tobias IIUC your django backend will be the only web server, right? then just tell your build tool to put the generated javascript somewhere that your django backend will know to serve

euccastro 2021-01-08T03:24:41.074900Z

in principle it's not very different to working with a Clojure backend

Daniel Tobias 2021-01-08T03:25:08.075700Z

doesnt figwheel or whatever spin up a little development server?

Daniel Tobias 2021-01-08T03:25:14.076Z

i dont want to have to compile every time i make a change etc

euccastro 2021-01-08T03:25:45.076600Z

that's independent of the server that actually serves your main web page

euccastro 2021-01-08T03:27:34.077500Z

https://figwheel.org/docs/your_own_server.html

Daniel Tobias 2021-01-08T03:28:28.078500Z

ty

👍 1
euccastro 2021-01-08T03:29:16.079100Z

if you serve a html doc like the one described in that page from your web server, and if your web server serves the right file when asked for "/cljs-out/dev-main.js", you should be good

2021-01-08T03:32:09.079300Z

It comes from here: https://www.infoq.com/presentations/datomic-functional-database/

2021-01-08T03:32:14.079600Z

14:48

zackteo 2021-01-08T03:36:48.082800Z

Hi everyone, I'm not sure where I should ask this but am trying to get the automated testing for clojurewerkz/money working again. Seems like at least for openjdk8 all tests pass but am encountering Tried to use insecure HTTP repository without TLS as shown here https://travis-ci.org/github/clojurewerkz/money/builds/753470823 Understand that this is the result of the snapshot deployment link for Nexus, but does anyone know what link i should update it to in the project.clj here - https://github.com/clojurewerkz/money/blob/master/project.clj#L19

2021-01-08T03:47:25.083Z

Transcript is here if you prefer reading: https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/FunctionalDatabase.md

seancorfield 2021-01-08T04:12:33.086300Z

@zackteo Change http:// to https://?

orpheus 2021-01-08T04:14:15.088300Z

Hey guys and girls. New to Clojure, I'm learning by writing clojure to solve problems at http://projecteuler.net. I just solved #3 using Clojure and I'd like to get some advice and tips about how I could've written my code better. Here's a gist, lmk if the link works: https://gist.github.com/orpheus/e803cb8fb90f925fda90b07576273741 Also, there's an error I could use help debugging with the getFactor function, if passed 6857 (`getFactor 6857`) there's a stack overflow that I'm not sure how to go about solving.

Rowan Barnard 2021-01-08T09:43:46.114600Z

You might also want to look at https://www.4clojure.com/ which has problems designed to help you learn the language.

zackteo 2021-01-08T04:14:57.089700Z

@seancorfield thought about that. Guess I could give that a try. Was thinking if the link was meant to be inaccessible

euccastro 2021-01-08T04:25:06.090800Z

@titanroark a quick thing to try would be to replace recursive calls to getFactor with recur: https://clojuredocs.org/clojure.core/recur

orpheus 2021-01-08T16:12:44.124900Z

Thank you, this is the kind of advice I was looking for

Daniel Tobias 2021-01-08T04:33:48.093700Z

im a bit confused here, the doc linked doesnt say anything about it

Daniel Tobias 2021-01-08T04:34:35.094400Z

do i need to change the port of the ring server to match as well?

euccastro 2021-01-08T04:35:26.095500Z

also, to find factors you only need to check up to the square root... but now we're talking math. if your current primary focus is learning Clojure, http://projecteuler.net problems may have the focus too much on the math side?

Daniel Tobias 2021-01-08T04:36:51.095900Z

I am so confused, am i running fig:build or what?

euccastro 2021-01-08T04:37:42.096900Z

factorial is a different math concept. stick to the name "factor"

✅ 1
Daniel Tobias 2021-01-08T04:41:06.098400Z

euccastro i think what you suggested before isnt quite right

👀 1
euccastro 2021-01-08T04:41:16.098500Z

lines 8-11 are the same as line 14, just specialized for the number 2. you could just call (getFactor x 2) at that point

✅ 1
euccastro 2021-01-08T04:42:51.098600Z

your django server would replace the ring server. it doesn't matter what port it listens on, as long as you visit localhost:<that-port> in your browser

euccastro 2021-01-08T04:43:19.098800Z

you can run any regular figwheel command

euccastro 2021-01-08T04:43:56.099Z

sorry, I had missed your reply; I've just replied in that thread

Daniel Tobias 2021-01-08T04:45:08.099200Z

there is no html file produced though?

Daniel Tobias 2021-01-08T04:53:01.099400Z

oof this is not working at all, i made an html and loaded the js there but

dumrat 2021-01-08T04:56:33.099600Z

I did some Project Euler problems some time ago. You can find here: https://github.com/nakiya/euler/blob/master/euler.clj Just check for problem 3

Daniel Tobias 2021-01-08T05:00:04.099900Z

@euccastro it looks like how the js is trying to load files is bad...it's using escape charatcers in strings?

zackteo 2021-01-08T05:11:22.100300Z

Wow it did work. Guess i should have just tried that

Daniel Tobias 2021-01-08T05:13:26.100500Z

https://github.com/jstaffans/django-cljs-loader i got it working using this

zackteo 2021-01-08T05:47:15.107Z

Not sure if this falls under beginners but has anyone encountered a situation where a new github pull request (that just changes the readme breaks the existing clojure tests? CI on github actions) https://github.com/zero-one-group/fxl/pull/31/checks?check_run_id=1666803003 It is very strange. Because when I try rerunning the tests on the previous commit there is no issue. But once I make a new pull request, even in the minimal example just amending the readme, breaks the CI

seancorfield 2021-01-08T06:05:50.108Z

It's possible the tests are non-deterministic or something in the tests is not compatible with the GitHub Actions environment...

zackteo 2021-01-08T06:28:37.108100Z

hmmm, my issue is that it would make sense that the github actions doing the test would have failed for the previous commits then or failed when I reran the actions but no issues

zackteo 2021-01-08T06:29:02.108300Z

It is just generally quite an odd situation

seancorfield 2021-01-08T06:33:51.108500Z

Computers are deterministic by definition 🙂

zackteo 2021-01-08T06:34:34.108700Z

My own theory is that the github secrets might be having issues when I am the one pushing the commit

zackteo 2021-01-08T06:35:35.108900Z

Tho I am not sure if that theory checks out with the github actions history :thinking_face:

seancorfield 2021-01-08T06:35:46.109100Z

In which it should be intermittent and kicking off the process again should succeed...

zackteo 2021-01-08T06:37:51.109300Z

Oh I mean the owner of the repo might be the only one able to access the secrets - I can't tell if that makes sense

zackteo 2021-01-08T06:37:59.109500Z

I do know that this exists tho https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/

zackteo 2021-01-08T06:38:11.109800Z

guess all I can do is sleep on it

roelof 2021-01-08T08:18:07.110800Z

Do not know what is the right channel for pedestral questions so I ask here I have this :

`(ns hello
  (:require [io.pedestral.http :as http]
            [io.pedestral.http.route :as route]))

(defn respond-hello [request]
  {:status 200 :body "Hello, world!"})

(respond-hello {})

roelof 2021-01-08T08:18:31.111200Z

deps.edn

{:deps
 {io.pedestal/pedestal.service {:mvn/version "0.5.7"}
  io.pedestal/pedestal.route   {:mvn/version "0.5.7"}
  io.pedestal/pedestal.jetty   {:mvn/version "0.5.7"}
  org.slf4j/slf4j-simple       {:mvn/version "1.7.28"}}
 :paths ["src"]}

roelof 2021-01-08T08:19:01.111700Z

but still I see this error :

; Execution error (FileNotFoundException) at hello/eval13893$loading (REPL:1).
; Could not locate io/pedestral/http__init.class, io/pedestral/http.clj or io/pedestral/http.cljc on classpath.

roelof 2021-01-08T08:19:26.112200Z

im following this tutorial now : http://pedestal.io/guides/hello-world

pavlosmelissinos 2021-01-08T08:28:34.112500Z

You have a typo, it's called pedestal, not pedestral. (Remove the r ) FYI there's #pedestal

roelof 2021-01-08T08:36:11.112700Z

thanks

pez 2021-01-08T09:49:59.116900Z

What am I not getting?

(defn vec-of-14 [&amp; seqs]
  (count seqs) ;=&gt; 3
  (-&gt;&gt; seqs
       (concat)
       (take 14)
       (vec)) ;=&gt; Eval timed out!
  )

(comment
  (vec-of-14 (repeat 14 true)
             (repeat 1 false)
             (repeat true)) ;=&gt; Eval timed out!
  
  (-&gt;&gt; (concat (repeat 14 true)
               (repeat 1 false)
               (repeat true))
       (take 14)
       (vec)) ;=&gt; [true true true true true true true true true true true true true true]
  )
So, the second form in the comment there works as I expect. Trying to make a function from it blows up. The seqs are realized is my guess, but when and how and why?

Matheus Moreira 2021-01-08T10:16:47.117Z

You probably need to replace (concat) by (apply concat) in your method.

pez 2021-01-08T10:28:05.117200Z

Oh, of course… Thanks!

1
roelof 2021-01-08T13:59:42.117800Z

See that I have to learn a lot more about clojure to make my own sites and really understand how things really work

roelof 2021-01-08T14:00:02.118Z

interceptors are I think the hard part

pavlosmelissinos 2021-01-08T14:17:01.118500Z

You don't need interceptors to make a site

pavlosmelissinos 2021-01-08T14:17:11.118700Z

Start simple

pavlosmelissinos 2021-01-08T14:18:36.118900Z

Pedestal bundles a few things together

pavlosmelissinos 2021-01-08T14:21:31.119300Z

If you find it hard to grok you could go a step back. I think the absolute minimum for a beginner is something like compojure and figwheel but it's best to ask around

roelof 2021-01-08T14:22:46.119700Z

maybe I will or go back to duct or take a few steps more back. Before pedestal I did a few tutorials about duct and before that about ring.

benny 2021-01-08T14:35:24.121200Z

what would be the pattern if I basically want to block until a certain condition is true? I'm waiting on a file and the last-modification time keeps changing and I want to wait until it doesn't change any longer for 100ms or something

benny 2021-01-08T14:39:08.121700Z

Your deps.edn looks fine. But you have a misspelling in your require. "pedestral"

roelof 2021-01-08T14:53:06.122Z

thanks

Chase 2021-01-08T15:53:08.122300Z

So what exactly are the differences between `(filter #(<= 5 %) coll)` and `(filter (partial <= 5) coll)` ? Is that second example using a "transducer?"

Chase 2021-01-08T15:53:39.122400Z

From reading the home page docs I don't think so. I should be creating an "xform." I get the feel that transducers are the current trend in performant, idiomatic clojure but I'm mostly confused about it all.

Chase 2021-01-08T15:53:48.122600Z

Any resources you recommend to start thinking in the transducer way of doing things? I feel like that could (should?) be the next step in upping my fp game.

Chase 2021-01-08T15:55:50.122800Z

What initially inspired this is this reddit thread: https://www.reddit.com/r/Clojure/comments/kr0j0f/newbie_question_on_idiomatic_iteration/ I want to start thinking like how SimonGray and joinr handled the problem

dpsutton 2021-01-08T15:56:46.123100Z

https://clojure.org/reference/transducers

dpsutton 2021-01-08T15:56:57.123300Z

neither of those are using transducers

Chase 2021-01-08T15:58:48.123500Z

I knew the first one wasn't, just wasn't sure if that second one was. I guess I don't really know what I'm asking besides how to start thinking in the higher abstraction, transducer sense of solving problems. Probably the only answer is experience.

dpsutton 2021-01-08T16:00:42.123700Z

read that guide and internalize what transducers are. i think its really important to remember they are functions that take reducing functions and return reducing functions

Chase 2021-01-08T16:01:21.123900Z

Will do. The embarrassing part is the first paragraph reiterates: Note: this reduced arity is not currying or partial application. And here I am asking if that partial produced a transducer. lol

dpsutton 2021-01-08T16:03:56.124100Z

no worries. they can be a bit difficult to grok them. follow that guide and build up your intuition and also keep that definition in mind: a function from a reducing function to a reducing function

Chase 2021-01-08T16:05:16.124300Z

And are they more performant to use in most cases? I know that's probably to general to ask though. But is it something you usually try and reach for when writing idiomatic clojure?

dpsutton 2021-01-08T16:06:23.124500Z

at the top is a link for "good use cases for transducers" which has a section about performance. nothing more authoritative or thoughtful than that section

Chase 2021-01-08T16:08:00.124700Z

Fair enough! Thanks

roelof 2021-01-08T16:28:26.125300Z

again stuck how I have to deal with this :

; Implement update-in.

(def my-update-in [m k f]
  
  )
I think at some way I have to find the part with the key and then apply the function at the value and put the whole m again together. Do I thinking the right way ?

2021-01-08T16:37:55.125800Z

Sounds like a good plan, yes. If by "put the whole m again together" you are thinking "create a new map in N steps if the original map m has N key/value pairs", then there are faster ways, e.g. "create a new map from m by replacing only the value of key k with the new value"

roelof 2021-01-08T16:39:04.126Z

hmmm, then I have to think again

roelof 2021-01-08T16:39:34.126200Z

that could work but on some way I have to check where I want to check things

2021-01-08T16:39:43.126400Z

You could get a correct solution by creating a new map in N steps.

roelof 2021-01-08T16:40:16.126600Z

n steps ?

2021-01-08T16:40:16.126800Z

It probably just would not be among the fastest solutions.

2021-01-08T16:40:47.127Z

Your original statement said "and put the whole m again together".

2021-01-08T16:40:59.127200Z

There are multiple things you might have meant when you said that, and I don't know what you were thinking.

roelof 2021-01-08T16:41:17.127400Z

that is not the most important I think. This is a challenge from the brave book and I think the purpose is to understand how things work

2021-01-08T16:41:33.127600Z

One thing you might have meant was "for each of the N keys in the original input map, add that key to a new map to be returned"

roelof 2021-01-08T16:41:33.127800Z

not find the fastest one

roelof 2021-01-08T16:41:56.128Z

Lets say we have this map : (def users [{:name "James" :age 26}  {:name "John" :age 43}])

2021-01-08T16:42:09.128200Z

That is a vector containing two maps.

roelof 2021-01-08T16:42:20.128400Z

oke

roelof 2021-01-08T16:43:15.128600Z

another one then : {:name "James" ;age 26}

2021-01-08T16:43:20.128800Z

That is one map 🙂

roelof 2021-01-08T16:43:46.129Z

now I want to change the age to 36 because I made a typo

2021-01-08T16:43:55.129200Z

sure

roelof 2021-01-08T16:44:12.129400Z

then my idea was to use for example `get to get the age out of it

2021-01-08T16:44:20.129600Z

sounds good

roelof 2021-01-08T16:44:33.129800Z

make a new age with 36

2021-01-08T16:44:40.130Z

yep

roelof 2021-01-08T16:44:55.130200Z

and then I have to make a new map with the name part and the new age part

2021-01-08T16:45:08.130400Z

yes

roelof 2021-01-08T16:45:41.130600Z

or if I want to change the name a new map with the new name and the old age part

roelof 2021-01-08T16:46:08.130800Z

but I think I do not see how the pieces comes together

2021-01-08T16:46:15.131Z

My only point was that there is more than one way to do that last step, and I was making a comment about efficiency of a couple of different ways. If you aren't worried about efficiency at all, then by all means ignore that comment.

roelof 2021-01-08T16:46:31.131200Z

I think I have to store the new part somewhere with a let ?

2021-01-08T16:46:56.131400Z

I wouldn't say "have to", but if it helps you write a solution, then let is perfectly reasonable.

roelof 2021-01-08T16:47:54.131600Z

(def my-update-in [m k f] (let [new_value (f (get m k)]      )

2021-01-08T16:49:04.131800Z

If you want to use let, then taking your breaking the function up in to steps, you can first get the current value in the map for key k, and bind that result to some new name in the let, e.g. cur-val or whatever you would like to call it.

2021-01-08T16:49:23.132100Z

Sure, what you do there is doing your first two steps in one line, which is also good.

roelof 2021-01-08T16:49:47.132300Z

oke , if I go to fast , say it please

2021-01-08T16:50:03.132500Z

I will. Don't worry, I'm following so far 🙂

roelof 2021-01-08T16:50:32.132700Z

then I have to make a new map. I think I need to use assoc

roelof 2021-01-08T16:51:02.132900Z

but how do I now from the old map what is then the old part ?

roelof 2021-01-08T16:51:26.133100Z

and what is the new part?

2021-01-08T16:52:12.133300Z

So assoc always returns a new map, leaving the original one unchanged. The new map is almost the same as the input map, except for the value associated with the key you give to assoc, which in the returned map will be the value you give to assoc

roelof 2021-01-08T16:53:19.133500Z

yep, so there im stuck

2021-01-08T16:53:21.133700Z

user=&gt; (assoc {:a 1 :b 2 :c 3} :b -2)
{:a 1, :b -2, :c 3}

roelof 2021-01-08T16:53:43.133900Z

oke, so I do not have to know

2021-01-08T16:53:49.134100Z

I didn't tell assoc to do anything with keys :a or :c, and the returned map still has them, associated with their original values.

2021-01-08T16:54:10.134300Z

That is what assoc is intended to do.

roelof 2021-01-08T16:54:44.134500Z

oke, did not realize that

2021-01-08T16:55:37.134700Z

Has the book you are following described assoc before this exercise, I hope?

roelof 2021-01-08T16:55:46.134900Z

so I can do just this :

(def my-update-in [m k f]
   (let [new_value (f (get m k)]
   (assoc m new_value) 
  )

roelof 2021-01-08T16:55:58.135100Z

yep, I did

roelof 2021-01-08T16:56:20.135300Z

but I think I misunderstood it as just for adding things

2021-01-08T16:56:21.135500Z

Your call to assoc doesn't have the correct number of parameters.

roelof 2021-01-08T16:57:09.135700Z

(def my-update-in [m k f]
   (let [new_value (f (get m k)]
   (assoc m k new_value) 
  )

2021-01-08T16:57:21.135900Z

that looks better

2021-01-08T16:57:54.136100Z

Looks like a good time to try out your new function with some sample input parameters in a REPL and test if it works as you hope.

roelof 2021-01-08T16:58:10.136300Z

there is still a error somehow

2021-01-08T16:58:27.136500Z

What editor are you using?

roelof 2021-01-08T16:58:32.136700Z

calva is yelling me that the closing ] is on the wrong place

roelof 2021-01-08T16:58:47.136900Z

I use vs code with calva

2021-01-08T16:59:35.137400Z

Most editors have the option to show you when parens, square brackets, or curly braces are matching or not. You definitely want to get familiar with how to understand what it is telling you there.

Ty 2021-01-08T16:59:41.137700Z

Anyone using cider with Doom emacs? Trying to figure out the most appropriate way to evaluate the form under the cursor

👀 1
2021-01-08T17:00:29.137800Z

e.g. many editors will show you the matching paren, bracket, or brace when your cursor is on or just after one of them, highlighting it visually so you can see which one matches the one where the cursor is.

roelof 2021-01-08T17:00:41.138Z

yep, I was missing a )

2021-01-08T17:01:02.138200Z

Trying to write a Lisp-like language without such editor support is going to slow you down tremendously.

2021-01-08T17:01:37.138400Z

There is a lot of fancy 'structural editing' stuff you may have heard about that some people love, but I've never used that myself. But I do really, really miss it if I ever use an editor that doesn't show me matching parens and brackets.

roelof 2021-01-08T17:03:30.138600Z

still somewhere a error :

; Execution error (ClassCastException) at chapter5/my-update-in (form-init95645667318631163.clj:51).
; 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')
code :
(defn my-update-in [m k f]
  (let [new_value (f (get m k))]
    (assoc m k new_value)))

(my-update-in p :age 35)

2021-01-08T17:04:57.138800Z

Is there anything else in the same file with that function? Looking at the function definition, nothing obviously wrong jumps out at me.

2021-01-08T17:05:25.139100Z

What is the 3rd parameter of my-update-in supposed to be?

roelof 2021-01-08T17:06:20.139300Z

Im my first idea it was a function but later it changed to the new value

2021-01-08T17:06:35.139500Z

What does my-update-in do with the 3rd parameter?

roelof 2021-01-08T17:07:10.139700Z

it uses it to make the new map with a updated key

roelof 2021-01-08T17:07:32.139900Z

so it is not a function

2021-01-08T17:07:33.140100Z

The only place the 3rd parameter is used in my-update-in is this expression (f (get m k))

2021-01-08T17:07:49.140300Z

So it is trying to call f as a function.

roelof 2021-01-08T17:08:19.140500Z

yep, I see it , thinking how tto solve it

2021-01-08T17:08:53.140700Z

That is what the exercise asked you to write, I think, yes?

2021-01-08T17:09:32.140900Z

Then when you are trying to use my-update-in, you gave it the number 35 as the 3rd parameter, and my-update-in tried calling the number 35 as if it were a function.

2021-01-08T17:10:02.141100Z

So it appears to me that your my-update-in is doing what the exercise says it should, but your attempt to call the function is passing a 3rd parameter that it was never intended to handle.

2021-01-08T17:10:46.141300Z

i.e. you are calling my-update-in incorrectly. You should try calling it where the 3rd parameter is some function.

2021-01-08T17:11:00.141500Z

If you want a quick try, replace 35 with inc, which is a function.

2021-01-08T17:11:14.141700Z

I'm using it with lispy[ville] and lispy-eval keybinding (iianm I had to add com.cemerick/pomegranate and com.billpiel/sayid to my clojure deps for it to work)

roelof 2021-01-08T17:13:00.141900Z

yep, that works

2021-01-08T17:13:34.142100Z

Does it make sense why you got the error when you passed in 35?

roelof 2021-01-08T17:13:52.142300Z

it makes sense

2021-01-08T17:14:10.142500Z

Do you know how to write a Clojure function that takes a number and adds 10 to it?

roelof 2021-01-08T17:14:57.142800Z

yep

defn add-ten [number] (+ number 10))```

2021-01-08T17:15:18.143Z

Good. If you define that function, you could pass add-ten as the 3rd parameter to my-update-in

roelof 2021-01-08T17:15:51.143300Z

oke, so there is no way I could make it work without a function ?

roelof 2021-01-08T17:16:08.143500Z

only given the right value

2021-01-08T17:16:10.143700Z

You could write a different function than my-update-in

2021-01-08T17:16:27.143900Z

that takes a new value for the 3rd parameter instead of a function.

2021-01-08T17:16:45.144100Z

If you did, I would call it my-assoc 🙂

roelof 2021-01-08T17:16:51.144300Z

I was thinking to change my_update_in

2021-01-08T17:17:26.144500Z

If you change my-update-in to take a value instead of a function as the third parameter, you can certainly do that. Note that it would not be one that solves the exercise you were working on.

roelof 2021-01-08T17:18:18.144700Z

?? the only that the challenge said it to implement update-in

2021-01-08T17:18:29.144900Z

Yes, I understand that.

2021-01-08T17:18:43.145200Z

YOu asked if you could change my-update-in to behave differently. You can do that if you want.

2021-01-08T17:18:54.145400Z

I am only saying that such a changed my-update-in does not solve the challenge.

roelof 2021-01-08T17:19:37.145600Z

oke, I see it, update-in takes always a function

2021-01-08T17:20:00.145800Z

as the 3rd parameter, yes.

roelof 2021-01-08T17:20:03.146Z

so I wanted to make another function

2021-01-08T17:20:22.146200Z

And I encourage you to experiment to your heart's content 🙂

roelof 2021-01-08T17:20:30.146400Z

thanks for thinking with me and teaching me some things

2021-01-08T17:21:56.146700Z

no problem

roelof 2021-01-08T17:22:43.146900Z

clojure is a totally other beast then when I was learning ruby or haskell

roelof 2021-01-08T17:23:06.147100Z

but I love the way repl helps me to see the results when I try something

2021-01-08T17:24:07.147300Z

You could write my-update-in in Haskell in about the same number of characters, I suspect. Clojure and Haskell share that they deal mostly with immutable values, but Haskell has far fewer "escape hatches" than Clojure does for mutating state.

2021-01-08T17:24:27.147500Z

And Clojure doesn't restrict you to writing code that passes Haskell's type checker.

roelof 2021-01-08T17:27:20.147700Z

and clojure is much faster then a haskell programm is my feeling

roelof 2021-01-08T17:28:35.148100Z

and I played with some web stuff and clojure has much more choices then haskell

roelof 2021-01-08T17:28:55.148300Z

in haskell you have only yesod and servant as big players

2021-01-08T17:29:26.148500Z

I don't know a lot about Haskell performance to compare it to Clojure -- they both are not necessarily the language you want to use to get the best performance for heavy numerical computation, for example.

roelof 2021-01-08T17:29:41.148700Z

clojure has for back-end duct, pedestral en some more

2021-01-08T17:29:51.148900Z

but both are perfectly fine for calling out to libraries written in other languages for doing that kind of thing.

roelof 2021-01-08T17:29:54.149100Z

but much more to do for your own

roelof 2021-01-08T17:30:26.149500Z

dinner time

roelof 2021-01-08T17:30:50.149700Z

and tomorrow or later time to study the next chapter macro's 🙂

2021-01-08T17:41:48.150100Z

Apart from that and cider-eval-… bindings as well as cider-pprint-eval-last-sexp-to-comment I so far have found cider debugger with enlighten-mode quite useful. Seeing how flexible this all is I'd be also interested in seeing what others are using for quick & easy inspection of forms & values 🙂

benny 2021-01-08T18:28:31.150700Z

I moved away from lispy because of le-clojure.clj. I use cider-eval-defun-at-point and cider-eval-last-sexp ... If I ever need to be more granular, I use er/expand-region and then cider-eval-region ... all these are bound to things like , e d , e e etc

2021-01-08T18:31:45.150900Z

Use while

2021-01-08T18:33:25.151100Z

These are the same

2021-01-08T18:34:27.151300Z

The only difference is that #(<= 5 %) creates the predicate function at read time, and (partial <= 5) creates the predicate function at run-time

2021-01-08T18:35:55.151500Z

The docstring you're reading is referring to the arity (number of arguments) of filter

2021-01-08T18:36:32.151700Z

Both your example call filter with 2 arguments though, so in your case you are using the 2-ary version of filter in both case

2021-01-08T18:37:36.151900Z

The doc says return a transducer when no collection is provided, and in both cases you provide [pred coll]

Daniel Tobias 2021-01-08T18:39:20.152300Z

it really doesnt look like cljs works well with a django backend 😛

Daniel Tobias 2021-01-08T18:39:25.152500Z

i am really struggling to get it working

2021-01-08T18:44:22.156200Z

The backend and front end are orthogonal. If you return Json the backend technology is irrelevant for cljs. Do you have a more specific problem you can share?

Daniel Tobias 2021-01-08T18:48:12.157300Z

i think it's more about the project.clj file, im doing a figwheel-main reagent template and I guess i need to hook it up so that the project itself isnt necessarily in the django folders but the produced html/js/css ends up in the correct places

Daniel Tobias 2021-01-08T18:48:20.157600Z

there's just like 2 million directories specified in this thing

Daniel Tobias 2021-01-08T18:54:31.159800Z

looks like the configuration doesnt like relative paths either

Daniel Tobias 2021-01-08T18:54:32.160Z

damn

2021-01-08T18:58:54.160300Z

can you share your project.clj?

2021-01-08T18:59:25.160900Z

@b Are you're referring to the part of lispy provided by le-clojure.el ? Does it have some flaws one should be aware of?

Daniel Tobias 2021-01-08T19:00:14.162Z

(defproject livematch "0.1.0-SNAPSHOT"
  :description "FIXME: write this!"
  :url "<http://example.com/FIXME>"
  :license {:name "Eclipse Public License"
            :url "<http://www.eclipse.org/legal/epl-v10.html>"}

  :min-lein-version "2.7.1"

  :dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/clojurescript "1.10.773"]
                 [reagent "0.10.0" ]]

  :source-paths ["src"]

  :aliases {"fig"       ["run" "-m" "figwheel.main"]
            "fig:build" ["run" "-m" "figwheel.main" "-b" "dev" "-r"]
            "fig:min"   ["run" "-m" "figwheel.main" "-O" "advanced" "-bo" "dev"]
            "fig:test"  ["run" "-m" "figwheel.main" "-co" "test.cljs.edn" "-m" "livematch.test-runner"]}

  :profiles {:dev {:dependencies [[com.bhauman/figwheel-main "0.2.12"]]
                   
                   :resource-paths ["target"]
                   ;; need to add the compiled assets to the :clean-targets
                   :clean-targets ^{:protect false} ["target"]}})

Daniel Tobias 2021-01-08T19:02:46.162200Z

the main issue im having i think is the dev-main.js can't find any of the deps it needs for some reason

Daniel Tobias 2021-01-08T19:03:07.162400Z

if i look at dev-main.js i have lines like this:

Daniel Tobias 2021-01-08T19:03:10.162600Z

document.write('&lt;script src="..\..\paladeenz\website\static\livematch\public\cljs-out\dev/cljs_deps.js"&gt;&lt;/script&gt;');

Daniel Tobias 2021-01-08T19:03:15.162800Z

notice the escape characters..

Daniel Tobias 2021-01-08T19:04:40.163Z

it's just copy and pasting the target directory..but remember the src is in a different folder than my django app...so when the js gets put into the django app it needs to look in the correct place for the deps but isnt

2021-01-08T19:07:05.163200Z

what’s dev-main.js?

2021-01-08T19:07:28.163400Z

where is this file? and what’s suppose to do?

Daniel Tobias 2021-01-08T19:07:51.163600Z

this is the output js from building...i fixed it by editing all of the urls the issue is that if recompiled it will overwrite and i have to change it over and over

2021-01-08T19:08:10.163800Z

ohh ok…

Daniel Tobias 2021-01-08T19:08:50.164Z

the target-dir i set is so that it can create dev-main.js in the correct spot, but dev-main itself seems to be using the target-dir also to find the dependencies which completely breaks it

Daniel Tobias 2021-01-08T19:09:26.164200Z

so i have a figwheel-main.edn file which says

:target-dir "../../paladeenz/website/static/livematch"

Daniel Tobias 2021-01-08T19:09:52.164400Z

which puts dev-main.js where it needs to be..it's just now dev-main.js is trying to load files from target-dir + other stuff, which is wrong

Daniel Tobias 2021-01-08T19:10:44.164600Z

https://figwheel.org/config-options#target-dir idk if there's anything in here to fix that

2021-01-08T19:12:40.164900Z

it’s long time since i use fighweel.main but let me see if i can find something

Daniel Tobias 2021-01-08T19:13:27.165100Z

im going to try adding in output-to and output-dir

Daniel Tobias 2021-01-08T19:14:31.165300Z

NVM it didnt like those keywords haha

Daniel Tobias 2021-01-08T19:16:40.165500Z

it's like this stuff is designed to be as cryptic as possible

2021-01-08T19:21:25.165900Z

did you try maybe asking in the #figwheel-main channel, i think somebody with more experience than me will be able to help you (and wife is screaming at me now 8:30 pm now :D)

Daniel Tobias 2021-01-08T19:21:52.166100Z

ok ill ask there, ty

roelof 2021-01-08T20:12:21.167400Z

What is here wrong ?

(defn my-update-in [m ks f args]
  (assoc m ks (apply f (get m ks) args)))

(my-update-in p [:1] :age inc)
error :
; Execution error (IllegalArgumentException) at chapter5/my-update-in (form-init95645667318631163.clj:51).
; Don't know how to create ISeq from: clojure.core$inc

2021-01-08T20:16:01.168600Z

you specify f before args, then :age before inc

2021-01-08T20:16:39.169100Z

also (get m ks) is weird - it's as if you expect the whole seq of keys to be one key

2021-01-08T20:17:10.169500Z

neither :age nor inc are collections, so neither works as a last arg to apply

roelof 2021-01-08T20:29:39.170200Z

I will sleep about this one :

(defn my-update-in [m ks f &amp; args]
  (let [[[k &amp; ks] ks  (assoc m k (apply f (get m ks) args))]])
error ;
; Syntax error macroexpanding clojure.core/let at (chapter5.clj:51:3).
; [[[k &amp; ks] ks (assoc m k (apply f (get m k) args))]] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings

roelof 2021-01-09T09:51:03.196900Z

grrr. now again a wierd error

(defn my-update-in [m ks f &amp; args]
  (let [[k &amp; ks] ks]
    (assoc m k (apply (get m k) ks f args))))


(my-update-in m [:1] assoc :value 1 :active true)
error:
; Execution error (ArityException) at chapter5/my-update-in (form-init6180925798125192449.clj:54).
; Wrong number of args (6) passed to: c
I always thought that &amp; args was taking in all the arguments that were left So why still a argument error

roelof 2021-01-09T09:57:00.197100Z

and when im using our code from yesterday

(defn my-update-in [m keyword number]
  (assoc m  [number keyword] "not-found"))
it added a new value instead of chancing it

roelof 2021-01-09T10:14:53.197300Z

Hmm,

roelof 2021-01-09T10:15:10.197500Z

This works with the m variable but not with the p variable

roelof 2021-01-09T10:15:14.197700Z

(defn my-update-in [m keyword number function]
  (function (get-in m  [number keyword]) ))

(update-in m [:1] assoc :value 1 :active true)

(def p {:name "James" :age 26})

(defn add-ten [number]
    (+ number 10))

(my-update-in p add-ten)

roelof 2021-01-09T10:15:34.197900Z

I see a arityException 😞

roelof 2021-01-09T12:30:47.201Z

or when I do this :

(defn my-update-in2 [m keyword function]
  (function (get-in m keyword)))

(my-update-in2 p :age add-ten)
error :
; Execution error (IllegalArgumentException) at chapter5/my-update-in2 (form-init4877412091744917773.clj:57).
; Don't know how to create ISeq from: clojure.lang.Keyword

2021-01-09T15:32:03.204300Z

get and get-in are different. You are giving get-in a single keyword, when it expects a sequence of key values.

2021-01-09T15:32:39.204500Z

That comment was for my-update-in2

2021-01-09T15:33:02.204700Z

Remember, one way to debug these things is to evaluate expressions step-by-step, and see which one goes wrong, or returns a value you do not expect.

2021-01-09T15:35:58.204900Z

For the call to (my-update-in p add-ten) giving an arityException, well, count the number of args in this definition, and how many you gave in your call: (defn my-update-in [m keyword number function]

2021-01-09T15:36:52.205100Z

In experimentation like this, it might be less confusing to leave earlier experimental functions that you consider working unchanged, and create new names for new experiments. I am not sure if that is part of the difficulty here for you or not, but thought I would suggest it.

2021-01-09T15:53:40.205300Z

Regarding your earlier question today: "I always thought that `& args` was taking in all the arguments that were left So why still a argument error". Because some other function besides my-update-in is being called with the wrong number of args. argument errors can happen for any function called with the wrong number of arguments, not only for ones that you define yourself.

2021-01-09T15:54:34.205500Z

Look for another function that is being called with the wrong number of arguments. Again, I would recommend trying to evaluate sub-expressions step by step, seeing what values they return, and continue step-by-step, and you should be able to get to the answer of which function call is throwing the exception because of wrong number of args.

2021-01-09T15:54:57.205700Z

If you never try to break down these things step by step, I don't know how else to help you learn how to discover what is going wrong.

roelof 2021-01-09T16:39:16.205900Z

oke, I will then try to debug this :

(defn my-update-in2 [m keyword function]
  (function (get-in m keyword)))
where I see this error :
; Execution error (ClassCastException) at chapter5/add-ten (form-init4877412091744917773.clj:62).
; class clojure.lang.Keyword cannot be cast to class java.lang.Number (clojure.lang.Keyword is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')
clj꞉chapter5꞉&gt; 

roelof 2021-01-09T16:39:39.206100Z

my idea is that there is a argument missing in the get-in part

roelof 2021-01-09T16:42:44.206300Z

yep, when I do (get-in p :name) I see the same error

roelof 2021-01-09T16:43:07.206500Z

where p is (def p {:name "James" :age 26})

2021-01-09T16:43:18.206700Z

So, what do you know about the arguments that get-in should be given?

roelof 2021-01-09T16:43:31.206900Z

but no idea was should be missing

2021-01-09T16:43:47.207100Z

What is the difference between get and get-in ?

roelof 2021-01-09T16:44:03.207300Z

I do not have a key before the :name`

2021-01-09T16:44:33.207500Z

If it helps you remember, create working examples of both get and get-in that you put in some personal notes for each function, maybe plus a sentence or two explaining the difference between them.

roelof 2021-01-09T16:45:10.207700Z

oke,

roelof 2021-01-09T16:46:20.207900Z

both are working

(defn my-update-in [m keyword number function]
  (function (get-in m  [(number keyword) keyword]) ))

(defn my-update-in2 [m keyword function]
  (function (get-in m keyword)))
so I now know if there is a number given I need get-in and otherwise I need get

2021-01-09T16:46:34.208100Z

In case it helps, my personal thinking on this to explain their difference would be like so: "get takes a map and a single key to be looked up, or a vector and a key (integer index) to be looked up, and returns the value associated with that key, or nil if the key is not found"

roelof 2021-01-09T16:47:09.208300Z

yep

2021-01-09T16:47:15.208500Z

"get-in takes a sequence of keys to be looked up, and if that sequence is N elements long, it behaves like N repeated applications of the function get where each repeated application of get is applied to the collection returned by the previous call to get."

roelof 2021-01-09T16:48:14.208800Z

so it looks I need a function with 2 things in it one for 4 arguments and one for 3

2021-01-09T16:48:15.209Z

Thus (get m k) and (get-in m [k]) behave exactly the same as each other.

roelof 2021-01-09T16:49:01.209200Z

BRB, wife needs the computer

2021-01-09T16:49:05.209400Z

sure

2021-01-09T16:49:23.209600Z

In what way does the my-update-in2 function you show above "work"?

2021-01-09T16:49:43.209800Z

As in, can you give an example call where it does what you want?

roelof 2021-01-09T17:02:13.210Z

of course :

(def p {:name "James" :age 26})


(defn add-ten [number]
    (+ number 10))

(my-update-in2 p :age add-ten)

roelof 2021-01-09T17:02:47.210200Z

gives : 36 chips the old one needs to be added

roelof 2021-01-09T17:04:42.210400Z

the other one :

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})


(defn my-update-in [m keyword number function]
  (function (get-in m  [(number keyword) keyword]) ))

(defn my-update-in2 [m keyword function]
  (function (get-in m keyword)))

(update-in m [:1] assoc :value 1 :active true)
gives :
{:1 {:value 1, :active true}, :2 {:value 0, :active false}}

roelof 2021-01-09T17:04:49.210600Z

which is right

roelof 2021-01-09T17:07:14.211Z

so for the second one back to the drawing board

2021-01-09T17:10:07.211200Z

Is your goal to write my-update-in so that it can take a sequence of keys, like get-in does? Or do you want to make it so it can take one key, or two keys, only?

roelof 2021-01-09T17:11:02.211400Z

first one key, later maybe more keys

2021-01-09T17:11:38.211600Z

So yesterday you had a working my-update function that took only 1 key, and I thought worked, true?

roelof 2021-01-09T17:12:27.211800Z

my goal is still to make it work with this two :

(def p {:name "James" :age 26})
(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})

roelof 2021-01-09T17:12:47.212Z

yep, and also for the m one we have a working version

roelof 2021-01-09T17:13:09.212200Z

for the p as far as I know we have not

roelof 2021-01-09T17:13:16.212400Z

or I have deleted it

2021-01-09T17:15:14.212600Z

So sorry if you've already said it clearly and I've forgotten, but what do you mean when you say "my goal is still to make it work with this two ...". What do you want the behavior to be? Stating what you want the behavior to be with inputs and desired return values can help clarify this (at least for me).

roelof 2021-01-09T17:16:11.213Z

np

2021-01-09T17:16:38.213200Z

One way to clarify this would be to say: "I want to write my own version of Clojure's built-in update-in function, that always returns the same values it does, given the same inputs."

roelof 2021-01-09T17:16:45.213400Z

we have two working versions

(defn my-update-in [m keyword number function]
  (function (get-in m  [(number keyword) keyword]) ))

(defn my-update-in2 [m k f]
  (let [new_value (f (get m k))]
    (assoc m k new_value)))

2021-01-09T17:17:13.213700Z

but I'm not sure if that is what you are trying to do, or not.

roelof 2021-01-09T17:17:22.213900Z

update-in works on this case : (def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})

roelof 2021-01-09T17:17:53.214100Z

and update-in2 works in this case : (def p {:name "James" :age 26})

2021-01-09T17:17:57.214300Z

Do you mean Clojure's built-in function udpate-in works on that case, or do you mean one of your my-update-in functions works in that case.

2021-01-09T17:18:11.214500Z

Because if you use different names, I get confused which function you mean.

roelof 2021-01-09T17:18:19.214700Z

the code we wrote seems to work

2021-01-09T17:18:30.214900Z

The code you wrote is not called update-in

roelof 2021-01-09T17:18:42.215100Z

im talking about my written versions of update-in

2021-01-09T17:19:08.215300Z

So please use my-update-in to refer to my-update-in, because there is a Clojure built-in function named update-in

roelof 2021-01-09T17:19:18.215500Z

yep

roelof 2021-01-09T17:19:48.215700Z

sorry, I named it so because it otherwise make problems with the built in one

2021-01-09T17:20:02.215900Z

When you say my-update-in "works" in this case, you are only giving one of the parameter values, not all of them. It doesn't make any sense to me to only give one of the parameters of a function that takes 2 or 3 parameters, and say it works.

2021-01-09T17:20:21.216100Z

Its behavior depends upon all of the parameter values, not just one.

roelof 2021-01-09T17:20:30.216300Z

sorry for the confusion

2021-01-09T17:21:21.216500Z

Please give complete calls to those functions that you consider working.

roelof 2021-01-09T17:21:36.216700Z

oke

roelof 2021-01-09T17:22:05.216900Z

I know have this :

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})


(defn my-update-in [m keyword number function]
  (function (get-in m  [(number keyword) keyword]) ))

(defn my-update-in2 [m k f]
  (let [new_value (f (get m k))]
    (assoc m k new_value)))


(my-update-in m [:1] assoc :value 1 :active true)

roelof 2021-01-09T17:22:29.217100Z

and get a argument error . I have to give 4 arguments and I provide 7

2021-01-09T17:23:22.217300Z

So what function do you want to write? Please try to state that clearly, otherwise the goal keeps changing.

2021-01-09T17:23:41.217500Z

You say that these functions do what you want, then you say that they don't do what you want.

roelof 2021-01-09T17:24:15.217700Z

yep, I see now that I use the built-in function not my own written one

roelof 2021-01-09T17:24:21.217900Z

stupid mistake

roelof 2021-01-09T17:25:23.218100Z

pfff, two days busy and not closer to the solution. Wonder if clojure is for me

2021-01-09T17:27:15.218300Z

I can't answer that for you. For solving a problem of writing a particular function, I may be able to help if I know what function you want to write 🙂

roelof 2021-01-09T17:27:36.218500Z

for now I want to make my own written update-in working

2021-01-09T17:28:10.218700Z

And you want it to behave the same way that Clojure's built-in function update-in works?

roelof 2021-01-09T17:28:34.218900Z

yep, that is I think the purpose of the challenge

2021-01-09T17:29:48.219100Z

ok, so that makes the goal of what function to write pretty clear, because we have an existing function that we can make calls to, see what the return value is, and know that is what this new function should return. (or we can just read the code of update-in to see how it works, of course, but maybe not yet for this challenge).

2021-01-09T17:30:47.219300Z

It is OK to write multiple functions along the way that only do part of what update-in does, of course, and there are multiple ways to break that down into steps.

roelof 2021-01-09T17:30:59.219500Z

we can even peek how it written but that feels to me as cheating

2021-01-09T17:31:48.219700Z

One way would be to first write a function that doesn't take the &amp; args part of the arguments that update-in does, only the function f as the last parameter, and see if we can make something that works like that part of update-in. Only if you get that working first, then try to add the &amp; args part.

2021-01-09T17:32:35.219900Z

That is, try writing a function my-update-in that takes only the arguments [m ks f] and no others, and make it behave the same way as Clojure's built-in update-in when given those arguments only.

roelof 2021-01-09T17:32:53.220100Z

We had that I think with this version

`(defn my-update-in2 [m k f]
  (let [new_value (f (get m k))]
    (assoc m k new_value)))
or do I misunderstood you now

roelof 2021-01-09T17:33:15.220300Z

we wrote that yesterday

2021-01-09T17:33:54.220500Z

I am pretty sure that behaves like Clojure's built-in function update, but it does not behave the same way as Clojure's built-in function update-in

2021-01-09T17:34:03.220700Z

Here are some examples to demonstrate why I think so:

2021-01-09T17:38:12.220900Z

(defn my-update-in2 [m k f]
  (let [new_value (f (get m k))]
    (assoc m k new_value)))

(def m1 {:a 17 :b 18})

(update m1 :a inc)
;; {:a 18, :b 18}
(my-update-in2 m1 :a inc)
;; {:a 18, :b 18}

(update-in m1 [:a] inc)
;; {:a 18, :b 18}
(my-update-in2 m1 [:a] inc)
;; Execution error (NullPointerException) at user/my-update-in2 (REPL:63).
;; Cannot invoke "Object.getClass()" because "x" is null

2021-01-09T17:38:54.221100Z

The function that you have called my-update-in2 behaves the same as Clojure's built-in update for the example parameters shown above. It does not behavior the same as Clojure's built-in update-in for the example parameters shown above.

2021-01-09T17:39:19.221300Z

If I were you, I would rename my-update-in2 to my-update, since we know it doesn't behave like update-in

2021-01-09T17:39:28.221500Z

and at least in some cases, it does behave like update

roelof 2021-01-09T17:39:43.221700Z

oke

roelof 2021-01-09T17:40:03.221900Z

we did yesterday only check it on this : (def p {:name "James" :age 26})

2021-01-09T17:40:23.222100Z

The map I give is the same in all calls.

2021-01-09T17:40:26.222300Z

That is not the difference.

2021-01-09T17:40:38.222500Z

Do you see the difference in the parameters given to update vs. update-in?

roelof 2021-01-09T17:41:26.222700Z

I think so we gave it a key and on update-in2 fails when its a vector of keys

2021-01-09T17:42:07.222900Z

As I wrote above, the difference between get and get-in is that get takes a single key but get-intakes a vector (or sequence) of keys.

roelof 2021-01-09T17:42:40.223100Z

yep

2021-01-09T17:42:41.223300Z

That is one of the main differences between Clojure's built-in update and update-in, too. update-intakes a vector (or sequence) of keys, updatetakes only a single key

roelof 2021-01-09T17:43:09.223500Z

hmm, I have to think how to solve that one

2021-01-09T17:43:22.223700Z

Your function my-update-in2 works for a single key. It does not work for a vector (or sequence) of keys.

roelof 2021-01-09T17:43:22.223900Z

idea is to use apply somewhere

roelof 2021-01-09T17:43:45.224100Z

or maybe recursion

2021-01-09T17:43:49.224300Z

I can see how apply can help if you are trying to implement the &amp; args part of the problem.

roelof 2021-01-09T17:44:06.224500Z

yep, but that is not the problem now

2021-01-09T17:44:10.224700Z

But I do not see how apply can help if you are trying to implement the part of handling a vector of keys.

2021-01-09T17:44:19.224900Z

Recursion or a loop sounds more promising to me.

roelof 2021-01-09T17:44:39.225100Z

BRB dinnner and I have to take some time to think how this could work

roelof 2021-01-09T17:45:22.225300Z

because yesterday you said destruction is almost never needed

roelof 2021-01-09T17:45:31.225500Z

and now I need to get the first key

2021-01-09T17:46:19.225700Z

destructuring is never necessary to write a correct Clojure program. It can be a nice convenience in some cases, but you can always write an equivalent Clojure program that does not use destructuring, using functions like first and rest or nth

2021-01-09T17:47:20.225900Z

(first [:a :b :c])
;; :a
(rest [:a :b :c])
;; (:b :c)

2021-01-09T17:47:37.226100Z

I would hope that those functions were described early in the book you are using

2021-01-09T17:48:27.226300Z

They work on any vectors or sequences, no matter whether they contain numbers, keywords, other collections, etc.

roelof 2021-01-09T18:12:57.226500Z

yep, there are also explained

roelof 2021-01-09T18:13:16.226700Z

dinner ready and time to think about this one

roelof 2021-01-09T18:13:27.226900Z

am I right I need a anymous function here

2021-01-09T18:14:27.227100Z

I would also put anonymous functions into the category of "often convenient, but not absolutely required", like destructuring.

2021-01-09T18:14:49.227300Z

I do often use them when they are short and thus convenient to use, so I don't have to make up a name for some tiny one-use function.

2021-01-09T18:15:42.227700Z

The only reason I say these things is because you ask if you "need" an anonymous function. When you use that word, it makes me think "there is no other way to write the function I want, other than to use an anonymous function", and that is never true. You can always write a small function with a name and call that instead.

2021-01-09T18:17:19.227900Z

Note: I am not saying that destructuring or anonymous functions are bad. I am only saying they are not needed.

2021-01-09T18:18:21.228100Z

There are some Clojure language constructs that are pretty much needed, or else you cannot write useful programs. E.g. being able to define functions, and call them, is needed for writing practical programs.

roelof 2021-01-09T18:24:42.228300Z

and im now lost in parentheses here :

(defn my-update-in [m [ks] f]
  (let [up (fn up [m ks f ]
             (let [k (first ks)
                   rest (rest ks)
                   new_value (f (get m k))
                   (assoc m k new_value)]))]))

roelof 2021-01-09T18:31:51.228500Z

why makes clojuer things so difficult

2021-01-09T18:34:55.228700Z

Does your editor automatically show you the matching parenthesis or bracket for the one that your cursor is next to?

roelof 2021-01-09T18:36:25.228900Z

yep

roelof 2021-01-09T18:36:33.229100Z

got it after some fiddeling

roelof 2021-01-09T18:36:37.229300Z

(defn my-update-in [m [ks] f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   rest (rest ks)
                   new_value (f (get m k))]
               (assoc m k new_value)))]))

2021-01-09T18:37:03.229500Z

Some fiddling is pretty normal in such situations. Practice makes the fiddling easier.

roelof 2021-01-09T18:37:03.229700Z

now time to think where the recursive call wiill be if this a good code

2021-01-09T18:37:23.229900Z

Why did you put brackets around [ks] in the arguments to my-update-in?

roelof 2021-01-09T18:38:02.230100Z

I thought that was needed

2021-01-09T18:38:16.230300Z

Needed for what?

roelof 2021-01-09T18:38:46.230500Z

needed to make it work and tell a user ks needs to be a vector

2021-01-09T18:40:06.230700Z

There are no type declarations on Clojure parameters to tell you they need to be a vector, or a map, or any other kind of thing, the way some languages have.

2021-01-09T18:41:02.230900Z

What Clojure actually does when you write a parameter like that is destructuring. It will expect that second argument to be a vector or sequence, take the first element of that vector or sequence, bind it to the name ks, ignore the rest of that vector or sequence, and execute the body of the function.

2021-01-09T18:41:45.231100Z

If you write ks instead of [ks] there, it will take whatever the second parameter is, a vector, a sequence, a number, whatever, and bind it to ks, and discard none of that value.

roelof 2021-01-09T18:41:46.231300Z

oke, this seems to be complimng

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   rest (rest ks)
                   new_value (f (get m k))]
               (assoc m k new_value)))]
    (up m ks f)))
I only have to figure out where the recursive call needs to be 😞

2021-01-09T18:42:46.231500Z

Looks like a good start to me.

roelof 2021-01-09T18:42:59.231700Z

yep me too

2021-01-09T18:43:01.231900Z

Where you now have (assoc m k new_value), you need to have (at least) two cases.

roelof 2021-01-09T18:43:31.232100Z

do I ?

2021-01-09T18:44:06.232300Z

Warning: rest (rest ks) using the name rest there means that in the body of that let, it will be impossible to call the built-in function rest because you have re-bound the name rest to a new value.

2021-01-09T18:44:36.232500Z

If you never do that, then no problem, but if you do try to call the built-in function rest inside of that let, it can be very confusing what is going wrong.

roelof 2021-01-09T18:44:48.232700Z

oops, what is then a better name for all the other entries in ks

roelof 2021-01-09T18:45:24.232900Z

mayeb again ks ?

2021-01-09T18:45:27.233100Z

If the inner let is only a small amount of code, as I expect it will be, a single letter like r is probably ok.

2021-01-09T18:45:48.233300Z

ks looks fine, too, as long as you know it will be all but the first element of the original ks inside of the let body.

2021-01-09T18:46:00.233500Z

I will be AFK for a few minutes at least.

roelof 2021-01-09T18:46:13.233700Z

oke, no problem

roelof 2021-01-09T18:46:19.233900Z

I have called it r

roelof 2021-01-09T18:47:30.234100Z

still thinking where I have to put the call to up

roelof 2021-01-09T18:48:08.234300Z

Still thinking before the (get m k) part but then the name is not right anymore

roelof 2021-01-09T18:52:34.234500Z

so something like this :

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   r (rest ks)]
               (assoc m k (up (get m k) r f))))]
    (up m ks f)

roelof 2021-01-09T18:55:32.234700Z

and I do not work on both cases one still give a error that I have given 7 arguments where 4 are given

roelof 2021-01-09T18:55:53.234900Z

and the other one :

(my-update-in p :age inc)

roelof 2021-01-09T18:56:33.235100Z

give this :

; Execution error (IllegalArgumentException) at chapter5/my-update-in$up (form-init12940824632450433692.clj:55).
; Don't know how to create ISeq from: clojure.lang.Keyword

2021-01-09T18:58:11.235300Z

Currently you are working on implementing the case without &amp; args

2021-01-09T18:58:23.235500Z

If you are doing that, then stick to it, and never try to call it with 7 args

2021-01-09T18:58:39.235700Z

Pick a single function to call it with, and test it with that, with no extra args.

roelof 2021-01-09T18:59:07.235900Z

oke, I did with the p one and it also fails

roelof 2021-01-09T19:00:10.236100Z

or is this not a single one : (my-update-in p :age inc)

2021-01-09T19:00:12.236300Z

Earlier I said: "Where you now have `(assoc m k new_value)`, you need to have (at least) two cases." and you answered "Do I?"

2021-01-09T19:00:17.236500Z

Have you written recursive functions before?

roelof 2021-01-09T19:00:28.236900Z

yep, in haskell a lot

2021-01-09T19:00:45.237100Z

Have you tried writing a recursive function that did not have two or more cases in its body?

roelof 2021-01-09T19:01:02.237300Z

there you had to write a base case when the recursion has to quit and one for the rest

2021-01-09T19:01:08.237500Z

right.

roelof 2021-01-09T19:01:17.237700Z

so no, that will cause a infinite loop

roelof 2021-01-09T19:01:45.237900Z

the base case is here when ks is empty I think

2021-01-09T19:01:51.238100Z

Same here. You need a base case that does not make a recursive call, and you need a recursive call that does part of the work, but also calls itself recurively on a smaller problem.

2021-01-09T19:02:36.238300Z

The assoc you have in the inner let seems like it might be reasonable for a base case.

roelof 2021-01-09T19:02:40.238500Z

hmm, so here when r is empty , have to think what can be done then

2021-01-09T19:03:21.238700Z

When you have only one key left k which is (first ks), you want to do that assoc call I believe.

2021-01-09T19:04:11.238900Z

The base case is "do the same thing update would do given that one key"

roelof 2021-01-09T19:04:20.239100Z

oke, that way

roelof 2021-01-09T19:04:39.239300Z

oke, we need a if , I believe

2021-01-09T19:05:12.239500Z

An if would be one way. cond is another, but if is good enough for here.

roelof 2021-01-09T19:05:31.239700Z

maybe if (== (count r) 1) ???

2021-01-09T19:05:54.239900Z

Do you want the base case to be when r has 1 key left in it?

roelof 2021-01-09T19:06:25.240100Z

if (== (count first) 1)`

2021-01-09T19:06:29.240300Z

Earlier you suggested "the base case is here when ks is empty I think"

roelof 2021-01-09T19:06:54.240500Z

if (empty? r)

2021-01-09T19:07:51.240700Z

That seems to me to match the condition "`k` is the last key of the original input sequence, and there are no more"

2021-01-09T19:11:24.242600Z

Looks reasonable to me. Even as written, that should hopefully work if you give a sequence of one key as ks argument.

roelof 2021-01-09T19:11:34.242800Z

am I here right

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   r (rest ks)]
               (if (empty? r)
                 (assoc m k (up (get m k) r f))
                 (assoc m k (apply (get m k) r f))
                 )))]
    (up m ks f)))

2021-01-09T19:11:45.243Z

I was just about to suggest leaving out &amp; args again 🙂

2021-01-09T19:12:01.243200Z

The else case of your if is not recursive.

2021-01-09T19:12:27.243400Z

The then case is recursive, when it should be the base case.

roelof 2021-01-09T19:13:10.243800Z

moment, I have to switch them ?

2021-01-09T19:14:10.244Z

You tell me. In what condition should you make a recursive call, and which one should you NOT make a recursive call?

roelof 2021-01-09T19:16:06.244200Z

oke

roelof 2021-01-09T19:16:18.244400Z

I have now this :

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   r (rest ks)]
               (if (empty? r)
                 (assoc m k (up (get m k) r f))
                 (assoc m k (apply (get m k) f))
                 )))]
    (up m ks f)))
         


(my-update-in p :age inc)

roelof 2021-01-09T19:16:33.244600Z

; Execution error (IllegalArgumentException) at chapter5/my-update-in$up (form-init12940824632450433692.clj:55).
; Don't know how to create ISeq from: clojure.lang.Keyword
clj꞉chapter5꞉&gt; 

2021-01-09T19:17:51.245Z

You have the recursive call when (empty? r) is true. I don't think that is correct. There is no reason to keep going with more keys, is there?

roelof 2021-01-09T19:17:58.245200Z

when I do [my-update-in p [:age] inc) I get a stack overflow

roelof 2021-01-09T19:19:16.245400Z

here still the same IlligalArgumentException

roelof 2021-01-09T19:19:22.245600Z

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   r (rest ks)]
               (if (empty? r)
                (assoc m k (apply f (get m k)))
                (assoc m k (up (get m k) r f))
                 )))]
    (up m ks f)))
         


(my-update-in p :age inc)

roelof 2021-01-09T19:24:12.245900Z

; Execution error (IllegalArgumentException) at chapter5/my-update-in$up (form-init12940824632450433692.clj:57).
; Don't know how to create ISeq from: clojure.lang.Keyword

roelof 2021-01-09T19:24:29.246100Z

got the feelimg im very close but I oversee something

2021-01-09T19:27:31.246300Z

I don't know your current definition of p

roelof 2021-01-09T19:28:10.246500Z

(def p {:name "James" :age 26})

roelof 2021-01-09T19:30:59.248500Z

be back in 10 - 15 min. Going for a walk to get a fresh head

2021-01-09T19:31:35.248900Z

What should be the second argument to my-update-in?

roelof 2021-01-09T19:32:58.249100Z

a vector ?

roelof 2021-01-09T19:33:33.249500Z

but also then I see that annoying error

2021-01-09T19:33:44.249800Z

a vector or a sequence is what update-in is supposed to take, not a single key.

roelof 2021-01-09T19:33:52.250200Z

(my-update-in p [:age] inc)

2021-01-09T19:33:53.250400Z

You are trying to write update-in, so you should test it like update-in

roelof 2021-01-09T19:34:09.250900Z

??

roelof 2021-01-09T19:34:31.251300Z

I got these examples from the page of update-in

2021-01-09T19:34:53.251500Z

Your current goal, if I understand it, is to write a function that works like update-in. update-in would give an error if you gave it a single key, not a vector or sequence of keys as the second parameter. So don't test your function in a way that update-in cannot work.

2021-01-09T19:34:59.251700Z

Which example page of update-in?

2021-01-09T19:35:29.252Z

Show me an example page of update-in calling it like this: (my-update-in p :age inc) and I will show you a page with a mistake.

roelof 2021-01-09T19:36:17.252200Z

this page(https://clojuredocs.org/clojure.core/update-in) but also when I change it to (my-update-in p [:age] inc)

roelof 2021-01-09T19:36:35.252400Z

I see this error :

; Execution error (IllegalArgumentException) at chapter5/my-update-in$up (form-init12940824632450433692.clj:57).
; Don't know how to create ISeq from: clojure.lang.Keyword

2021-01-09T19:39:52.252600Z

Every example on that page has a vector of keys that I can see.

roelof 2021-01-09T19:40:23.253100Z

oke, but why if I do that I still see the argumentError

roelof 2021-01-09T19:40:42.253300Z

maybe because we do not use &amp;args

2021-01-09T19:45:45.253600Z

I don't think &amp; args can cause that error.

2021-01-09T19:45:57.253800Z

Playing a board game at the moment, so dividing my attention and may be slow here.

roelof 2021-01-09T19:47:04.254Z

oke

roelof 2021-01-09T19:47:15.254200Z

we can discuss this later if you have more time

roelof 2021-01-09T19:47:43.254400Z

but I see that it chrashing on the (empty? .._) line

roelof 2021-01-09T19:48:00.254600Z

and I do not make any difference if I use r or k here

2021-01-09T19:49:36.254900Z

I don't see why it would crash on that line: (empty? (rest [:a]))

2021-01-09T19:49:49.255100Z

returns true as I would expect. As long as you put r there, not k

roelof 2021-01-09T19:50:34.255300Z

hmm, here it chrashes

(defn my-update-in [m ks f]
  (let [up (fn up [m ks f]
             (let [k (first ks)
                   r (rest ks)]
               (if (empty? r)
                 (assoc m k (apply f (get m k)))
                 (assoc m k (up (get m k) r f)))))]
    (up m ks f)))

2021-01-09T19:53:24.255500Z

Take out the apply. We are not doing the &amp; args version yet.

2021-01-09T19:55:35.255700Z

This function call gives the same error, and is the reason you are getting the exception: (apply inc (get p :age))

roelof 2021-01-09T20:08:24.255900Z

yes, it working 🎉

roelof 2021-01-09T20:08:44.256100Z

so now to make ti work with & args ?

2021-01-09T20:13:20.256300Z

Before that, have you tested it with a sequence of multiple keys?

roelof 2021-01-09T20:14:27.256600Z

nope

2021-01-09T20:15:12.256800Z

I would recommend testing to see if that case works before &amp; args

roelof 2021-01-09T20:15:42.257Z

it seems to work

(defn my-update-in [m ks f ]
  (let [up (fn up [m ks f ]
             (let [k (first ks)
                   r (rest ks)]
               (if (empty? r)
                 (assoc m k (f (get m k )))
                 (assoc m k (up (get m k) r f )))))]
    (up m ks f )))

roelof 2021-01-09T20:16:18.257200Z

(my-update-in p [:age] inc)

roelof 2021-01-09T20:16:40.257400Z

answer : {:name "James", :age 27}

2021-01-09T20:17:13.257600Z

That does not test it with a sequence of 2 or more keys.

2021-01-09T20:17:27.257800Z

You are still testing the case with a sequence of one key, so the recursive case is not being exercised at all.

roelof 2021-01-09T20:17:33.258Z

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})

(update-in m [:1] assoc :value 1 :active true)

answer : {:1 {:value 1, :active true}, :2 {:value 0, :active false}}

roelof 2021-01-09T20:17:52.258200Z

which is also well

roelof 2021-01-09T20:18:21.258400Z

satisfied ?

roelof 2021-01-09T20:20:31.258600Z

I am

roelof 2021-01-09T20:20:51.258800Z

2 days struggeling and both cases solved 🎉

roelof 2021-01-09T20:24:37.259Z

if you do not have feedback then I would thank you for a lot of patience with me

roelof 2021-01-09T20:24:49.259200Z

ennjoy the weekend and your family

2021-01-09T20:42:45.259400Z

no further feedback 🙂. May you also enjoy your weekend.

2021-01-09T20:43:18.259600Z

The last case you showed still has a vector of only 1 key, so not testing recursion, though 🙂

roelof 2021-01-09T20:46:17.259800Z

hmm, then I have to look for a example for that case

2021-01-09T20:46:30.260Z

or make one up

roelof 2021-01-09T20:49:34.260400Z

maybe this one :

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}, :3 {:value 0, :active false}})

roelof 2021-01-09T20:51:49.260600Z

(update-in m [:1 :3] assoc :value 1 :active true)

roelof 2021-01-09T20:52:05.260800Z

does not give the right answer 😞

roelof 2021-01-09T20:52:27.261Z

also not (update-in m [:[1 ][:3]] assoc :value 1 :active true)

roelof 2021-01-09T21:06:35.261200Z

or do you more like this :

(def player1 {:name "Player 1" :attribs {:str 10 :int 11 :wis 9}})

(update-in player1 [:attribs :str] inc)
;; {:name "Player 1", :attribs {:str 11, :int 11, :wis 9}}

roelof 2021-01-09T21:06:58.261400Z

where a nested one is done

roelof 2021-01-09T21:08:22.261600Z

that one works 🎉

roelof 2021-01-09T21:46:25.261900Z

time to sleep here. Again many mny thanks for all the patience with me

roelof 2021-01-09T21:46:45.262100Z

a lot to learn how to approach "complex" problems like this

2021-01-09T22:00:23.262300Z

The example with player1 looks like a good test that actually exercises the recursive code.

roelof 2021-01-09T22:09:39.262500Z

thanks, it worked also

roelof 2021-01-09T22:10:00.262700Z

I get the same answer as the page said

roelof 2021-01-09T22:14:08.262900Z

then tomorrow or Monday this page on the menu : https://www.braveclojure.com/read-and-eval/#Summary

2021-01-08T20:31:39.170600Z

that last call needs to be outside the [] binding block

2021-01-08T20:32:13.171300Z

the syntax of let is (let [binding value ... ...] body) - it's usually a logic error not to provide a body, and it's a compilation error to have a binding without a value (or visa versa)

2021-01-08T20:34:13.171500Z

When first learning, I would recommend avoiding the use of destructuring, until and unless you get a version of a function working without it.

2021-01-08T20:34:44.171700Z

Destructuring can be useful, but it is never necessary.

roelof 2021-01-08T20:41:43.172Z

hmm

roelof 2021-01-08T20:41:51.172300Z

you mean like this :

(defn my-update-in [m ks f &amp; args]
  (let [[k &amp; ks] ks]
  (assoc m k (apply f (get m ks) args))))



(my-update-in p [:1] assoc :name "James" :age 35)

roelof 2021-01-08T20:42:16.172600Z

that does this :

{:name "James", :age 26, :1 {:name "James", :age 35}}

roelof 2021-01-08T20:42:24.172900Z

and not updating the value

roelof 2021-01-08T20:43:13.173Z

oke

roelof 2021-01-08T20:46:00.173200Z

hmm, still no luck

(defn my-update-in [m ks f &amp; args]  
  (assoc m ks (apply f (get m ks) args)))



(my-update-in p [:0] assoc :name "James" :age 35)
gives this :
{:name "James", :age 26, [:0] {:name "James", :age 35}}

roelof 2021-01-08T20:48:27.173400Z

maybe the apply is wrong here

roelof 2021-01-08T21:03:13.176400Z

@andy.fingerhut

caumond 2021-01-08T21:03:24.176800Z

Im not getting what you want to achieve there. Update-in work with nested maps. And ks is supposed to be a list a key of your map. What do you want to specify with :1 ?

roelof 2021-01-08T21:03:26.176900Z

but I do not see any better one

2021-01-08T21:03:59.177100Z

It is almost always possible to take a Clojure function and evaluate it step by step in a REPL session.

2021-01-08T21:04:14.177300Z

Do you know which sub-expression of your my-update-in above must be evaluated first?

roelof 2021-01-08T21:04:46.177500Z

I would say get m ks

2021-01-08T21:04:53.177700Z

yes, good.

2021-01-08T21:05:06.177900Z

And what parameters it should be passed in your example call, and what value it will return?

2021-01-08T21:05:27.178100Z

(If you are not sure, that is where the REPL can be handy)

roelof 2021-01-08T21:06:08.178300Z

i think the old value is taken where then the function is applied to

2021-01-08T21:06:26.178500Z

It isn't clear to me what the value of p is in your call above

roelof 2021-01-08T21:06:58.178700Z

sorry, I forget to paste that

roelof 2021-01-08T21:07:02.178900Z

(def p {:name "James" :age 26})

roelof 2021-01-08T21:08:31.179100Z

we solved that one earlier but I try to make it work that it also worked with (def users [{:name "James" :age 26} {:name "John" :age 43}])

2021-01-08T21:08:32.179300Z

So what does (get m ks) return?

roelof 2021-01-08T21:09:03.179500Z

in the example of p it will return 26

2021-01-08T21:09:23.179700Z

Do you prefer to try to figure out why your current function is behaving like it is? Or do you prefer to start with the input/output behavior of the function you want to write, and try to write that?

2021-01-08T21:09:47.179900Z

Now, try eval'ing this in a REPL: (get p [:0]

2021-01-08T21:09:52.180100Z

and see what it returns.

roelof 2021-01-08T21:10:23.180300Z

I think it schould be (get p p: [:0])

roelof 2021-01-08T21:11:13.180500Z

that returns nil

roelof 2021-01-08T21:11:18.180700Z

so not good

2021-01-08T21:11:21.180900Z

Does it make sense why it returns nil?

roelof 2021-01-08T21:12:07.181100Z

yep, I think there is no key named [:0]

2021-01-08T21:12:13.181300Z

correct.

2021-01-08T21:12:48.181500Z

So we can keep looking at what happens with your current function, but maybe you might prefer starting with explaining what function behavior you are hoping to write, because I don't know what that is yet.

2021-01-08T21:13:41.181700Z

You say you want a function that takes a vector of maps like this: (def users [{:name "James" :age 26} {:name "John" :age 43}]) and does something with it, but I'm not sure what you want the behavior to be.

roelof 2021-01-08T21:13:54.181900Z

I was hoping to get first a record from a map so in this example {:name "James" :age 26}

2021-01-08T21:14:19.182100Z

So in Clojure terms, that would be getting the first element from a vector or sequence.

roelof 2021-01-08T21:14:19.182300Z

and then I schould find a way to update what I want to update

2021-01-08T21:14:33.182500Z

The value of users is not a map, but a vector of two elements (each of those elements is a map)

roelof 2021-01-08T21:14:41.182700Z

yep, or the second if I want to update the second entry

2021-01-08T21:15:39.182900Z

So try to explain what the parameters of the function you want are, and see if you can give one or two examples of what you want the return value to be for those example inputs, along with a sentence explaining what the function ought to do.

roelof 2021-01-08T21:16:22.183100Z

oke, in the example of p. Lets say I want to update the age to 45

roelof 2021-01-08T21:16:25.183300Z

Right ?

roelof 2021-01-08T21:16:50.183500Z

then m is still p so {:name "James" :age 26}

2021-01-08T21:16:54.183700Z

So p is a single Clojure map, right, meaning this one: (def p {:name "James" :age 26})

roelof 2021-01-08T21:17:02.183900Z

yep

roelof 2021-01-08T21:17:23.184100Z

I work from that example first

roelof 2021-01-08T21:17:32.184300Z

later we can do more entries

2021-01-08T21:17:36.184500Z

So you wrote my-update-in earlier that could take m, a key k, and a function f, and do inc or add-ten, or whatever function you want, to the current value associated with that key.

2021-01-08T21:17:39.184700Z

That was working.

2021-01-08T21:17:58.184900Z

So now you are saying you want a function that can take a vector of maps, and do something with that.

roelof 2021-01-08T21:18:09.185100Z

yep

2021-01-08T21:18:33.185300Z

My first comment would be: you could write a single function that does both, but maybe given that the first argument is a map in one case, but a vector of maps in the other, maybe a different function might be better.

roelof 2021-01-08T21:18:58.185500Z

oke

roelof 2021-01-08T21:19:09.185700Z

to be sure we are on the same page

2021-01-08T21:19:14.185900Z

i.e. try writing a function that only works if the first argument is a vector of maps, without trying to serve both purposes.

roelof 2021-01-08T21:19:56.186100Z

I want to end at a function that can do this :

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})

(update-in m [:1] assoc :value 1 :active true)

outcome : 

{:1 {:value 1, :active true}, :2 {:value 0, :active false}}

2021-01-08T21:20:06.186300Z

Once you can see both functions on their own, and get them working, then maybe go back and see if it makes sense to try to write some combination of them that can do both behaviors. But I suspect it will only be more confusing to try to write that combined-behavior function first.

roelof 2021-01-08T21:20:33.186500Z

oke, no problem to take one of more steps back

2021-01-08T21:21:37.186700Z

So in this example call (update-in m [:1] assoc :value 1 :active true) you have a vector containing :1. Do you want this proposed update-in function to be able to take any number of keys in that vector, 1 or more? Or do you want it to only work for 1 element in that vector?

2021-01-08T21:22:03.186900Z

If you only want it to work for 1, then why put it in a vector?

roelof 2021-01-08T21:22:05.187100Z

maybe better to make it work with 1 element first

roelof 2021-01-08T21:22:35.187300Z

and then look what needs to be changed for multiple entries in the vector

2021-01-08T21:22:48.187500Z

I guess perhaps from the name update-in, you might be thinking along the lines of how get-in works in Clojure?

2021-01-08T21:23:20.187700Z

Are you familiar with get-in?

roelof 2021-01-08T21:24:28.187900Z

yep, that one is explained in this chapter as Whereas the function get-in` lets you look up values in nested maps, `

2021-01-08T21:25:28.188100Z

So if your update-in is intended to be similar to get-in, in that it can take a vector of keys, and update a value in a nested map, then it makes sense that it should be a vector. In fact, your update-in would likely want to use get-in to get the current value.

roelof 2021-01-08T21:27:57.188300Z

moment

roelof 2021-01-08T21:28:43.188500Z

it does not work as expected :

(def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}})

(get-in m [:1][:active] )
gives
{:value 0, :active false}
I expect to see only false

2021-01-08T21:29:28.188900Z

How many keys to you give to get-in /

2021-01-08T21:29:29.189100Z

?

2021-01-08T21:30:06.189300Z

Oh, I see what you did. That is not how you give a sequence of multiple keys to get-in. Try this: (get-in m [:1 :active])

2021-01-08T21:30:26.189500Z

1 sequence of keys, not multiple separate sequences of keys.

roelof 2021-01-08T21:33:32.190400Z

yep, that works

2021-01-08T21:33:35.190600Z

get-in takes an optional 3rd parameter, that if you give one, and if the sequence of keys you give are not found in the collection, it returns the 3rd parameter to indicate "not found", instead of nil

2021-01-08T21:34:13.190800Z

In this call: (get-in m [:1][:active]) there is a key :1, so the 3rd parameter is not used.

roelof 2021-01-08T21:34:36.191Z

yep, I see it : (get-in m [:3 :active] "not-found")

roelof 2021-01-08T21:34:45.191200Z

gives not found

2021-01-08T21:34:56.191400Z

yep. as it is documented to do.

2021-01-08T21:35:10.191600Z

(once the documentation makes sense, that is 🙂

roelof 2021-01-08T21:35:23.191800Z

yep, and I tried to see if I really understand things

2021-01-08T21:35:47.192Z

experimentation at the REPL with different variations of an idea are definitely good ways to test your understanding.

roelof 2021-01-08T21:36:14.192200Z

yep, I will , can we talk tomorrow about this further

roelof 2021-01-08T21:36:27.192400Z

its late here, 22:36

2021-01-08T21:37:01.192600Z

sure. I will warn you that I expect update-in will be a bit more code to write than my-update you wrote earlier, but doable with patience.

roelof 2021-01-08T21:37:12.192800Z

and I will experiment if I can make it work on a different keyword, so on value and active

2021-01-08T21:38:06.193Z

It is definitely a good idea to have a good understanding of what Clojure built-in functions like get and get-in do, especially when relying on them to write your own functions.

roelof 2021-01-08T21:38:15.193200Z

and then try to adapt it to make it also work on the different entries so the keyword and the number of entries (1 or 2)

roelof 2021-01-08T21:38:49.193400Z

so first understand that

roelof 2021-01-08T21:39:11.193600Z

and then look how I could change a value and make a new map

roelof 2021-01-08T21:39:16.193800Z

thanks for the lessons

roelof 2021-01-08T21:39:41.194Z

you are the first one which do not give a answer but let me think about a solution

roelof 2021-01-08T21:39:45.194200Z

for now GN

2021-01-08T21:41:03.194400Z

It usually takes longer to ask questions that let the learner think about a solution :-)

2021-01-08T21:41:41.194600Z

My hope is that you will learn questions to ask yourself, and habits of thought, that let you more often find the answers yourself.

roelof 2021-01-08T21:45:01.194800Z

and got the code where the number and the keyword is a variable

(defn get-on-keyword [m keyword number]
  (get-in m  [number keyword] "not-found"))

roelof 2021-01-08T21:45:08.195Z

and now really sleep

roelof 2021-01-08T22:29:43.195800Z

Maybe a idea to try now t change the get-in into update-in ? after some sleep naturlly