Fork me on GitHub
#beginners
<
2019-11-21
>
solf06:11:18

Is there a more concise syntax for this? :example.ns/foo/bar

noisesmith18:11:56

if you had (alias 'ex 'example.ns) you could then use ::ex/foo/bar but using multiple / in a namespaced keyword is weird

noisesmith18:11:31

to point to a value inside a nested map, consider [::ex/foo :bar]

noisesmith18:11:03

that can be passed to get-in to do the lookup even

solf06:11:07

In this example foo does not refer to anything special, I just would like foo/bar to spec a value in a nested map

MorongÖa08:11:45

I have just added a new library(taoensso/tempura ) to my Clojurescript project. In advanced compilation I get a warning with 'unreachable-code'. Do I need to write an 'extern' for this?

Luke Schubert14:11:36

is there a trivial way to walk a nested object removing all namespaces?

Luke Schubert14:11:32

{:my-ns/a 2 :my-ns/thing {:my-ns/blah 3} :a [{:my-ns/val "a"}]} => {:a 2, :thing {:blah 3}, :a [{:val "a"}]} being an example

Luke Schubert15:11:16

I've attempted using something like (clojure.walk/walk (fn [[k v]] [(-> k name keyword) v]) identity my-obj) but that chokes on any nesting

noisesmith18:11:31

In practice walk should always have a conditional because your fn should do different things for leaves / branches. Also, if your pre or post fn is identity, just use prewalk or postwalk

dpsutton15:11:29

not everything you walk will be a pair like [k v]. usually you can do something like (fn [form] (if (keyword? form) (keyword (name form)) form))

didibus15:11:43

Also you need prewalk or postwalk if you want it to be deeply walked

didibus15:11:52

Like walk isn't recursive

noisesmith18:11:03

walk is recursive, it combines pre and post walks into one function

noisesmith18:11:24

in fact both prewalk and postwalk are defined using walk

didibus19:11:47

No it is not

didibus19:11:24

Unless you call it again yourself in the inner function you pass in. Which is what prewalk and postwalk do.

didibus19:11:25

(walk/walk println identity [1 2 [3 [4 5]]])

1
2
[3 [4 5]]

noisesmith19:11:29

cool, yeah, it only walks the top level input, I misunderstood

👍 4
didibus19:11:22

I was swetting there for a minute 😛 Like was I just not able to understand how the source for walk was recursing hehe, fiew

Luke Schubert15:11:48

oh wow I missed that in the docs

Luke Schubert15:11:01

that was all I needed

Kevin19:11:23

Hi, I created a library (Project A) using lein new libary greetings command. I was wondering if it was possible to require this library as an jar. So I ran lein jar and generated a jar. I placed this jar in a different project (Project B), including it in the :resource-paths . This all works fine. The problem however is when I try adding a dependency to Project A, Project B cannot find it (which is logical). So instead of lein jar I tried the lein uberjar , assuming it would compile all dependencies into a single jar file. Adding this uberjar to Project B makes it crash, sadly. Is it possible to build Project A and its dependencies into a single jar file to be used in Project B?

noisesmith19:11:33

leiningen (and any other maven tool) will look up dependencies recursively

noisesmith19:11:12

if adding a dep to A doesn't make it available in B, you made some other error - making a new jar and restarting with that should make A's new deps available

noisesmith19:11:06

adding an uberjar to B shouldn't make it crash either

Kevin19:11:33

Does that mean it should work with lein jar ? And lein uberjar shouldn’t be necessary?

noisesmith19:11:51

my usual flow is to run lein install in A, then declare B as a dep of A in project.clj

noisesmith19:11:28

perhaps the real issue is that you are trying to manually use the jar, instead of properly doing inter-project dependencies, sorry, I forgot that one would even consider doing that, but of course a beginner would :D

Kevin19:11:09

Haha, yes I’m aware that I’m not using inter-project depedencies. This is a business related issue that I’m trying to solve

noisesmith19:11:17

@kevin.van.rooijen so my previous answer was subtly wrong because I misunderstood what you were doing, the real solution is to add A to B's project.clj, and run lein install which creates a jar for a and puts it in local cache

Kevin19:11:49

Right, but sadly that isn’t an option for me

noisesmith19:11:00

then you need to add all of A's deps to B

Kevin19:11:04

(I would do that too lol)

noisesmith19:11:23

or remove all A's deps from B so the uberjar works

Kevin19:11:25

Ok, so there’s no way to bundle the dependencies somehow? I thought uberjar was supposed to do that

noisesmith19:11:46

the problem is that uberjar now duplicates libs, but doesn't ensure versions match

noisesmith19:11:58

in theory it could work, but that would basically be an accident

Kevin19:11:08

All right

Kevin19:11:20

Sounds like what I’m trying to achieve isn’t possible

noisesmith19:11:41

you could also just add A as an extra classpath element when running B

Kevin19:11:09

Isn’t that was resource-paths does?

noisesmith19:11:13

(that wouldn't work)

Kevin19:11:34

I’d have to also copy A’s dependencies to B’s resource-paths

Kevin19:11:45

If I’m understanding this correctly

noisesmith19:11:46

@kevin.van.rooijen also deps.edn does allow this sort of thing, but then you need to replace all non classpath building features of lein

noisesmith19:11:15

it's likely simplest to merge A+B into a single project, or set up a private maven repo (eg. there's a plugin to treat an s3 bucket as a private maven repo)

Kevin19:11:56

The problem is that Project A is kind of a dynamic thing. And I don’t have control over that

Kevin19:11:13

I could create a create that modifies project B’s project.clj

Kevin19:11:19

But that’s kind of my last resort

Kevin20:11:33

I was just hoping there would be a “just add this jar” solution

Kevin20:11:07

I know it sounds silly but I can’t change B’s project.clj by hand

noisesmith20:11:37

third project that depends on both A and B?

Kevin20:11:27

That’s probably not going to work for my case. I’ll think about this a bit more. Thanks a lot for your help though

johnj20:11:00

What is the type of the keys in the :deps map for deps.edn?

noisesmith20:11:30

I may be misunderstanding your question, but the literal answer is symbols - deps reads the config but doesn't eval, so the symbols are used as data rather than being resolved

noisesmith20:11:40

it internally turns the symbols into strings and parses them to get maven coordinates

noisesmith20:11:52

user=> ((juxt namespace name) 'com.foo/bar-lib)
["com.foo" "bar-lib"]
basically this I assume

johnj20:11:33

yeah, that is want I meant, thanks. so the edn reader is not use to read the config

noisesmith20:11:48

it is used - the edn reader does not resolve symbols

noisesmith20:11:56

it's a reader not a compiler or evaluator

noisesmith20:11:45

(cmd)user=> (clojure.edn/read-string "{foo bar}")
{foo bar}
(ins)user=> (type (first (keys *1)))
clojure.lang.Symbol

johnj20:11:13

ah, thought foo,bar where not valid symbols and it had to be "{'foo 'bar}"

johnj20:11:45

not valid edn I mean

noisesmith20:11:47

they are valid symbols, just not bound, clojure.edn doesn't care if anything is bound

noisesmith20:11:57

it doesn't resolve bindings

johnj20:11:14

yeah, I get how it works now, thanks

johnj20:11:42

is weird to see the return value as {foo bar} though, but I guess is on purpose to be able to pass things that eval at runtime

noisesmith20:11:57

it uses name on lib, then either namespace or name again

noisesmith20:11:30

@lockdown- the point of clojure.edn is to be able to read things without evaluation, without eval a symbol is just a symbol

johnj20:11:49

yeah, I mean after you have read the edn, the key might a function that you later evaluate if you choose too

noisesmith20:11:25

it might point to a function, sure, in this case it's just turned into a string, but using a symbol in the input makes the config syntax less noisey I guess

4
rogerio haruo adachi20:11:16

Hi there, as a begginner Clojure developer I'm trying to understand the concepts behind the framework from James Reeves, Integrant. The video tutorial was available few months ago although seems to be down. Does anyone has a copy of it? Thanx in advance (this URL is down https://skillsmatter.com/skillscasts/9820-enter-integrant-a-micro-framework-for-data-driven-architecture-with-james-reeves)

noisesmith20:11:50

here's something similar behind a paywall https://lambdaisland.com/episodes/integrant

noisesmith20:11:02

@rogerio.adachi I think if you find integrant strange or hard to grasp, it might be helpful to find some of what Stuart Sierra has written about his component library, because integrant is a refinement and attempt to improve his approach while preserving its benefits and functionality

👍 4
johnj20:11:22

@noisesmith do you approve those refinements? 😉

noisesmith20:11:57

haha - I haven't used integrant in anger, I have used component and been annoyed by some of the things integrant claims to fix, but can't personally vouch for it

dpsutton20:11:35

there's a new one that came out too

johnj20:11:40

K, will check them both out

noisesmith20:11:08

@dpsutton if you mean mount, integrant was an attempt to streamline component while avoiding what it considers the mistakes of mount

dpsutton20:11:18

no, i remember seeing one in the last month

dpsutton20:11:22

might have been from juxt

dpsutton20:11:08

and i think the "component" map was more easily querieable

dpsutton20:11:27

yes exactly

johnj20:11:57

command-line-args is passed automatically as an arg to the -main function?

noisesmith21:11:11

in what context? clojure will pass any extra args to your -main if you start your app by specifying an ns with -main

johnj21:11:55

from script, in the CLI, ok

dpsutton21:11:06

clojure.core/*command-line-args*
  A sequence of the supplied command line arguments, or nil if
  none were supplied

dpsutton21:11:25

it sounds like this is a record of what was passed to the main, not what will be passed there

4
noisesmith21:11:50

the data in *command-line-args* will be the same as the args to -main if your app was started in the "normal" way

noisesmith21:11:12

yeah, not sure of the ordering there

noisesmith21:11:34

and since it's guaranteed to be unevaluated strings, the order doesn't really matter

Frank McGeough21:11:06

Hi Clojurians. I've just started learning Clojure and I'm working thru the "Programming Clojure" (3rd edition) book. Got a basic question about the repl. When I start it there are a bunch of functions that are available that are coming from different namespaces (like the functions in clojure.core)... why don't I have to use the namespace to invoke them? That is, I can just do (take-while even? [2 4 6 7 8 10])

henrik22:11:29

You can exclude specific functions if you want to define your own with the same name, eg.

(ns foo.core
  (:refer-clojure :exclude [read]))
Not generally needed, but possible.

👍 4
Frank McGeough18:11:10

Sure. Thank you! Since I'm just getting started its all interesting to me at this point. I realize some of the things (like this) just won't come up in "real" code but I like digging into features a bit until my curiosity is satisfied.

👍 4
johnj21:11:09

the symbols there are automatically mapped for you in the user namespace

Frank McGeough21:11:05

ok, that makes sense. is there some config file that I can use to control what gets loaded/mapped ?

dpsutton21:11:59

all of the functions from clojure.core are automatically in every valid namespace

dpsutton21:11:51

the clojure repl ones (doc, source, dir ...) are in user for you and you can use them elsewhere as you would consume any other ns

johnj21:11:35

@fmcgeough there are many ns manipulation functions

johnj21:11:11

if you do (in-ns 'foo) at the repl you will see clojure.core doesn't get mapped

Frank McGeough21:11:14

huh. yeah I see that. Its very interesting. back to the book ! thank you.

Adrian Smith22:11:34

Are there any options if I want a cross platform catch all in my exceptions? Don't mind using a library for error handling but I don't want some kind of maybe error thing leaking everywhere

Adrian Smith22:11:54

slingshot looked good but cljs support isn't there yet

Adrian Smith22:11:24

suppose I could use reader conditionals for now

noisesmith22:11:00

@sfyire it's been ages since I did cljs, but when I did I just used a conditional that either made a js object (for cljs) or an ex-info (for clj) - oh that's on the throw side, on the catch side I always try to use the most concrete type I can but Object vs. Throwable for those "catch everything" cases via cljc

👍 4
hiredman23:11:24

Js can throw non-Objects, cljs has :default for catching everything

hiredman23:11:25

The core.async go macro for cljs at one time (maybe still?) had a bug where catch couldn't catch certain things because the thrown things would just escape because the machinery because it wasn't general enough about what it caught