Fork me on GitHub
#clojure
<
2017-08-11
>
qqq00:08:23

hmm, is the clojure solution to hygeinic macros as follows: 1. if all vars had full path, we wouldn't have hygiene problems 2. thus `(... ) automatically adds the namesapce to any symbol

mobileink03:08:43

what does 1. mean? vars are already fully qualified. an fqn is still just a,name.

mobileink03:08:53

merely adding an ns does not solve the problem?

qqq03:08:01

(defmacro not-working [x y z] (list 'list x y z)) (let [list "hello world"] (not-working-fun 2 3 4)) ==> compile time error /// $&*@($#& (defmacro working [x y z] (list 'clojure.core/list x y z)) ==> okay, it no longer calls the local env list

mobileink03:08:55

not-working or not-working-fn? i cannot parse ur code.

qqq03:08:15

sorry, not-working

qqq03:08:54

these are terrible variable names; I deserve an award of some kind

mobileink03:08:54

try some macro-expand magic.

qqq03:08:09

the point is this: if we want `(list x y ~z) to do the right thing, we need list to be bound when macro is DEFINED, not when macro is USED

noisesmith02:08:25

@qqq that sounds pretty close to it, yeah - I wouldn't call it hygiene, but it's a lot safer than the approach in CL or elisp macros

skaplan03:08:00

I'm using pipeline-async and curious what the best way to handle errors is. Right now, if the function throws then it gets swallowed and goes no where. Separately, is there a better way of processing a queue than using pipeline-async?

noisesmith03:08:38

@skaplan have you tried providing the error-handler arg to the chan you pass in?

noisesmith03:08:08

oddly, I tried to test that but with my core.async version the exception shows up at the top level where I started the pipeline-async and doesn't reach the channel error handlers

noisesmith03:08:46

of course, you can just try/catch in your af

skaplan04:08:21

It seems that chan's error-handler is only for transduction

skaplan04:08:17

I want the error to stop the pipeline. What's the best way to do that if i try catch in the af?

noisesmith04:08:01

I wonder - one way would to be have a delay or promise which is realized in a catch block, and bail if it is realized in the af

noisesmith04:08:08

that feels hackish though

lmergen07:08:46

hmm does anyone know whether it’s possible to forward-declare a namespace for sole purpose of using namespaced keywords under an alias ?

lmergen07:08:20

e.g. being able to use ::foo/my-key without having to (:require [my.very.long.ns.foo :as foo])

lmergen07:08:05

i was thinking about using declare and alias, but i’m not sure whether that’s the best approach

juhoteperi07:08:05

@lmergen You could use foo as namespace instead of alias: :foo/key

lmergen07:08:46

@juhoteperi but then i would have to use :my.very.long.ns.foo/key, right ?

juhoteperi07:08:31

why do you need long ns if the ns doesn't really exist?

lmergen07:08:13

the namespace does exist

lmergen07:08:22

i think i’m misunderstanding something

juhoteperi07:08:43

Ah no, I somehow misread the question

juhoteperi07:08:20

I somehow jumped to conclusion that the ns doesn't exists as you don't want to use require

lmergen07:08:25

aha, no, the namespace does exist

lmergen07:08:52

i figured that if i’m able to just literally type the long-ns keyword and have things work, then i wouldn’t have to require the module either

lmergen07:08:50

aha, just doing (alias 'foo 'my.very.long.ns.foo) does the trick, no forward declarations necessary

misha08:08:46

@lmergen this will not require file to exist:

(create-ns 'my.very.long.ns.foo)
(alias 'foo 'my.very.long.ns.foo)

lmergen08:08:11

@misha thanks, that’s exactly what i was looking for!

misha08:08:38

I tend to have a bunch of those in ns with all the specs.

andrea.crotti08:08:18

so I was thinking that instead of trying to serve static files with Ring/Pedestal/whatever directly I could just push them to S3

andrea.crotti08:08:24

which seems like a standard thing to do

andrea.crotti08:08:38

the only non deprecated/maintained thing I found about this is amazonica though

andrea.crotti08:08:53

I don't really need the library for the whole S3 to just push some files to S3

andrea.crotti08:08:03

what do you guys use for that?

yonatanel09:08:06

I use the java api directly when it's not too horrible

yonatanel09:08:46

This doesn't seem too bad:

(-> (AmazonS3ClientBuilder/defaultClient)
        (.getObject bucket key)
        (.getObjectContent))

misha09:08:49

am I doing multiarity macro right?

(defmacro or-based-coerce
  ([spec-name triples] `(or-based-coerse ~spec-name (constantly nil) ~triples))  ;;<= this bit specifically
  ([spec-name default-coerce-fn triples] ...)

yonatanel09:08:41

@misha I don't know, but I'm interested in what you're trying to achieve

misha09:08:59

the actual macro's purpose?

misha09:08:07

or the multiarity bit?

misha09:08:37

I want to avoid manually duplicating s/ors dispatch keywords in a coerce function

misha09:08:08

Trying register or spec, and create coerce function at the same time by providing [dispatch-key predicate coerse-fn] triples

misha09:08:52

@yonatanel here's an example of the actual thing I am trying to address https://clojurians.slack.com/archives/C1B1BB2Q3/p1502377408579283

misha09:08:50

does it do something like "s/nonconforming"? Then no. I want or branches, I just don't want to keep spec and coerce function in sync manually

misha09:08:20

will see whether it even worth it or not

yonatanel09:08:21

I see now. Any reason not to s/and spec and coerce on each branch?

misha09:08:07

in case above – I need to have executable-id and executable as a separate specs, so the coercion needs to be separate from executable-id.

misha09:08:35

but in general I'd use nested s/ands

misha09:08:26

I might be framing macro's purpose wrong, actually, since coerce fn in my example uses 2 different specs for validation, and coerces in-between. Macro as I write it now would stop after coercion, and I'd need to validate against the second spec "manually" afterwards. Which renders whole effort sort of useless :)

mitchelkuijpers12:08:09

Are there any zprint gurus who know how I can make this:

(atlaskit/label #js
                                  {:label "Search" :htmlFor "hipchat-search" :isLabelHidden true})
format like this
(atlaskit/label #js {:label "Search" :htmlFor "hipchat-search" :isLabelHidden true})

mitchelkuijpers12:08:38

I basically want to force the thing after #js to always be on the same line

plexus13:08:47

Anyone have an implementation of ?-> and ?->> lying around that I could borrow? (thread but stop threading when any intermediate value is nil)

plexus13:08:15

I'm sure some of the utility libs must have these but seems http://crossclj.info is down and these are a bit tricky to google 🙂

danielneal13:08:01

I think some-> does that

danielneal13:08:18

how to use clojure bot 🙃

plexus13:08:21

oh, right. thanks for the reminder!

danielneal13:08:11

lol we can do this

plexus13:08:52

ok I give up 🙂

plexus13:08:05

ok this last one is definitely supposed to work.... computers picard-facepalm

danielneal13:08:09

works on my machine 😛

noisesmith13:08:24

yet another bug in the bot (it also treats strings as if they were symbols)

qqq16:08:02

(this is clojure runtime, not source code) suppose I have ;; foo/bar.clj (ns foo.bar) (def xyz 20) ;; some other file (def my-var-name 'foo.bar/xyz) (???? my-var-name) ==> 20 what do I put in ???? to "resolve" the var ?

bfabry16:08:57

@qqq I think that's going to be a 2 step process. you need something to load the file and something to resolve the var

qqq16:08:21

that's fine; is there sample code I can copy/paste ?

qqq16:08:56

clojure.core/resolve + clojure.core/ns-resolve ?

bfabry16:08:56

(do (require '[foo.bar]) (var-get (resolve 'foo.bar/xyz)) should do it

qqq17:08:26

hmm, I tried (ns-resolve ns-sym hiccup-var) // got the var instead (var-get (ns-resolve ns-sym hiccup-var)) // worked [ there was a require executed earlier ]

qqq17:08:46

so you had the var-get .. and it turns out I also need it, is the problem resolve returns a "VARIABLE CONTAINER" but not the actual value ?

bfabry17:08:47

yeah a var is not the value, the var is the container, you can get the value from the container 🙂

qqq17:08:58

cool; thanks

noisesmith17:08:30

a subtlety about ns-resolve - people assume it means "get this symbol which is defined in this ns" it actually means "look up this symbol as if we were currently in this ns" - subtle but sometimes significant

mobileink18:08:46

what happens if SYM is interned more than once, e.g. foo/x and bar/x?

noisesmith18:08:45

intern throws errors for this kind of thing - which is why we need refer-clojure clauses if we want to reuse those names

noisesmith18:08:00

ns-resolve only looks up in the target ns

mobileink18:08:29

suppose the target ns requires both foo and bar but does not itself intern x?

noisesmith18:08:46

you have to give ns-resolve the symbol to look up - and the semantics of intern and namespace definition ensure that this symbol can only be resolved to one var

noisesmith18:08:04

mind you this can be a namespaced symbol (and must be if they didn't use refer or use)

noisesmith17:08:46

but if you know the precise ns and symbol, you can just use resolve

qqq17:08:55

@noisesmith : I don't get the subtlety. What is a scenario where it differs from what I would expect ?

bfabry17:08:13

my guess is aliases?

bronsa17:08:24

it means that the namespace of the var returned from ns-resolve doesn't have to be the ns used in ns-resolve

noisesmith17:08:38

@qqq (ns-resolve 'my.ns '+) returns #'clojure.core/+

bronsa17:08:50

ns-resolve vs ns-interns

noisesmith17:08:51

(unless you didn't refer clojure.core in my.ns of course)

noisesmith17:08:18

usually this doesn't matter, but the difference is worth noting

bfabry17:08:12

user=> (ns foo.bar)
nil
foo.bar=> (def x 20)
#'foo.bar/x
foo.bar=> (ns foo.baz)
nil
foo.baz=> (alias 'bar 'foo.bar)
nil
foo.baz=> (ns foo.bash)
nil
foo.bash=> (ns-resolve 'foo.baz 'bar/x)
#'foo.bar/x

qqq17:08:24

(ns-resolve NS SYM) if SYM is defined in NS, return NS/SYM if SYM is NOT defined in NS, look at the use/requires of NS, and return whatever one would get by resolving SYM in NS ^^-- is that correct ? I guess the two above cases does simplify to "resolve SYM as if it was in NS"

bfabry17:08:42

oh yeah, things pulled in from core or use that could be quite confusing

Alex Miller (Clojure team)18:08:06

in the context of a namespace, a symbol can have only one binding

Alex Miller (Clojure team)18:08:02

a bare symbol that is. you can have many aliased or unaliased ways to refer to a symbol though.

Alex Miller (Clojure team)18:08:52

so x can mean only one thing given a namespace context

Alex Miller (Clojure team)18:08:11

fully-qualified symbols are always valid (assuming the namespace has been loaded)

Alex Miller (Clojure team)18:08:31

aliased symbols depend on the current namespace context

noisesmith18:08:56

and this is why I mention using resolve if you know the exact ns and var name - it doesn't have any of those extra concerns ns-resolve does about some other ns' aliases

mobileink19:08:58

to take the example @noisesmith gave: (ns-resolve 'my.ns '+) returns #'clojure.core/+. what if my.ns requires foo, which also defines +?

noisesmith19:08:21

then you can only get it via the alias foo has

mobileink19:08:27

i'm missing sth here.

noisesmith19:08:32

and you you tried to do (use 'foo) you would have gotten an error

noisesmith19:08:01

if you had (require '[bar.foo :as foo]) you would look up 'foo/+

noisesmith19:08:22

+ would return clojure.core/+, foo/+ would find foo+, just like if you were in the ns

noisesmith19:08:58

so the full call would be (ns-resolve 'my.ns 'foo/+)

mobileink19:08:03

suppose no alias, :refer :all. then you'd get foo/+?

noisesmith19:08:28

you'd get a compiler error on the refer all

noisesmith19:08:41

unless you used refer-clojure to exclude +, then sure, yeah

mobileink19:08:44

my my, that is subtle indeed. resolve SYM as interned in NS, not as defined by NS?

mobileink19:08:37

or: resolve within rather than for NS.

mobileink19:08:23

thanks, i did not know that. i just can't wait for all my ns-resolve code to break.

mobileink19:08:42

maybe a documentation jira is in order for this?

noisesmith19:08:05

the docs for ns-resolve are correct, people just misread or don't understand the implications or even more often don't read it and make some assumptions based on the name

noisesmith19:08:20

there's clojuredocs which accepts submissions though

mobileink19:08:47

@noisesmith disagree. in the docs "resolve" is undefined, so "resolved in a namespace" (from ns-resolve) is ambiguous. the docs for ns-resolvee' and resolve` are circular.