Fork me on GitHub
#beginners
<
2019-04-22
>
dimitri.sokolov2500:04:47

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

dimitri.sokolov2500:04:13

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

dimitri.sokolov2500:04:34

(map #(Integer/parseInt %) stringy)

dimitri.sokolov2500:04:50

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

dimitri.sokolov2500:04:44

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

dimitri.sokolov2500:04:59

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

mail46200:04:19

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

dimitri.sokolov2500:04:00

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

mail46200:04:23

are all the elements strings?

mail46200:04:53

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

dimitri.sokolov2500:04:18

oh damn, you are right

dimitri.sokolov2500:04:44

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

dimitri.sokolov2500:04:47

because it is a long

dimitri.sokolov2500:04:39

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

joel38005:04:30

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

mail46205:04:30

note load/load-string might produce multiple namespaces

mail46205:04:08

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

mail46205:04:38

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

joel38002:04:06

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

mail46205:04:11

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

pythonjokeun09:04:22

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

pythonjokeun09:04:44

I'm aware with https://github.com/nathanmarz/specter, but i want to learn without external libraries

k.i.o09: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

k.i.o09:04:22

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

pythonjokeun09:04:48

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

k.i.o09:04:56

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

k.i.o09:04:22

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

k.i.o09:04:46

its really good and fun introduction into clojure and its abstractions

pythonjokeun09:04:01

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

alexcatalina09:04:09

Is there any link about transducers?

pythonjokeun09:04:04

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

pythonjokeun09:04:21

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

k.i.o09:04:37

@pythonjokeun practice i guess

pythonjokeun09:04:50

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

k.i.o09:04:33

conceptually its all the same across functional languages

sfyire10: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:

sfyire10:04:07

I have clojure up to date with

brew upgrade clojure

sfyire10:04:52

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

k.i.o10:04:56

better be asking in #cursive

pythonjokeun10:04:21

@k.i.o thanks!

pythonjokeun11:04:05

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

k.i.o11:04:59

#beginners #clojure is fine

pythonjokeun11:04:26

cool, thanks for the help, much appreciated!

k.i.o11:04:34

have fun learning

nicholas.jaunsen11:04:40

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

mail46211:04:49

like this? (apply mapv + colls)

mail46211:04:21

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

nicholas.jaunsen11:04:48

ya, completely forgot about apply.

mail46211:04:50

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

mail46211:04:05

(reduce (partial mapv +) colls)

alexcatalina12:04:06

yes, you have to reduce it

pythonjokeun13:04:03

Mind to have a look at my question on SO https://stackoverflow.com/q/55795010/8488828 ?

tabidots14:04:43

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?

k.i.o14:04:54

@pythonjokeun

(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]}))

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

k.i.o14:04:06

most likely it can be done better

k.i.o14:04:49

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

k.i.o14:04:12

cursive allows for breakpoints, just like java ones

k.i.o14:04:12

cider can instrument your function call if i'm correct https://cider.readthedocs.io/en/latest/debugging/

k.i.o14:04:23

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

tabidots14:04:17

@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?

qythium14:04:34

I like using https://github.com/vvvvalvalval/scope-capture as an informal way of debugging the insides of functions

qythium14:04:26

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

k.i.o14: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

didibus14:04:58

How are you using trace?

pythonjokeun14:04:12

@k.i.o thanks again!

k.i.o14:04:13

with-redefs maybe, should be useful for mocking.

k.i.o14:04:20

@pythonjokeun np

tabidots14:04:25

@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

didibus14:04:10

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

didibus14:04:42

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

tabidots14:04:29

On GitHub it says it was last updated late last year

tabidots14:04:54

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

didibus15:04:31

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

tabidots15:04:39

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

didibus15:04:34

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

didibus15:04:38

Not wrap it inside

tabidots15:04:51

yes I do. Ok I’ll try that

didibus15:04:31

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

tabidots15:04:09

So I did

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

pythonjokeun15:04:09

@k.i.o i'm curious on how you approach data transformation problem in clojure 🤔

didibus15:04:27

And that didn't work?

tabidots15:04:50

Still not getting too far 😕

didibus15:04:50

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

pythonjokeun15:04:52

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

k.i.o15:04:23

i don't know

tabidots15:04:13

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

didibus15:04:16

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.

tabidots15:04:03

@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!

m373h4n15:04:41

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

m373h4n15:04:17

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

lilactown15:04:37

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

m373h4n15:04:53

thank you i'll check out reduce on documentation

lilactown15:04:18

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

qythium16:04:39

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

nicholas.jaunsen16:04:09

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

qythium16:04:38

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

nicholas.jaunsen17:04:53

(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

qythium16:04:35

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

m373h4n16:04:54

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

m373h4n16:04:30

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

lilactown16:04:12

the keyword function turns a string into a keyword

m373h4n16:04:24

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

lilactown16:04:40

they are called keywords

m373h4n16:04:46

aha their name is keyword right ?

m373h4n16:04:56

thanks 🙂

lilactown16:04:14

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

m373h4n16:04:48

oh thank you 🙂 bookmarked

dehli20:04:40

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?

john20:04:11

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

noisesmith20:04:20

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

ghadi20:04:22

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

ghadi20:04:30

you can also spec third-party code

ghadi20:04:44

and you can toggle instrumentation on / off with spec

dehli20:04:39

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

dehli20:04:00

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!

lennart.buit20:04:52

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

dehli20:04:33

Neat! I'll have to look into that

john20:04:41

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

dehli20:04:09

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

john20:04:49

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

john21:04:43

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

noisesmith20:04:49

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?

noisesmith20:04:16

any function with state, or which does IO

mss20:04:16

is there a way to get clojure.java.jdbc’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?

noisesmith20:04:53

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

mss21:04:18

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

noisesmith21:04:50

that keyword might be wrong, checking...

sotrhraven21:04:22

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

seancorfield21:04:14

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

lorenzo.evans9421:04:38

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.

sotrhraven21:04:01

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.

seancorfield21:04:58

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

seancorfield21:04:46

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

sotrhraven21:04:21

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

sotrhraven21:04:09

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

seancorfield21:04:36

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.

sotrhraven21:04:29

I was using clojars

seancorfield21:04:10

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

sotrhraven21:04:33

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

sotrhraven21:04:04

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.

seancorfield21:04:58

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.

seancorfield21:04:11

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

seancorfield21:04:58

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

seancorfield21:04:31

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

sotrhraven21:04:57

cool will give it a shot.

sotrhraven21:04:13

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.

seancorfield21:04:13

It doesn't use :use here https://github.com/practicalli/clojure-webapps-example/blob/05-compojure/src/webdev/core.clj#L2-L6 -- it looks nice and up to date. Even uses Clojure 1.10 and Ring 1.7.1. Nice and new.

sotrhraven21:04:21

cool, Thank you. 😊

seancorfield21:04:34

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).

sotrhraven21:04:11

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.

lorenzo.evans9421:04:14

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.