Fork me on GitHub
#clojurescript
<
2016-12-30
>
tcarls00:12:26

Is there a way to have a source file available for (load) from a different ns, but not searched for via the clojurescript compiler directly (but only evaluated when so loaded from something else being compiled)? Context: I have a bunch of shared code which can be built against two different libraries, with two different namespaces providing the same API. My solution to this was to put this code into -shared.cljc and (load "-shared.cljc") from a different namespace requiring each upstream library. In the ClojureScript world which -- while being ugly -- works fine to be able to backend into both compatible Clojure libraries. However, cljsbuild is trying to compile the -shared.cljc on its own, which it isn't designed to do.

tcarls00:12:19

...a way to achieve the same end without being quite so evil would be similarly welcome.

tcarls00:12:44

...well. As an immediate workaround. renaming the file to shared.cljc.inc, and using load-file rather than load.

tcarls01:12:37

...which doesn't actually work. Hrm. I'm at a bit of a loss as to how to get compile-time textual inclusions to work in ClojureScript.

dnolen03:12:15

@tcarls there’s no reliable way to do that - and unlikely to be

kauko06:12:59

@stbgz What do you mean by "non-spa template for Luminus"? Luminus is a template 🙂 If you want to, I imagine you can use it for non-spa sites also, just don't add reagent or anything like that.

kauko06:12:37

lein new luminus foobar +site maybe?

ibarrick12:12:35

Do any of David Nolen's talks compare om/om.next to re-frame directly?

ibarrick12:12:07

I suppose I could tag him.. @dnolen

martinklepsch12:12:17

I don’t think a talk like this exists @ibarrick

dnolen13:12:21

@ibarrick not aware of anything, but om.next isn’t really similar to anything else I’m aware of in ClojureScript

emccue14:12:32

Well from a surface level reading, om.next and reagent are both ways to "use react" in ClojureScript. While not directly comparable, perhaps some sort of dedicated breakdown of the differences in how applications tend to be structured when approaching a problem in om.next versus doing the same in something like re-frame/reagent might be helpful

ibarrick14:12:44

I know they both use react. And my understanding was that they both (re-frame and om.next) store the application state altogether in a single atom/ratom. At first glance (not having written code in either) they both use the idea of single app state that flows down into components and changes travel back up the tree somehow. I was just looking for an easy way to see what the material differences were without getting my hands dirty 😆

tbaldridge14:12:30

@ibarrick reagent uses a ratom (reactive atom) style model. It tracks when you deref an atom and will update a component when that atom changes. Om is more explicit. You send information to a component via params, if the params you send are different the component is re-rendered.

tbaldridge14:12:10

The way the "ratom" dependency tracking is done works 99% of the time, but I've hit some rather nasty bugs with it from time to time.

tbaldridge14:12:34

I aslo recommend looking at Reframe as it covers over some of the more ugly aspects of reagent.

tbaldridge14:12:48

The new version of Om.Next and Reframe are rather comparable in goals but they do have a distinct difference. Om.Next wants you to declare up-front the data your component needs. With Reframe you just take the data out of the global state and it does the tracking for you. So it's the age-old question of "do we be explicit with data deps, or implicit".

pesterhazy14:12:01

In my view, reagent is absolutely reliable, although there are a few gotchas

pesterhazy14:12:39

I also find it rather non-magical

ibarrick15:12:03

I think I like the idea of explicit deps. I work on a very large Ember app and the pain of trying to guess why components aren't rerendering when they should and rendering when they shouldn't isn't something I want to repeat.

ibarrick15:12:35

I suspect persistent data structures mean that even with re-frame there wouldn't be as many gotchas though

ibarrick15:12:43

Thanks for the input!

pesterhazy15:12:56

@ibarrick, @tbaldridge, I've just published a blog post covering some of the gotchas people encounter with Reagent: http://presumably.de/reagent-2.html

scaturr15:12:04

Is there any reason not to use extend-type with native JS types in library code?

scaturr15:12:21

something like (extend-type js/HTMLCanvasElement ....)

scaturr15:12:58

I’m feeling the JS fear of having library code that did things like Object.prototype.myCoolThing = …

dnolen15:12:32

@scaturr it’s usually ok in application code - but not something you should ever do in a library you intend to publish

scaturr15:12:12

Thank you! Would specify! on a specific instance be acceptable?

scaturr15:12:41

Or a better alternative?

dnolen15:12:30

still questionable in a published library

dnolen15:12:36

I don’t know what you mean by alternative

scaturr15:12:17

Likely my understanding that is flawed 🙂 - But I thought of specify! as reify but on a specific instance of something. Like I might be able to create a canvas element that supports a given protocol, and it would not affect other canvas elements.

scaturr15:12:10

Maybe hide behind a factory function of some sort (defn make-canvas [] (specify! (.createElement js/document “canvas”) ....)

dnolen15:12:33

I just don’t know what you are asking

dnolen15:12:39

library code or in your application?

scaturr15:12:59

library code

scaturr15:12:09

would that specify! example be bad to publish for others to use?

dnolen15:12:11

no not a good idea

dnolen15:12:48

I also don’t see what benefit you would be getting out of it anyhow over just regular functions that work on a canvas type

dnolen15:12:06

esp. if you just going to do deal with an individual instance - just write normal code then

scaturr15:12:27

Yeah 🙂 Probably going a little overboard here. Thanks a lot @dnolen - I appreciate the responses a ton

scaturr15:12:35

Still getting my legs here

dnolen15:12:46

consider protocols a special case

dnolen15:12:10

first write some functions, and then decide later if protocols provide some additional abstraction you might need

dnolen15:12:28

based on experience, usually the answer is no - you don’t need them

scaturr15:12:35

that is extremely helpful

dnolen15:12:07

for example - when I might consider protocols

dnolen15:12:21

if I was writing some kind of generic rendering abstraction - where canvas was only one possible type

dnolen15:12:33

and 3D Canvas, or SVG might be other possible implementations

dnolen15:12:43

if you’re not doing that then don’t bother

scaturr15:12:03

That makes sense. I think I was trying to mangle a protocol for use as syntactic sugar

dnolen15:12:54

heh, yeah not intended for that - it’s for abstraction and they aren’t free - there’s a small perf hit over regular functions

scaturr15:12:21

thanks again, i appreciate the help and all you’re doing here

tcarls16:12:39

...okay, taken as given that there isn't likely to be a reliable way to do textual inclusions into a ClojureScript file, but I'd like to understand why that's the case -- my understanding of the compilation model was that macros (evaluated as regular Clojure) could modify the source arbitrary using anything available to Clojure-on-the-JVM, so I'm unclear on why functions pulled in via a macro running something like (clojure.tools.reader/read-string (slurp "shared.clj.inc")) don't have JavaScript generated for them; it feels like my understanding of the compilation model is missing something big.

timgilbert16:12:17

Just curious @dnolen, you’re advising against using extend-type in library code because it has global effects on the JS environment, is that right?

timgilbert16:12:50

Cool, thanks

dnolen16:12:27

@tcarls it just introduces more complications than it’s worth - no deep reason

dnolen16:12:44

and you can write your own macro for inlining source if you really need it

dnolen16:12:13

real I/O ops for this don’t make sense since I/O in JS is async - not true for Clojure

tcarls16:12:12

...but if that slurp is done in a macro, isn't it happening at compile-time in Clojure, vs ClojureScript?

dnolen16:12:58

yes but I already explained why non compile time isn’t going to work in the next statement

dnolen16:12:51

re-reading what you wrote above you may be missing something about how ClojureScript works

dnolen16:12:00

which is that there is no runtime component

dnolen16:12:13

unless you are using optional bootstrapping - no eval

tcarls16:12:12

nod. I don't expect eval, so I don't expect to be able to invoke a macro from figwheel. OTOH, I do expect a function whose text was generated by a macro to be available, and I'm not even seeing that. If that expectation is a wrong one, I'm trying to fix my mental model to understand why it's wrong. (OTOH, if it's a valid assumption and my code's just broken, and the "you won't be able to make that work" was because "that" is fragile, likely to break things, and just generally bad practice... well, then understanding that would avoid the headscratching in trying to bend my mental model around observed behavior).

dnolen16:12:56

@tcarls I think your mental model is just a little off here

dnolen16:12:12

if you want to load code at runtime and expect to see generated source you necessarily require eval

dnolen16:12:38

if you inline code via macro, eval is not necessary

dnolen16:12:09

rewinding a bit - nothing about figwheel prevents invoking a macro (defining a macro is a different story since it can’t be defined in ClojureScript)

dnolen16:12:30

@tcarls going back to what you were saying yesterday - if you use load you have written non-portable Clojure code

dnolen16:12:48

load absolutely necessitates the entire compiler to be present at runtime - and it isn’t in ClojureScript

dnolen16:12:30

if you want to write something portable - don’t use load or any other form of runtime source inclusion

dnolen16:12:43

everything must be declared statically in the ns form

tcarls16:12:04

I think what I didn't grok is that load is always runtime, vs compile-time if invoked root-level as opposed to in a function.

zilvinasu20:12:43

Hey, anyone could suggest some book on ClojureScript ? have some travelling to do, would like to have some additional material to read on Kindle

ewen22:12:11

Hi, when using transit-cljs, I noticed that a lot of things from transit-js don't get removed by the closure compiler. Are things like transitMap used by transit-cljs? If not, is there a way to get it removed by the closure compiler ?

sova-soars-the-sora22:12:55

@zilvinasu Hmm books on CLJS? I can only recommend books on Clojure (The Joy of Clojure being my favorite)... are you looking for something that assumes knowledge of clojure already, or something totally from a fresh perspective?

ejelome22:12:11

I only saw ClojureScript: Up and Running as the cljs book available, but I personally preferred videos (either from O'Reilly or PluralSight, both were actually good) ^ but not actually solves your concern since you said material to read on Kindle.

emccue23:12:56

Clojure for the Brave and True would be my suggestion.