Fork me on GitHub
#hoplon
<
2016-09-26
>
xssive22014:09:07

Hello everyone. I was wondering if there's a catch when one tries to define a macro in a hoplon project.

xssive22014:09:48

I created a macros.core file, the content of which seems to be compiled, e.g. I get different errors when changing the file 🙂

xssive22014:09:09

Can I somehow pretty print the expansion to see what I'm doing wrong?

xssive22014:09:34

else I need to punch in 8 different (defc=.. lines).

xssive22014:09:03

Looks like I can't get even the simplest macro to work

xssive22014:09:38

It claims I'm not using the correct number of args in calling the macro

micha15:09:12

@xssive220 you're familiar with the way clojurescript macros work already?

xssive22015:09:39

Apparently not, since I'm reading up now 🙂

micha15:09:54

ah yeah they're not real lisp macros

micha15:09:59

they're "compiler macros"

micha15:09:11

the macros are not written in clojurescript

micha15:09:23

you write macros in clojure and emit s expressions

micha15:09:43

so you need to make a clojure namespace in which you define macros

xssive22015:09:13

You have an example on github which does something with directories.

xssive22015:09:34

That's clojure as well?

micha15:09:36

so take javelin for example

micha15:09:45

there is the clojurescript namespace, javelin.core

micha15:09:11

so in the javelin project we have :resource-paths #{"src"} in the build.boot file

micha15:09:27

and there is a src/javelin/core.cljs file

micha15:09:31

that's the clojurescript namespace

micha15:09:47

there is also, however, a src/javelin/core.clj file

micha15:09:01

that's where the macros are (like cell=, defc, etc)

micha15:09:32

in the src/javelin/core.cljs file we do (:require-macros [javelin.core])

micha15:09:14

now, when you do (:require [javelin.core]) in your own project you can use both the cljs definitions and the macros

micha15:09:44

perhaps a good thing to look at for inspiration is hoplon.core actually

micha15:09:51

the javelin macros are a little hairy

micha15:09:10

hoplon itself also has macros, simpler ones

xssive22015:09:12

They're basically merged into that same namespace, although of different compiler-origin?

micha15:09:25

the cljs compiler does some shenanigans

xssive22015:09:34

I'll study them then 😉

micha15:09:36

since the compiler is a clojure program itself

micha15:09:14

the compiler macros leverage the similarity of clojure and clojurescript

micha15:09:24

like the same core functions exist in both, more or less

xssive22015:09:42

So I should have no problem creating a macro for complex (defc=..) incantations.. It's just that my (ns..) stuff is probably wrong?

micha15:09:50

so most of the time macro expansion in clojure emits code that can be massaged to work automatically in clojurescript

micha15:09:10

yeah i'd get a simple macro working first

micha15:09:24

just to make sure you have the plumbing set up correctly

xssive22015:09:28

Brilliant... I'll start with a web page on clojurescript macros then, to make sure I get the difference

xssive22015:09:00

I'll do that, thanks... Awesome to be working with something and being able to talk to developers...

micha15:09:15

oh btw, if you're going to be writing macros around javelin cells, do you already know about the formula function?

micha15:09:38

so javelin doesn't really need any macros

micha15:09:51

the cell= macro is just syntax sugar

micha15:09:05

the real work is done by the cell and formula functions

micha15:09:10

for example:

micha15:09:28

(defc= c (+ a b))

micha15:09:40

that expands to something like this:

micha15:09:10

(def c ((formula (fn [x y z] (x y z))) + a b))

micha15:09:57

the idea being that the formula function takes a function as its argument, and returns a formula cell constructor

micha15:09:34

so when you make macros you usually want to deal with the underlying real functions, rather than more macros

micha15:09:45

so that might be helpful for you

xssive22015:09:51

whereas (defc... creates something with (cell... which is similar to an atom

micha15:09:02

yeah and cell is just a function

xssive22015:09:05

That should simplify matters

micha15:09:38

the benefit of working with functions instead of macros is that you're able to use all the lisp things, you can use apply, etc

xssive22015:09:40

I'll study the source then

xssive22015:09:15

Which would be great, because I would want to use the macro with map, which I know to be impossible.

micha15:09:32

yep, totally

xssive22015:09:36

This should help me out 😉

micha15:09:49

if you get stuck we can help 🙂

xssive22015:09:47

Thank you very much... Coming year I intend to make a living out of developing web applications, so I'm studying a lot now

micha15:09:18

great, good luck in your travels 👍

xssive22015:09:42

Thanks again!

flyboarder17:09:30

More hoplon demo’s at this weekends Free Code Camp in YEG! 🙂

keithsparkjoy20:09:11

Curious if anybody has done much SVG work with Hoplon? I’ve had a lot of success getting SVG working but <use> elements aren’t working. They work great if I serialize the HTML document I get from Hoplon into a static HTML file and open it from the file system, so I’m wondering if something about how the page dynamically renders is causing the issue.

flyboarder20:09:46

@keithsparkjoy you will need the hoplon.svg namespace

keithsparkjoy20:09:51

yup, using that

keithsparkjoy20:09:11

I’m going to put a simple repro case up on git in case anybody is interested

keithsparkjoy20:09:23

been pulling my hair out on this one most of the day

flyboarder20:09:48

So it works with prerender then?

keithsparkjoy20:09:13

I’m new to Hoplon - how can I test that?

flyboarder20:09:38

add (prerender) to your boot task

flyboarder20:09:58

like boot hoplon cljs prerender

flyboarder20:09:36

or (comp (hoplon) (cljs) (prerender))

flyboarder20:09:08

prerender just runs the hoplon page through phantomjs

keithsparkjoy20:09:26

Cool I’ll give that a whirl thanks @flyboarder

keithsparkjoy20:09:44

How can I tell if (prerender) is doing anything different? I just added that to my boot dev task, reran boot dev, and I’m not seeing anything different...

keithsparkjoy20:09:24

Ahh I see - need to install phantomjs 🙂

keithsparkjoy20:09:22

Okay I’m getting a flash of what I expect to see with (prerender) although the client scripts seem to still replace all the content a fraction of a second later.

keithsparkjoy20:09:41

So the problem shows up again. But yea, it behaves differently with (prerender).

keithsparkjoy20:09:52

Working on it - will post a link once it’s up

flyboarder21:09:05

@keithsparkjoy yeah for sure an issue with using use

flyboarder21:09:44

@keithsparkjoy I think it’s a problem with the xlink:href attribute, editing your original code in browser (removing the use and then manually adding it) works!

keithsparkjoy21:09:12

Weird stuff, huh

flyboarder21:09:48

I think hoplon thinks there should be a xlink namespace

flyboarder21:09:19

which would be correct since :xlink:href isnt a proper keyword

keithsparkjoy21:09:31

like a Clojure namespace or an XML namespace?

keithsparkjoy21:09:54

It’s weird because Hoplon does render it properly “xlink:href"

flyboarder21:09:49

yeah I think the issue is how it’s rendered, i dont know too much about svg but I imagine we need to implement namespaced keyword differently for XML style attributes

flyboarder21:09:14

like :xlink:href vs :xlink/href

flyboarder21:09:31

is xlink the standard namespace?

keithsparkjoy21:09:02

I think so. I think there’s actually an XML namespace definition for it in the extra dev-related goop that Hoplon puts in the output

keithsparkjoy21:09:33

You know how Hoplon pops up that little icon at the bottom when it detects a change and pulls the HTML resource again?

keithsparkjoy21:09:39

That includes it 🙂

flyboarder21:09:10

thats part of cljs-reload actually, not hoplon

keithsparkjoy21:09:54

Hmm. Is there a way in Hoplon to emit an attribute without using the keyword syntax?

keithsparkjoy21:09:58

maybe I could try that.

flyboarder21:09:03

hoplon just wraps the documentcreate method (well it does other things too :P)

flyboarder21:09:23

sorry createelement

micha21:09:28

yeah there is a someElement.setAttributeNS(...) method

micha21:09:43

i believe that might be what you are looking for?

flyboarder21:09:19

Yeah your document currently doesnt have a namespace prefix for xlink

flyboarder21:09:36

so the elements need to be created with the namespace as well

keithsparkjoy21:09:46

Thanks guys - some ideas for exploration

flyboarder21:09:59

im trying to set the prefix, will report back

keithsparkjoy21:09:40

I think :foo:bar is a valid keyword in Clojure… I dunno - just built a little app with lein new app and ran (prn :xlink:href) and it didn’t choke at least 🙂

micha21:09:17

clojure and clojurescript not the same tho

flyboarder21:09:19

yes because a keyword can be any character

flyboarder21:09:54

ex. (keyword "Hello World") is valid but produces something you cant really use since there is a space

flyboarder21:09:36

oh that threw an error hmm

micha21:09:39

yeah you can do (keyword "") also lol

micha21:09:08

but clojure and cljs often differ in these weird cases

flyboarder21:09:41

@keithsparkjoy try :xmlns:xlink " as part of your html tag

keithsparkjoy21:09:14

No change for me

flyboarder21:09:25

actually that fails for me still, probably because we still arnt using setAttributeNS

keithsparkjoy21:09:38

actually I think it’s supposed to be this

keithsparkjoy21:09:42

let me try that

flyboarder21:09:35

yeah we will need custom attribute handling for these i think

keithsparkjoy21:09:56

I’ll try what Micha suggested to see if that makes any diff

keithsparkjoy21:09:38

maybe I can figure out how to replace the svg/use defelem to deal with this

flyboarder21:09:32

What you probably want is a custom attribute (defmethod hoplon.core/do! :xlink:href [elem kw val] …)

flyboarder21:09:57

then use (as micha suggested) setattributeNS on the elem part of that

keithsparkjoy21:09:13

Cool I’ll explore that.

micha21:09:00

there is also the (defmetho do! :xlink/* ... thing

flyboarder21:09:39

yeah I think we can add something like that to the hoplon.svg namespace once we know it works

flyboarder22:09:17

that was actually much easier than I thought

keithsparkjoy22:09:33

Sweet! I’ll give it a try.

flyboarder22:09:50

just add that to the top of your index page above the html part

keithsparkjoy22:09:53

Thanks guys - you rock 🙂

flyboarder22:09:13

thank micha, he taught me all my hoplon and cljs knowledge 😛

micha22:09:29

haha don't believe it

keithsparkjoy22:09:38

he’s been patient with me so far 🙂

flyboarder22:09:04

I’ll throw something together to fix this for other prefixed keywords

flyboarder22:09:39

@keithsparkjoy here is a version you can use for all the xlink attributes

flyboarder22:09:16

change the attribute in hoplon to :xlink/href or whichever you need

keithsparkjoy22:09:27

Nice clean soln. Will try it out tomorrow :)