Fork me on GitHub
Dimitri S00:04:47

Hello, can anyone help me understand why this works but a variation does not?

Dimitri S00:04:13

(map #(Integer/parseInt %) ["100" "200" "300"])

Dimitri S00:04:24

That works fine

Dimitri S00:04:27

this does not

Dimitri S00:04:34

(map #(Integer/parseInt %) stringy)

Dimitri S00:04:50

(def stringy ["100" "200" "300"])

Dimitri S00:04:44

when I run the variant, the error I get is "error printing return value (ClassCastException)

Dimitri S00:04:59

java.lang.Long cannot be cast to class java.lang.String


variant should work. are you sure stringy is defined as ["100" "200" "300"] and not, say, [100 200 300]?

Dimitri S00:04:00

(type (stringy 0)) returns java.lang.String


are all the elements strings?


even if one of them is a number parseInt will have trouble

Dimitri S00:04:18

oh damn, you are right

Dimitri S00:04:44

I was tearing my hair out - I had defined stringy in the repl but the last one had no qoutes apparently

Dimitri S00:04:47

because it is a long

Dimitri S00:04:09

hehe derp 🙂

Dimitri S00:04:39

well I'm certainly glad I came here, otherwise I would have continued pulling my hair out


if i do load/load-string how do i know what namespace just got loaded?


note load/load-string might produce multiple namespaces


you could capture the result of (all-ns) before you load anything, then compare the old result with (all-ns) after the load


e.g. (let [prior (set (all-ns))] (load-string "(ns foobar1) (ns foobar2)") (clojure.set/difference (set (all-ns)) prior))


so maybe there is a better way to "discover" what was loaded?


hm, I can't think of a less complex solution. it seems fairly reasonable to discover the side effect of an operation by diffing before and after. I expect it's reliable for most use cases, though given it's an uncommon problem to solve


If i want deep dive into clojure collection processing (map, filter, reduce, etc.) where would be the best place?


I'm aware with, but i want to learn without external libraries

Ivan Koz09:04:27

specter has nothing to do with sequence transformation, i'm not sure where to start with functional abstractions like that. For me it was java streams and common lisp fp course

Ivan Koz09:04:22

then a book maybe? Clojure for the brave and true, programming clojure 3rd ed, joy of clojure 2nd ed


Correct me if i'm wrong but functions like map, filter, reduce, etc can be used for data processing right?

Ivan Koz09:04:56

@pythonjokeun yes, they transform data, in terms of clojure they implemented on top of sequences

Ivan Koz09:04:22

there is also transducers, its more or less the same but transformation and step(iteration) being separated, that's more advanced topic

Ivan Koz09:04:46

its really good and fun introduction into clojure and its abstractions


i've already read that book, but still missing the functional thinking when it comes to complex data structure


Is there any link about transducers?


long story short, i'm a data engineer, heavy user of python pandas, and apache spark dataframe


when it comes to clojure functional data processing i'm totally blank 😂


@nxtk i guess so. anyway thanks for all the links. much appreciated!

Ivan Koz09:04:33

conceptually its all the same across functional languages

Adrian Smith10:04:49

I've clicked file -> new -> project -> deps in cursive and its generated a file with

{:deps {}}
inside but cursive shows me this error:

Adrian Smith10:04:07

I have clojure up to date with

brew upgrade clojure

Adrian Smith10:04:52

both clj and clojure work on the terminal they start a repl with the latest version

Ivan Koz10:04:56

better be asking in #cursive

👍 8

@nxtk if i ask about data transformation stuff in the future, in which channel should i drop my question?

Ivan Koz11:04:59

#beginners #clojure is fine


cool, thanks for the help, much appreciated!

Ivan Koz11:04:34

have fun learning


Is it possible to unwrap the vector of args passed to the add function, namely colls, and pass the contents as arguments to mapv ?


like this? (apply mapv + colls)


(I'm not clear on what add is expected to do)


ya, completely forgot about apply.


if that's the behavior you want, then maybe reduce will cope better with arbitrary numbers of colls


(reduce (partial mapv +) colls)

👍 4

yes, you have to reduce it


Mind to have a look at my question on SO ?


Debugging question: If you have a very complicated function, and somewhere along the pipeline, a function inside that throws an error, is there a handy workflow (that does not involve inserting println everywhere) to see the intermediate input (to that internal function) that caused the error?

Ivan Koz14:04:54


(def test-data
  [{:id 35462, :status :completed, :p 2640000, :i 261600}
   {:id 35462, :status :created, :p 240000, :i 3200}
   {:id 57217, :status :created, :p 470001, :i 48043}
   {:id 57217, :status :completed, :p 1409999, :i 120105}])

(defn merge-tasks
  [[id [{p1 :p i1 :i :as task1}
        {p2 :p i2 :i}]]]
  (if (= (:status task1) :created)
    {:id id :p [p1 p2] :i [i1 i2]}
    {:id id :p [p2 p1] :i [i2 i1]}))

  (into [] (map merge-tasks (group-by :id test-data))))

Ivan Koz14:04:06

most likely it can be done better

Ivan Koz14:04:49

@tabidots as first step to debug a very complex function i would write spec and few tests if needed

Ivan Koz14:04:12

cursive allows for breakpoints, just like java ones

Ivan Koz14:04:12

cider can instrument your function call if i'm correct

Ivan Koz14:04:23

due to functional\\lispy nature of clojure, i find myself barely using debugger if at all


@pythonjokeun Thanks, I had come across trace before but couldn’t figure out how to use it. I just re-installed it in my project and still can’t get it working. I’m getting Can't dynamically bind non-dynamic var:... Is there no convenient way to get a full trace output with a function that already exists?


I like using as an informal way of debugging the insides of functions


just stick a (spy) form around any piece of code and you can retrieve the local context afterwards

Ivan Koz14:04:42

@tabidots var is a static container by default, can't bind it unless it's a dynamic one, but i don't know how to make it so, except def ^:dynamic


How are you using trace?

Ivan Koz14:04:13

with-redefs maybe, should be useful for mocking.


@didibus this is an implementation of the baby-step giant-step algorithm. I have a fn called baby-step-giant-step

(dotrace (baby-step-giant-step 11 7 11))
(dotrace '(baby-step-giant-step 11 7 11))
(trace (baby-step-giant-step 11 7 11))
(dotrace [^:dynamic baby-step-giant-step] (baby-step-giant-step 11 7 11))
(def ^:dynamic bsgs baby-step-giant-step)
(dotrace (bsgs 11 7 11))
(dotrace [bsgs] (bsgs 11 7 11))
These all either don’t work or don’t give me anything (just the same error, with no additional info). The last one gave me TRACE t4135: (bsgs 11 7 11) which isn’t very helpful


I think for fns you have to use deftrace or trace-ns


But it's possible trace is too old. It used to be Vars defaulted to being dynamic. And that changed. Maybe trace wasn't updated till then


On GitHub it says it was last updated late last year


So it should still work, I’d imagine 😕 wish it was a little more intuitive


Did you try changing your defn to baby-step-giant-step to a deftrace?


I have tried

(deftrace [bsgs] (baby-step-giant-step 11 7 11))
(deftrace ^:dynamic (baby-step-giant-step 11 7 11))
(deftrace ^:dynamic '(baby-step-giant-step 11 7 11))
and I just get First argument to def must be a Symbol I have no idea what the dynamic thing is btw, I’m just trying different things to get some result


Do you own the baby-step-giant-step fn? If so, can you change its defn to a deftrace


Not wrap it inside


yes I do. Ok I’ll try that


(deftrace baby-step-giant-step [args] ...)
Like that


So I did

(deftrace ^:dynamic baby-step-giant-step [α β p]...
with the rest of the original function copied from after that point


@nxtk i'm curious on how you approach data transformation problem in clojure :thinking_face:


And that didn't work?


Still not getting too far 😕


Hum... At least that's progress, no error :p

😆 4

is there an official book / guide for "Solving Data Transformation Problem, The Ivan Koz Way" ?

Ivan Koz15:04:23

i don't know

😆 4

@qythium I will give scope-capture a try. It seems a little heavy but if it works then it works


I've never used it myself. But it seems deftrace alone should have done it. Or you need to use trace-ns, that makes it so all fns in a namespace will trace their inputs and outputs.


@qythium scope-capture brings back memories of pre 1.10 stack-traces 🙈 Well, it didn’t specifically tell me what the inputs were at the point where the error occurred, but it did at least pinpoint the source of the error. From there it was easy to figure out. Thanks!


app:threedays.core=> (for [x (range 5)] {:id x})
({:id 0} {:id 1} {:id 2} {:id 3} {:id 4})


i want to achieve this {:x-0 {:id 0} :x-1 {:id 1}...} how can i get my expected result


for will always return a sequence. you want to reduce the sequence to a single map


thank you i'll check out reduce on documentation


there are several ways you could do it, but reduce is the most general and good to know


another common way is to build up a sequence of [key value] vectors and call (into {}) on it


How does one import a record in a different namespace while also requiring functions from that namespace?


You have to use import for records, like with Java interop classes


(ns collijion.core
  (:require [cljfx.api :as fx]
            [collijion.planet :refer [update-planet]])
  (:import [collijion.planet Planet]))
Tried doing this, but I’m getting errors in the repl when I try to eval this ns form


note that if the namespace has dashes in it they have to be replaced by underscores, that tripped me up in the past


@qythium thank you now i made this: (into {} (for [x (range 5)] [:(str "id-" x){:id x}]))


but how can change "id-2" to :id-2


the keyword function turns a string into a keyword


this things started with : i don't know how they are called 😄


they are called keywords


aha their name is keyword right ?


thanks 🙂


☝️ is a good reference when you're first starting out

✔️ 4

oh thank you 🙂 bookmarked


Hi! I'm reading about clojure spec and I see that you can use s/fdef to validate args and your function's return value. You can also use :pre/`:post`. I don't really see when you should use one vs. the other though. Is one more in favor over the other?


I think spec pretty much covers pre/post functionality. Spec came later in Clojure's evolution, so it's probably fair to say that favor is slowly gravitating towards spec/fdef for that. But it's not like pre/post will be deprecated, and you can build a pretty fancy contract system with just pre/post


a spec'd function is only checked if you turn instrumentation on


pre/post is also inlined with function definitions, where as specs can be applied at a later time


you can also spec third-party code


and you can toggle instrumentation on / off with spec


ahhh, i was noticing that i wasn't having errors thrown for an invalid fdef. thanks!


is it typical to turn on instrumentation for dev environments and tests?

Lennart Buit20:04:01

Instrument checks only :args for fdefs, keep that in mind!

👍 4
Lennart Buit20:04:52

That’s the default behavior, there are libraries that add :fn/`:ret` checks ^^

👍 4

Neat! I'll have to look into that


pre/post can be disabled globally too, but spec is moreso designed for that


so is best practice to enable it by default and then disable it globally for prod environments?


For pre/post? I think the intention behind the design was to allow for both options. Some folks might want to use pre/post for runtime validation

👍 4

I don't think you can turn it on or off on a per name space level though, which you can do it spec


another gotcha about fdef and instrument is that if one of the args is a function, multiple representative arg-lists will be generated and provided to that function, which in some cases could have very surprising results

Lennart Buit20:04:18

With side effecting functions you mean?


any function with state, or which does IO


is there a way to get’s with-db-transaction to utilize an existing db connection pool as opposed to a spec? I’ve got a component system with a connection pool already instantiated. starting up another connection from a db-spec over and over again just to perform the same transaction feels unnecessary to me. am I missing something here?


you can use {:datasource p}, it's a valid db spec


that’s exactly what I was looking for. didn’t realize what the syntax was. thanks for the help!


that keyword might be wrong, checking...


I have been running into a lot of can't find class path errors. Has anyone else experienced this issue? I am on Linux.


@sotrhraven Can you provide a bit more context/detail?


Would anyone be able to direct me to some tutorials on web development in Clojure that are high-quality/recent? I've found some tutorials/walk-throughs, but I usually end up getting frustrated 40-60% through, because there's some error or hangup or hiccup (pun intended) that's not mentioned in the tutorial, and generally isn't very google-able if you will, and now I'm left with a bunch of half-baked code, or a half-baked app I can't really move forward with, or debug because I'm still in the trying to learn phase.


I have been using leiningen and nightcode. For example I added compojure to my project.clj and when I use it in my myweb.clj it throws a can't find compojure init class etc.


Did you restart your REPL to pick up the newly added dependency?


Can you share more details of your project.clj and the actual error you are getting? And also exactly when you are getting it?


I could but I have nuked my lein and all associated folders. Going to go with fresh lein install and such. I thought maybe I had set something up. I can provide a project.clj one sec


(defproject myweb "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "" :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" :url ""} :dependencies [[org.clojure/clojure "1.10.0"] [compojure "1.6.1"]] :repl-options {:init-ns myweb.core})


Common problems are typos in the dependency (in project.clj) which would fail when Leiningen tried to download the library or typos in the :require, such as using the artifact name instead of the namespace name.


I was using clojars


Your project.clj looks fine so I suspect the error is in your :require in myweb.core...


(ns myweb.core (:use compojure.core) (:require [compojure.route :as route] [ring.adapter.jetty :as jetty]))


Finding a course I can afford that is not kind of old I am finding difficult. I use udemy, clojure is not a popular topic.


What you have above will produce this error Could not locate ring/adapter/jetty__init.class because you are missing the dependency for the Jetty adapter in Ring.


(so the error is not for Compojure, but for Ring)


add [ring "1.6.1"] as a dependency and it'll work.


(and I can tell you're following an old tutorial because :use is considered bad practice these days)


cool will give it a shot.


will you give this a look I am going to give this a go later. you have been very helpful. you might save me the trouble of getting into this and getting frustrated.


It doesn't use :use here -- it looks nice and up to date. Even uses Clojure 1.10 and Ring 1.7.1. Nice and new.


cool, Thank you. 😊


Looks like the later part of the tutorial is older -- still uses 0.3.x version of org.clojure/java.jdbc so that should all be updated (but it should work as it is -- as long as the code and dependency versions match).


So I will keep an eye on the dependencies matching. I was worried there could have been some name collisions in the .m2 folder that were causing the problem. But this is just better. need to be more vigilant.


I haven't attempted it yet, I've been reading For The True & The Brave/Programming Clojure, but if you think it's worth it, I'll definitely pick it up.