Fork me on GitHub
#beginners
<
2021-12-21
>
John Bradens00:12:04

I'm getting the error: [:app] Build failure: The required namespace "hiccup.core" is not available,

dpsutton00:12:13

just stay with the 1.0.5 for now. One thing to keep in mind, there’s a library called “hiccup” which has the coordinates on maven “hiccup” “1.0.5”. But that’s not something clojure consumes when it runs. That coordinate is just a bunch of namespaces for our purposes. So when you want to actually use hiccup, you use individual namespaces

dpsutton00:12:32

That is a clojurescript error i think. Hiccup is only available for clojure, not clojurescript

John Bradens00:12:44

Ohhhh I see thanks

John Bradens00:12:34

Ok so if I have a front end web page, like SPA style, and I want to create a link like I described above, how do I go about doing that with clojurescript? I've been able to set up paragraphs and all that, so I thought it was all hiccup 😅

John Bradens00:12:13

[:p "Please check out " [:a {:href "https://www.google.com"} "Google."]

👍 2
mister_m03:12:24

x-posting a question I had in the cider channel - should I be worried about polluting a namespace with function definitions and etc for functions or defs that I have removed from my source file? How can I keep it tidy? Should I? I am making use of comment blocks to give myself a path to reconstruct the program I am working on as I work on it, but restarting a repl to sort of clear the state seems pretty heavy, as does dropping the namespace and reloading it.

Ed10:12:18

I tend to not worry too much about it. I use clj-kondo's static analysis to tell me when something doesn't exist (if I've renamed a function, for example) and I tend to use let more than def in a rich comment block, so I don't end up polluting the namespace all that much.

noisesmith19:12:51

removing vars from one namespace (with ns-unmap) and removing an ns and re-loading (with ns-remove followed by require) are relatively low wieght there is also clojure.tools.refresh that actually removes all your namespaces and reload them (meant for automated editor usage), this led to the creation of stuartsierra/system for automatically recreating initial application state (when you have resources that need initializing during repl development, like db connections)

Pascal Christoph09:12:33

Hi, I am new to clojure, not to java. I have a mixed project, running clojure as frontend with a java dependency as backend. Tried to search but can't find an answer: how to debug clojure's java dependencies in codium (vscode)? I think I have to start the frontend and connect it to the IDE somehow. Is this the proper vscode extension for this: https://github.com/indiejames/vscode-clojure-debug/ ? Using codium, this extension doesn't exist. Has anyone experience using https://github.com/BetterThanTomorrow/calva/ in codium to achieve stepping into java code by invoking clicking around a clojure web app? (I have done this with scala & java (using sbt and eclipse) before. Should be possible with clojure, too?)

pez13:12:51

Calva’s debugger won’t let you step into Java land. I think only Cursive might offer something like that.

Pascal Christoph14:12:01

Many thx for the pointer!

🙏 1
Muhammad Hamza Chippa10:12:11

I have a vector (def x [5 7 8 10 11]) and a bunch of numbers (def numbers [1 2 3 4 5 .. 100]) , how can I extract only numbers x from numbers

Lennart Buit10:12:01

Extract as in remove? (remove (set x) numbers)

Lennart Buit10:12:52

Or otherwise, if you want to keep them if present, (filter (set x) numbers)

Lennart Buit11:12:28

a set when invoked as a function tests whether an item is member of that set. If it is, the element is returned, if it is not, nil is returned instead

Lennart Buit11:12:02

(so; I guess be careful with x containing false or nil, but I’d assumed from your example we are dealing with numbers here)

Muhammad Hamza Chippa11:12:06

basically I have data like [[820540800000 #inst "1996-01-02T00:00:00.000-00:00" 13 13 12.375] [820627200000 #inst "1996-01-03T00:00:00.000-00:00" 12.3334 12.6666 11.9166] [820713600000 #inst "1996-01-04T00:00:00.000-00:00" 11.875 11.9584 10.9584] [820800000000 #inst "1996-01-05T00:00:00.000-00:00" 11.0416 11.25 10.7916] [821059200000 #inst "1996-01-08T00:00:00.000-00:00" 11.2084 11.25 11]] and I want to extract the vector only which contains 820540800000 and 820800000000 (selective filtering)

Lennart Buit11:12:09

(filter (comp (set x) first) items) should then suffice

1
Muhammad Hamza Chippa14:12:06

That works thank you so much

dgr15:12:46

Filtering via sets is one of those Clojure idioms that other languages don’t have and that you find amazingly useful once you grok it.

Muhammad Hamza Chippa15:12:21

brother I implemented that

Muhammad Hamza Chippa15:12:31

but what I wanted to do is much complex than it

Muhammad Hamza Chippa15:12:38

I have matrix something like this `[["19996/28/11" 13 13 12.375] ["1997/28/11" 12.3334 12.6666 11.9166] ["1998/27/11" 11.875 11.9584 10.9584] ["1999/28/11" 11.0416 11.25 10.7916] ["2000/28/11" 11.2084 11.25 11]]` and dates of 11/28 like `["19996/28/11" "19997/28/11" "19998/28/11" "19999/28/11" "2000/28/11" ]` what I want to do if data of 11/28 is found just return the data, but if the data of 11/28 isn't found in the matrix return the data 11/27

Muhammad Hamza Chippa15:12:46

this is what I really want to do

dgr18:12:27

Then you need to dump the data into an array, sort it, and use something like binary search. If you don’t find the item at the end, then back up one item and return that.

dgr18:12:00

BTW, that has nothing to do with Clojure. That’s just basic algorithms.

Jane14:12:05

Whats the issue here?

alexmiller14:12:54

http is no longer supported for maven downloads so you probably need https somewhere

adi15:12:14

@U02RRUT1ALQ Hi, it's hard to see what's going on in that picture. If you are able to use Slack from the computer where you are seeing this error, could you please copy-paste the text of the stacktrace in your Slack message? Also, please describe what you are trying to do. Maybe it's obvious to some from the stack-trace, but other beginners in the channel will benefit from knowing the proper context.

☝️ 1
dpsutton15:12:00

putting these two errors together, it seems like you are using Clojure 1.8.0 and a library that uses Clojure spec which requires minimum Clojure 1.9.0

Muhammad Hamza Chippa15:12:05

I have matrix something like this [["19996/28/11" 13 13 12.375] ["1997/28/11" 12.3334 12.6666 11.9166] ["1998/27/11" 11.875 11.9584 10.9584] ["1999/28/11" 11.0416 11.25 10.7916] ["2000/28/11" 11.2084 11.25 11]] and dates of 11/28 like ["19996/28/11" "19997/28/11" "19998/28/11" "19999/28/11" "2000/28/11" ] what I want to do if data of 11/28 is found just return the data, but if the data of 11/28 isn't found in the matrix return the data 11/27

pavlosmelissinos15:12:06

what have you tried so far?

pavlosmelissinos15:12:16

and also what should be the result for the matrix in your example?

Muhammad Hamza Chippa16:12:44

sharing you the code snippets

pavlosmelissinos16:12:28

Btw your example only contains dates that are 27/11 or 28/11 so it might not be a good case

Muhammad Hamza Chippa16:12:36

it contains many dates

Muhammad Hamza Chippa16:12:45

every date from 1970-2021

Muhammad Hamza Chippa16:12:38

to keep the code clean I just shared the snippet, the case is I wanted to extract the vector containing data of 11/28 if data for 11/28 is not found then return the data of 11/27

Muhammad Hamza Chippa16:12:20

(def dates ["19996/28/11" "19997/28/11" "19998/28/11" "19999/28/11" "2000/28/11" ])

Muhammad Hamza Chippa16:12:33

(for [x data :when (some #(first x) dates)] x)

Muhammad Hamza Chippa16:12:10

I was trying this for loop but it is only returning the data for 11/28 when data of 11/28 is not available I wanted to get data of 11/27

pavlosmelissinos16:12:19

Oh, so 1996/28/11 is in the original data so the code has to return that entry but 1998/28/11 is not in the original data so the code should return the entry for 1998/27/11? (btw you have some extra 9s there)

pavlosmelissinos16:12:57

you need to use a library to parse the string into an actual date

Muhammad Hamza Chippa16:12:12

we have a matrix which contains data of every date from 1996-01-01 to 2021-12-21 and I wanted to extract data of 11/28 for every year like data for 1996-11-28 , 1997-11-28 upto 2021-11-28 but for some years (for example 2004/11/28) data is not available in that case I want data for 2004/11/27

Muhammad Hamza Chippa16:12:32

I am using the actual date using (js/Date. date) I am using the string here for simplicity

pavlosmelissinos16:12:52

I see. That changes the problem statement quite a bit, don't you think? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate Or you could consider using a https://github.com/henryw374/cljc.java-time (it has functions like minus-days and plus-days)

Muhammad Hamza Chippa16:12:56

I know how dates manipulated using higher level libraries, it is basically an iteration problem I have a data and a vector of dates . I want to basically match matrix with vector, if the data is found for 11/28, return it, if not found return the data for 11/27

pavlosmelissinos16:12:29

First of all, "iteration" is doing a single thing many times, so the best thing you can do is reduce the problem to a single item. Solve the problem for a single date and then map the function you wrote over the vector of dates

dgr18:12:04

I put this into another thread, but you should: sort the dates, then binary search the resulting array/vector. If you find the date you want, great. If not, at the last index of your binary search, go backwards one item and that should be what you want. And this has nothing to do with Clojure. It would be the same algorithm in any language. If your array is really short, then just sort it in reverse and linearly search it until you either find the item or a value less than the item you’re looking for.

1
dgr18:12:58

Another way to do this is to put the data into a map with the date as the key. Look up the key in the map. If you find it, great, return the data. If not, decrement the date by one and search for that. If you find it, great. If not, decrement the date by one and search for that. And so on. In that case, you’d probably want to covert all the dates to java.time/LocalDate so the date math was easy.

1
Muhammad Hamza Chippa19:12:28

Map approach looks fine to me this is what I want to be precise and as I mentioned I am using java Dates

dgr19:12:56

The map approach assumes that any gaps between dates are small. It’s effectively a fast initial search using the map, followed by a slow linear search if you don’t find the initial date. If there are lots of large gaps, then you should use the binary search. But if this is something like financial trade data, where you’re just jumping over weekends and holidays, but otherwise every M-F is a trading day, then the map approach will work well.

Muhammad Hamza Chippa20:12:24

most of the gap is small like one day or two day

Muhammad Hamza Chippa20:12:38

and yes it is financial trade data

Muhammad Hamza Chippa20:12:57

your advice just made my day thank you so much brother

👍 1
Daniel Craig18:12:13

How can I inspect an anonymous function to see how many parameters it takes?

alexmiller18:12:15

in general, you should not want to ask that question :)

alexmiller18:12:08

what are you trying to do where you want to ask that?

Daniel Craig18:12:52

I'm using Lacinia, and the pattern there is that you provide a 'resolver map', which is a map of keywords to anonymous functions which your schema can use to resolve fields in a graphql query. So I'm attempting to use a query that I've defined to take 2 arguments, but the resolver function gives me an error which states that I've provided an incorrect number of parameters

Daniel Craig18:12:22

{ "errors": [ { "message": "Exception in resolver for `Query/flightLine': Wrong number of args (3) passed to: neptune-browser-graphql-service.schema/resolver-map/fn--6216", "extensions": { "field-name": "Query/flightLine", "arguments": { "date": "20210909", "flightNumber": 1111 }, "location": { "line": 4, "column": 2 }, "path": [ "flightLine" ] } } ] }

Cora (she/her)18:12:22

can your anonymous functions all take & args and sort it out within the function?

Cora (she/her)18:12:40

then you can call it with whatever number of args and it's fine

Cora (she/her)18:12:57

it's a hack, and not ideal, but it's a thing that might work

hiredman18:12:09

it has been a while, but I believe lacina always passes the same number of args

hiredman18:12:54

the context, the arguements map, the value (those might have different names in the docs, I forget)

Daniel Craig19:12:45

I was able to solve this, thanks for the help!

Daniel Craig19:12:09

my resolver function was expecting the wrong number of params

Daniel Craig19:12:19

and then I had to restart emacs/cider

noisesmith19:12:15

@USDPTD3FY another trick for debugging something like this is to make an argument inspecting version of your function:

(ins)user=> (defn debug-args
              [f]
              (fn [& args]
                (println "arguments to function" f "--" (pr-str args))
                (apply f args)))
#'user/debug-args
(ins)user=> (def str2 (debug-args str))
#'user/str2
(ins)user=> (str2 "a" :b 'c \d)
arguments to function #object[clojure.core$str 0x6a84bc2a [email protected]] -- ("a" :b c \d)
"a:bcd"

Daniel Craig19:12:30

Thanks this is a great idea

noisesmith20:12:11

it's easy to extend this to inspecting return values too, of course - such a simple thing to implement

sheluchin21:12:41

What should be used to perform side-effects on a nested value? Like if you have a list of foos and each one has a list of bars that you want to print? Is putting map inside doseq okay? Does the map then need to be wrapped in a dorun or something?

hiredman21:12:34

(doseq [bars foos bar bars] (println bar))

sheluchin21:12:08

Okay, but what if you also want to print the foo, but only once per set of bars?

hiredman21:12:03

(doseq [bars foos :let [_ (println bars)] bar bars] (println bar))

sheluchin21:12:34

That... looks like it's pushing the boundary a little bit 🙂

hiredman21:12:47

the boundary of what?

sheluchin21:12:00

Side-effecting in the :let is cool?

sheluchin21:12:52

I dunno, intuitively the "binding box" seems like it should be for binding.

sheluchin21:12:13

That wouldn't be considered bad style?

hiredman21:12:58

I am hardly the style police

sheluchin21:12:27

heh well, that's one way to do it. Is that a common approach?

hiredman21:12:30

bindings are two things, a name and a value

hiredman21:12:43

a value is the result of evaluating an expression

hiredman21:12:05

clojure is an impure language so the evaluation of any expression can result in side effects

hiredman21:12:41

_ is a common binding name when you don't care

hiredman21:12:58

I use _ for side effects a fair bit, but more in tests that in production code (where I might have a mix of basically side effecting statements and expressions I need the value of in later assertions)

hiredman21:12:40

if you wanted to implement do as a macro you could do it like (defmacro do [& args] (when (seq args) (let [@(interpose '_ (butlast args))] (last args))))`

sheluchin21:12:25

How do you feel about this alternative?

(doseq [foo [{:id 1 :bars [:a :b]}    
             {:id 2 :bars [:c :d]}]]  
  (prn (:id foo))                     
  (dorun (map #(prn %) (:bars foo)))) 

hiredman21:12:46

whatever you want

hiredman21:12:11

use run! not dorun if you insist on that

sheluchin21:12:47

Is it any worse than your initial suggestion? I'm just a bit confused about the run!, dorun, doall, etc. family.

hiredman21:12:04

dorun and doall are ways to force the realization of lazy-seqs, and they are kind of old school

hiredman21:12:20

these days if you are not going to be dealing with laziness (such that you need to force lazy seqs, and/or are dealing with sideeffects) more often you use some reduce/transducers based approach which side steps lazy seqs all together

hiredman21:12:41

run! is using reduce to process a collection for side effects

sheluchin21:12:58

Hmm, I just watched Rich's talk on transducers yesterday. I kinda get it but still wrapping my head around it. I didn't realize dorun and doall are going out of style. I thought reduce and transduce were simply non-lazy ways of consuming a seq. Transduce being a little more generalized but still..

sheluchin22:12:54

Okay, looking at the docstring for run! again, it's starting to make a bit more sense.

hiredman22:12:18

they often are non-lazy ways of consuming seqs, but at the bottom reduce has some ways to process things other than seqs that can avoid the overhead of allocating seqs, and transducers provide a way of composing processing pipelines that avoid allocating extra layers of lazy-seqs between steps

sheluchin22:12:00

Okay, that gives me enough to think about for now. Thanks @hiredman.