Fork me on GitHub
#clojure
<
2016-10-01
>
gfredericks00:10:35

could you show how you want to use the thing?

shdzzl03:10:10

So the reason this doesn't work with an if is because an if must evaluate to a single form. Basically I want something like this:

(if true-or-false
  (wrapping-func arg1 arg2)
  arg1
  arg2)
But that obviously doesn't work.

shdzzl03:10:51

I'm more curious than anything else, I have already resolved this a different way in my own code.

lvh03:10:33

Can I define a ns alias just so that ::x/y will work even though that ns doesn’t really exist so I can’t simply require it?

lvh03:10:09

Phrasing the question that way made me search clojure.core and find alias….

lvh03:10:16

although I suppose alias doesn’t really fix the “ns doesn’t actually exist” part

achesnais05:10:57

@bcbradley Honestly I think the best way to go is for you to go ahead and just build a very basic app and stack overflow/wikidepdia/etc your way through it

achesnais05:10:16

You’ll probs want to start by learning some basic html/css/javascript and learn to make basic pages with those before you dive into the actual http protocol world

jrheard05:10:15

@lvh - :foo/bar works regardless of whether or not foo is a real namespace / whether or not you’ve required it, if that’s helpful information

jrheard05:10:28

i may have misunderstood your question though

danielstockton06:10:07

Trying my luck in here. I understand that fdef-ed functions (clojure.spec) should include the spec in the docstring of the function, but I don't seem to be seeing that. Is there anything special I need to do?

danielstockton07:10:53

Nevermind, it seems like it is a cider issue. At the repl, (doc my.namespace/fn) works.

lxsameer10:10:50

any assets pipeline for clojure ?

Alex Miller (Clojure team)12:10:01

@lvh not yet, although you can use create-ns to do that part separately

gfredericks13:10:42

@shdzzl you're saying that can work if wrapping-func is a macro?

gfredericks13:10:19

@lvh schpec has a function for that

lvh14:10:25

jrheard: Yeah, but I want an alias; ::x/y => ::a.b.c.x/y

lvh14:10:34

gfredericks; Oh, cool!

shdzzl17:10:12

@gfredericks No, in truth it's just unquote splicing that makes it work. But I just associate that with macros I guess. My bad.

shdzzl17:10:27

@gfredericks No, in truth it's just unquote splicing that makes it work. But I just associate that with macros I guess. My bad.

shdzzl17:10:50

Rephrasing my original question: Without unquote splicing, is there a way to replace one form with two or more?

gfredericks18:10:51

@shdzzl no, and that can only work when the surrounding context is a macro. So just changing wrapping-func to a macro doesn't even help.

shdzzl18:10:10

I didn't mean to suggest changing wrapping-func to a macro was a solution. The surrounding context needs to be quoted, yeah. I don't actually need to create a macro to do that though. I can just do something like this:

(def x [arg1 arg2])

(defn decide-for-me [pred inner]
  (if pred
    [(apply wrapping-func inner)]
    inner))

`(~@(decide-for-me some-bool x))

seancorfield18:10:37

if produces a single expression by definition so I can’t even imagine how you’d want to use the result…?

shdzzl18:10:41

I think i confused the issue with my original example, I don't want to actually use if to return two forms, I wanted a good way to conditionally return either one form or two or more forms.

seancorfield18:10:50

Based on your code above why not just do:

(cond->> [arg1 arg2]
  some-bool (apply wrapping-func)
  true vec)

seancorfield18:10:22

Or even (vec (cond->> [arg1 arg2] some-bool (apply wrapping-func)))

shdzzl18:10:58

Doesn't that return a single vector?

seancorfield18:10:11

Hmm, yeah, it’s not quite correct as written…

(cond-> [arg1 arg2]
  some-bool (->> (apply wrapping-func) vector))
I think that more accurately matches your code.

bcbradley18:10:28

how would i require tagsoup?

grzm18:10:29

(:require [pl.danieljanus.tagsoup :as tagsoup]) ?

grzm18:10:49

(require '[pl.danieljanus.tagsoup :as tagsoup]) ? (depending on context)

bcbradley18:10:29

thanks thats what i thought it was

bcbradley18:10:56

keep forgetting nightcode instarepl won't work with 3rd party code correctly

shdzzl18:10:21

@seancorfield That still returns just a single vector doesn't it? Or am I missing something?

seancorfield18:10:57

Your decide-for-me function either returns [(apply wrapping-func inner)] or inner — my code returns the exact same thing...

shdzzl18:10:12

Yeah, I just realised what you meant

seancorfield18:10:30

My earlier attempt tried to turn the result into a vector — which isn’t the same.

seancorfield18:10:23

But my initial question was: what problem are you actually trying to solve?

seancorfield18:10:01

What situation makes you want two expressions in a row (if it isn’t just getting a vector of expressions)?

shdzzl18:10:43

I have already solved my original problem, I just refactored to avoid the situation. But out of curiosity, I was asking about the possibility of replacing a single form with two or more. It appears the answer is unquote splicing or nothing.

seancorfield18:10:26

Is this for an argument list to another function? Why not use apply in the first place?

seancorfield18:10:01

(apply some-func (cond-> [arg1 arg2] some-bool (->> (apply wrapping-func) vector)))

seancorfield18:10:48

or if it’s in the middle of the arg list use (into (cond-> …) [the other arguments]) in there.

seancorfield18:10:37

(I’m coming at this from the position that macros are usually the wrong answer — there’s a right answer with functions first and then maybe some syntactic sugar with a macro later)

bcbradley18:10:11

(defn lispify [html]

  (w/postwalk (fn [e] (if (vector? e) (apply list e) e)) (t/parse html)))

bcbradley18:10:15

I'm having some issues with this code

bcbradley18:10:29

w is clojure.walk, t is pl.danieljanus.tagsoup

bcbradley18:10:12

t/parse returns things that look like [:html {} [:head {} [:title {} "Example Domain"]]]

bcbradley18:10:24

i'm trying to convert all vectors into lists

bcbradley18:10:02

if i do

(w/postwalk (fn [e] (if (vector? e) (apply list e) e)) [:html {} [:head {} [:title {} "Example Domain"]]])

bcbradley18:10:25

I'll get what i expect:

(:html {} (:head {} (:title {} "Example Domain")))

bcbradley18:10:06

But if i try

(lispify "")
i get an error:
ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry  clojure.lang.ATransientMap.conj (ATransientMap.java:44)

bcbradley18:10:12

yet

(t/parse "")
gives me something that looks like
[:html {} [:head {} [:title {} "Example Domain"]]]

bcbradley18:10:18

what could be going wrong?

grzm18:10:06

First thing I'd do is make lispify a true function by refactoring (t/parse html) out.

grzm18:10:54

Something like (defn lispify [html] (w/postwalk ... html)), and then call it like (lispify (t/parse url))

grzm18:10:09

Then you can test lispify without needing to call out to some page somewhere.

grzm18:10:15

At first glance I don't know what might be wrong, but I generally try to split up stuff and simplify when I'm debugging

shdzzl18:10:14

@seancorfield The original context was a wrapping a in Om Next (ClojureScript) that I wanted to apply conditionally. So original code was:

(dom/a #js {:href (:link contact)}
  (dom/span #js {:className (str "typcn " (:icon-class contact))})
  (dom/p nil (:value contact)))
And I wanted to conditionally replace it with just the inner two elements, or:
(dom/span #js {:className (str "typcn " (:icon-class contact))})
(dom/p nil (:value contact)))

shdzzl18:10:27

I didn't use a macro to fix it, I basically just shuffled some things around.

shdzzl19:10:55

Actually pretty close to what you suggested.

shdzzl19:10:15

It does present some other readability problems (because this is basically proxy html), but they're Om Next problems, not Clojure problems.

amacdougall20:10:19

Curious... why does every? have a question mark and some does not? Not a big deal, but I figure there is probably a reason.

ul20:10:31

because some? already exists

ul20:10:05

and some does not return boolean, it returns first truthy predicate application

ul20:10:12

it's even better reason

pesterhazy20:10:15

? signals that every? is a predicate; some isn't a predicate as it returns a value instead of true

amacdougall20:10:36

Ah, for some reason I didn't realize that some? existed and some was a special case, since so much Clojure code uses some when it only cares about the coerced boolean value.

amacdougall20:10:01

Oh strange... some? and some have totally different uses, though. Well, it makes enough sense for now.

bcbradley21:10:45

why does clojure.walk do this?

(clojure.postwalk-demo [:html {:a "b"} ""])
yields
Walked: :html; Walked :a; Walked "b"; Walked [:a "b"]; Walked {:a "b"}; Walked ""; Walked [:html {:a "b"} ""}
Notice the:
Walked: [:a "b"]
and yet there is no such vector in the input

bcbradley21:10:15

I am trying to use clojure.walk to recursively change all vectors in a nested structure into lists

bcbradley21:10:57

But this strange behavior is causing me to receive ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)

gfredericks21:10:20

@bcbradley map entries are vectors

bcbradley21:10:45

So what you are saying is that there is no real way to differentiate between a vector and a map for the purposes of walking through it?

bcbradley21:10:06

In other words, I can't really convert vectors to lists without modifying maps?

gfredericks21:10:30

a map and a vector, yes, a map entry and a vector, not generally; there might be some way of doing what you want though

bcbradley21:10:44

How would you do it?

gfredericks21:10:55

it might be better to back up and ask why you want to do that though

bcbradley21:10:30

long story short I am going to interpret the vector as a list so that I can execute it

bcbradley21:10:58

Its easy to make a list out of a single vector

bcbradley21:10:06

trying to do that recursively is a bit trickier

bcbradley21:10:15

i don't know how to go about doing it if walk won't work for me

gfredericks21:10:35

your data really is recursive?

bcbradley21:10:19

my data is the same as what is generated from clj-tagsoup

gfredericks21:10:30

oh, that's pretty restricted then

bcbradley21:10:59

all i really want to do is convert the vectors into lists

gfredericks21:10:04

does it always have a map as the second element?

bcbradley21:10:20

yes i believe it does

gfredericks21:10:37

and those are the only maps, so you know where they are, and you can write a recursive function to do it

bcbradley22:10:20

hey that looks pretty good

bcbradley22:10:24

i think i'll give it a shot too

gfredericks22:10:39

it does feel like clojure.walk is lacking a little bit here though

bcbradley22:10:02

yeah it just goes to show you that you should test your assumptions

bcbradley22:10:17

i had spent hours on this because I didn't think to consider that walk operated that way with maps

bcbradley22:10:25

i literally tested everything except this

bcbradley22:10:31

then finally tested this

bcbradley23:10:32

if i'm writing a library

bcbradley23:10:37

should i set my clojure dependency to 1.8

bcbradley23:10:42

or should i make it as low as possible?

gfredericks23:10:55

It doesn't generally matter, unless you want to be rigorous about testing with multiple versions, in which case you'll want a fancy profile setup