beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
kozmicluis 2020-11-03T06:51:50.062700Z

This may be the dumbest question ever but, does having both Leiningen and Clojure CLI Tools installed cause any conflicts?

practicalli-john 2020-11-03T14:28:29.070900Z

perfectly sensible question.

dharrigan 2020-11-03T07:21:05.063Z

nope

dharrigan 2020-11-03T07:21:25.063400Z

lots of projects have a project.clj and a deps.edn

practicalli-john 2020-11-03T14:26:58.070700Z

@luishendrix92 deps.edn for Clojure CLI tools and project.clj for Leinignen do not have relationship with each other. I've added a deps.edn configuration to leiningen projects before so I could use Clojure CLI tools instead. It is usually just adding the :dependencies from project.clj to :deps in deps.edn , along with any aliases for tools or paths. One caveat, if the code relies on Leiningen plugins, like lein-ring , which injects code into the codebase to be able to run a server, then you would need to add that code to make Clojure Cli tools work. This might cause a conflict with Leiningnen plugins.

oly 2020-11-03T16:04:27.072800Z

:validate = ( clojure.core/fn [ % ] ( clojure.core/contains? % :condition ) )
I have the above in a hash map, I want to access parts of the value but I get Don't know how to create ISeq from: clojure.lang.Symbol how can i run (last (last (:validate data))) on the above ?

oly 2020-11-03T16:04:51.073200Z

I feel like it should be easy but I am missing something

oly 2020-11-03T16:05:08.073500Z

(last (last '( clojure.core/fn [ % ] ( clojure.core/contains? % :condition ) )))

oly 2020-11-03T16:05:34.074100Z

I figured out that does what I need, it just does not work with the version inside the hash map

dpsutton 2020-11-03T16:07:47.074900Z

lots of quoted stuff going on and a random =. Can you show a bit more concretely what you have? it sounds like you have {:validate (fn [s] (contains? s :condition))} is that true?

oly 2020-11-03T16:08:29.075500Z

yeah that's correct, the equals is from cider inspect πŸ™‚

dpsutton 2020-11-03T16:08:48.075900Z

ok. given this map, what would you like to do?

oly 2020-11-03T16:09:09.076300Z

I am basically after :condition which last last would give me

oly 2020-11-03T16:10:00.077200Z

I understand its because the value is basically a fn just not sure how to make it a list that i can manipulate

dpsutton 2020-11-03T16:10:10.077500Z

in my example i've put the key :validate is mapped to a function and at that point its opaque. You can't get into it

dpsutton 2020-11-03T16:10:16.077700Z

you cannot

oly 2020-11-03T16:10:32.078100Z

oh so regex out the value is my only hope at that point

dpsutton 2020-11-03T16:10:46.078600Z

if you just have a funtion, no, you cannot regex it either

dpsutton 2020-11-03T16:10:57.079100Z

please correct me if you aren't dealing with a function though

oly 2020-11-03T16:11:16.079400Z

okay thanks for clarifying well i can str the function

dpsutton 2020-11-03T16:11:34.079900Z

(str +) -> "clojure.core$_PLUS_@3478c93b"

oly 2020-11-03T16:11:35.080Z

(str (:validate data)) for example

oly 2020-11-03T16:11:55.080800Z

it seems to give me the string version of it

2020-11-03T16:12:11.081Z

it's not though, it's a list

dpsutton 2020-11-03T16:12:13.081300Z

functions are compiled jvm code. they don't have string representations beyond a bit of munged name and an address

dpsutton 2020-11-03T16:12:29.081700Z

you do not have a function then. can you show some example code of how you're making this map?

2020-11-03T16:12:44.081900Z

@dpsutton it's a quoted list

2020-11-03T16:12:55.082200Z

that would be a function if it were evaluated

2020-11-03T16:13:26.082700Z

that's the only way the inspector would show that

alexmiller 2020-11-03T16:13:54.082900Z

clojure.repl/demunge may be useful if demunging class names

oly 2020-11-03T16:14:24.083800Z

it could be a quoted list, but should last not work on a quoted list ?

2020-11-03T16:14:27.083900Z

@oliver.marks what's your goal here? what do you want function shaped lists for?

dpsutton 2020-11-03T16:15:29.085700Z

is this parsing spec output?

oly 2020-11-03T16:15:56.086300Z

yes I am parsing spec, I do know about expound but it's not flexible enough

dpsutton 2020-11-03T16:19:50.086700Z

at my last job we had some clever core.match usage to pattern match on those

oly 2020-11-03T16:22:31.087200Z

so if its a quoted list should I be able to manipulate it / treat it as data

dpsutton 2020-11-03T16:22:37.087400Z

yes

dpsutton 2020-11-03T16:22:53.087700Z

(take 3 (iterate (fn [x] (if (seqable? x) (last x) x)) '( clojure.core/fn [ % ] ( clojure.core/contains? % :condition ) )))
((clojure.core/fn [%] (clojure.core/contains? % :condition))
 (clojure.core/contains? % :condition)
 :condition)

oly 2020-11-03T16:24:21.088600Z

so that works like in the example where its quote '() but when it comes from spec it errors on clojure.lang.Symbol

oly 2020-11-03T16:24:48.089200Z

which is what i don't 100% do i need to run it through another fn first

dpsutton 2020-11-03T16:25:35.090200Z

the error message above is saying it cannot create an ISeq from a Symbol. It sounds like you're calling last on a symbol which obviously can't work

2020-11-03T16:26:16.091Z

there are many function forms that you can't call (comp last last) on without that error

oly 2020-11-03T16:27:40.091700Z

I guess its back to using str and regex then for now πŸ˜•

alexmiller 2020-11-03T16:28:05.092200Z

you could use the spec for fn to s/conform the list representing a function

alexmiller 2020-11-03T16:28:10.092400Z

it will "parse" it for you

alexmiller 2020-11-03T16:30:42.092700Z

user=> (s/conform (:args (s/get-spec `fn)) (rest '(fn [x] (if (seqable? x) (last x) x))))
{:fn-tail [:arity-1 {:params {:params [[:local-symbol x]]}, :body [:body [(if (seqable? x) (last x) x)]]}]}

oly 2020-11-03T16:31:17.093100Z

nice I will give that a try and see what happens πŸ™‚

alexmiller 2020-11-03T16:32:01.094200Z

clojure is doing exactly that to verify the spec for all registered spec macros

oly 2020-11-03T16:33:25.095100Z

it a shame spec errors using (s/keys) does not store the key that's missing in an easier to access format

alexmiller 2020-11-03T16:34:14.096100Z

you can also use spec specs to s/conform a spec :)

alexmiller 2020-11-03T16:35:58.098500Z

https://clojure.atlassian.net/browse/CLJ-2112 has some work on spec specs, although really the map data forms in spec 2 are probably more useful as a future direction

Jim Newton 2020-11-03T16:36:49.099400Z

question about comparing symbols. I have two symbols. I have required [clojure.spec.alpha :as s] into my namespace. But when I try to compare s/and with clojure.spec.alpha/and using = it returns false. Are these really two different symbols? I thought they were the same symbol? I suspect I'm asking the wrong question, but how can I compare s/and to clojure.spec.alpha/and to get true?

alexmiller 2020-11-03T16:38:37.100Z

they are literally different symbols. you could resolve both and see if they refer to the same var

alexmiller 2020-11-03T16:38:57.100600Z

whether s = clojure.spec.alpha depends on your current *ns*

alexmiller 2020-11-03T16:39:06.100800Z

so it's contextual

alexmiller 2020-11-03T16:39:18.101100Z

if I alias s to clojure.string then ...

alexmiller 2020-11-03T16:40:14.101800Z

the namespace object is the one that holds alias mappings and ns is what tells you which namespace object to use for resolution right now

2020-11-03T16:42:02.102900Z

@jimka.issy if this helps, there's a hash-map that the namespace owns, that maps from symbol to var, and the "namespace" part of a namespaced symbol is used to decide which map to look in when resolving

alexmiller 2020-11-03T16:43:57.103300Z

^^ big picture

Jim Newton 2020-11-03T16:45:36.104400Z

This seems to work. I've never used condp before, and I was surprised that I need to quote the clause "tests" ('s/and 's/or), which is not the case with case.

(condp (fn [x y] (= (resolve x) (resolve y))) 'clojure.spec.alpha/and
                        's/and 1
                        's/or 2)

2020-11-03T16:48:47.105Z

case is super weird

alexmiller 2020-11-03T16:49:02.105300Z

case works with compile-time constants. b/c they're constants, they don't need to be evaluated

alexmiller 2020-11-03T16:49:58.106Z

a lot of weirdness in case is due to the special circumstances of the switch bytecode it's trying to leverage

2020-11-03T16:51:57.106500Z

right - there's so many special-case situations for case that don't apply to the rest of clojure

2020-11-03T16:52:20.107100Z

like how it treats lists, and symbols for classes off the top of my head

alexmiller 2020-11-03T16:54:03.107800Z

well, if anyone ever bothered to read the docstring...

2020-11-03T16:54:35.108200Z

I'm not saying the special cases are secret, just that it has a lot of them

Jim Newton 2020-11-03T16:57:44.110300Z

case is normal. Every lisp treats it pretty much the same way. clojure, emacs lisp, scheme, common lisp. No surprises there. That condp looks like case, but acts differently was a surprise. It's clear why the main expression needs to be evaluated, but not yet clear to me why the clauses need to be evaluated. Not exactly clear from the docstring either. At least with a casual reading.

Xavier 2020-11-03T17:19:16.120200Z

Hi all. Newbie here πŸ˜„ I have a spec generator question. I was trying (-> ::expression s/gen g/generate) and I ran into the sample limit issue. ::expression is a recursive spec of simple arithmetic-like calculator with def and if like additions. I have been digging around and it seems my naive use of s/or just makes it worst. I was wondering if anyone has any pointer on how to understand/debug why the generator struggles. (I found s/*recursion-limit* suggestions online, but did not help much). Thanks for your time in advance!

2020-11-03T17:21:53.121200Z

@xllora generators are quite naiive, and if your spec has an arbitrary function to test, it will create random inputs until one passes

2020-11-03T17:22:24.121900Z

usually I'd use a custom generator with the help of things like gen/fmap to create things the spec actually accepts

Xavier 2020-11-03T17:24:58.123700Z

@noisesmith does that mean that the default generator would be generating values for all the leave predicates and then just check if valid?

2020-11-03T17:24:58.123800Z

(fmap helps especially if there's two parts of the input data that have to "agree" in some way)

2020-11-03T17:25:51.125Z

@xllora if I understand what your asking yes, it's not clever

2020-11-03T17:26:18.125900Z

it looks at the types you accept, and creates things that might fit, and uses yours spec to filter

2020-11-03T17:26:39.126800Z

it's not hard to make a spec such that no appropriate example would be created after 1000 tries

2020-11-03T17:27:44.127800Z

especially in your case where it sounds like you are parsing an expression language

Xavier 2020-11-03T17:29:10.128600Z

I see. Then s/or is not actually selecting a branch and expanding it, but both hence making impossible to satisfy? Yes

(s/def ::data-primitives 
  (s/or :number number?                                                                                 
        :symbol symbol?
        :char char?
        :string string?
        :bool boolean?)) 

2020-11-03T17:30:34.128700Z

this two-column output displays very badly in the slack client

Xavier 2020-11-03T17:31:41.129Z

Sorry, jumped the gun accidentally hitting return 😞

πŸ‘ 1
Xavier 2020-11-03T17:32:56.129900Z

Then there is the usual recursive definition on expression around +, -, ... around it

2020-11-03T17:33:10.130Z

I notice from the error message though, it's not ::data-primitives that fails to generate, it's ::expression

2020-11-03T17:33:48.130500Z

yeah, that's your problem, not s/or

2020-11-03T17:34:17.131Z

the error, which you deleted because it was formatted weirdly, was about generating ::expression

Xavier 2020-11-03T17:35:22.131400Z

Execution error (ExceptionInfo) at clojure.test.check.generators/fn (generators.cljc:435).
Couldn't satisfy such-that predicate after 100 tries.

Xavier 2020-11-03T17:38:16.133Z

If I understood your point, your suggested is to check fmap to generate a custom generator for the recursive path. I guess adapted versions of something like https://cs.gmu.edu/~sean/papers/treecreation.pdf

2020-11-03T17:40:47.134200Z

yeah, more specifically you'd use with-gen to attach a custom generator to the spec for ::expression, and inside that use gen/fmap to create sample expressions that would actually pass the spec

2020-11-03T17:41:18.134900Z

the advantage of fmap is it lets you use random generation while still respecting the generator state, so the seed for recreating the failure works

Xavier 2020-11-03T17:42:25.135600Z

Interesting. Thanks @noisesmith. Let me go do some more reading πŸ˜„

ryan echternacht 2020-11-03T19:08:00.137400Z

When I boot up my repl, and eval my β€œmain” namespace (what lein could call core.clj) I’m getting FileNotFoundExceptions on the other files in my project. If I eval those files then everything is fine. any ideas what I may be doing wrong? I think I have the files/namespace mapping correct

ryan echternacht 2020-11-03T19:08:24.137900Z

This project is using deps/clj, not lein

seancorfield 2020-11-03T19:09:10.138500Z

@ryan072 Are there any - or _ in any of the filenames and/or namespaces?

ryan echternacht 2020-11-03T19:09:21.139100Z

- in namespace, _ in files

seancorfield 2020-11-03T19:09:24.139300Z

(also, is this a project we can look at on GitHub?)

ryan echternacht 2020-11-03T19:10:17.140600Z

it is, but private

seancorfield 2020-11-03T19:10:23.140900Z

And when you say "eval my "main" namespace", what exactly do you mean? (require '[my-project.core])

ryan echternacht 2020-11-03T19:10:28.141100Z

yes, that

ryan echternacht 2020-11-03T19:11:00.141900Z

specifically, eval the (ns my-toplevel (:require [ … ]))

seancorfield 2020-11-03T19:12:00.142700Z

If you're on macOS/Linux, could you share what tree . displays when run inside your project, and also what that complete ns form contains?

seancorfield 2020-11-03T19:12:19.143200Z

(it's hard to debug something we can't see πŸ™‚ )

ryan echternacht 2020-11-03T19:12:25.143400Z

for sure

ryan echternacht 2020-11-03T19:12:33.143700Z

(ns yardstick.yardstick-jobs
  (:gen-class)
  (:require [mount.core :as mount]
            [next.jdbc :as jdbc]
            [yardstick.process-channel :as pc]
            [yardstick.fetch-jobs :as fj]))

ryan echternacht 2020-11-03T19:13:19.143800Z

ryan echternacht 2020-11-03T19:13:32.144400Z

I don’t have tree , which is weird because i remember using it in the past

ryan echternacht 2020-11-03T19:14:01.145Z

(ns yardstick.channels
  (:require [clojure.core.async :as async]))
^ one of the other file’s namespace dec

seancorfield 2020-11-03T19:15:07.146100Z

What is the exact FNF exception you're seeing when you try to (require 'yardstick.yardstick-jobs) in the REPL?

seancorfield 2020-11-03T19:15:35.146500Z

(or whatever it is you are typing into the REPL that throws an exception)

ryan echternacht 2020-11-03T19:16:40.146800Z

… and now it works fine

ryan echternacht 2020-11-03T19:18:19.147700Z

whelp, sorry for wasting your time. I recreated the issue like 2x before posting here

ryan echternacht 2020-11-03T19:18:26.147900Z

and now everything is peachy

ryan echternacht 2020-11-03T19:19:18.148900Z

in general tho, if files match the directory structure under src things should be fine, yes?

2020-11-03T19:21:47.149700Z

the actual rule is that the path to the namespace must match a file on classpath or a resource on classpath with a path matching the ns parts

2020-11-03T19:22:13.150Z

src is a classpath root by default

ryan echternacht 2020-11-03T19:22:30.150300Z

makes sense

2020-11-03T19:22:55.150900Z

I find it somewhat surprising that require would give "file not found" as it can use files, or resources inside artifacts, (or even rare things like URLs...)

2020-11-03T19:25:40.152Z

oh, it does say 'FileNotFoundException", wow

user=> (require 'aokldsjflas.asdfkjlasdf)
Execution error (FileNotFoundException) at user/eval290 (REPL:1).
Could not locate aokldsjflas/asdfkjlasdf__init.class, aokldsjflas/asdfkjlasdf.clj or aokldsjflas/asdfkjlasdf.cljc on classpath.

ryan echternacht 2020-11-03T19:31:09.152300Z

That is roughly what I saw

Cas Shun 2020-11-03T20:25:08.155800Z

I'm trying to learn core.async and I'm having somewhat of a difficulty understanding what "parking" is and its implications. (I understand blocking). Could someone provide me a quick overview or some search terms that might help me?

alexmiller 2020-11-03T20:26:48.156500Z

Parking means that no thread is blocked and work stops until data is available

alexmiller 2020-11-03T20:27:30.157400Z

The arrival of data unparks the operation and it is queued to run again

Cas Shun 2020-11-03T20:31:50.158800Z

When something is 'unparked', I assume it waits for the next available thread in the pool?

alexmiller 2020-11-03T20:53:25.159Z

Yes

alexmiller 2020-11-03T20:54:10.160100Z

Which is why go blocks should never do blocking io (which can block a thread in that fixed size pool)

Cas Shun 2020-11-03T20:57:01.160300Z

Thank you Alex