This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-30
Channels
- # adventofcode (11)
- # beginners (155)
- # boot (627)
- # cider (64)
- # cljs-dev (110)
- # cljsrn (36)
- # clojure (290)
- # clojure-austin (21)
- # clojure-russia (2)
- # clojure-spec (2)
- # clojure-uk (21)
- # clojurescript (81)
- # code-reviews (2)
- # core-async (33)
- # cursive (6)
- # datomic (9)
- # emacs (1)
- # hoplon (472)
- # instaparse (1)
- # lein-figwheel (4)
- # luminus (9)
- # om (2)
- # protorepl (10)
- # re-frame (10)
- # reagent (48)
- # schema (2)
- # sql (5)
- # untangled (17)
- # vim (1)
- # yada (108)
@mynomoto I am afk (not true, I am away from my other laptop's keyboard), I will as soon as I get home π
@richiardiandrea thanks!
I think I will release SNAPSHOT first, so that folks can try the new split between tasks, how does it sound?
anyone know how I can pass the {:formatter :cljs.test/pprint}
option to the runner in cljs-test ?
@mynomoto deployed boot-cljs-devtools
0.1.3-SNAPSHOT
@richiardiandrea just tested the devtools only branch and it breaks when dirac is not on the classpath. Is this line needed? https://github.com/boot-clj/boot-cljs-devtools/blob/master/src/powerlaces/boot_cljs_devtools.clj#L8
(It seems the alias isn't used anywhere)
Uhm, It used to be need @martinklepsch let me fix it
@martinklepsch do you know if dirac
requires cljs-devtools
on the classpath?
(googling in the meantime)
it looks like it is included as transitive dep: https://github.com/binaryage/dirac/blob/master/project.clj#L26
@richiardiandrea that's a lot of deps haha. Can you let me know when/if you push a new snapshot? Then I'll give it another go. (Or if you're out right now I can also remove that line and push another snapshot)
@martinklepsch I am about to
I am making the assertion of deps more solid as well
if you have some mini-minute you might want to try with/without dirac
and/or cljs-devtools
(three cases really) π
@martinklepsch new 0.1.3-SNAPSHOT
deployed
(make sure you clean your .m2/repository/powerlaces/boot-cljs-devtools
if you notice inconsistencies)
Time for π΄ :sleeping_accommodation: here π
@richiardiandrea tried the following: - only devtools dep: worked - only dirac dep: warning about missing devtools dep - both: worked
(Didn't try actually using the dirac task though, but I guess it's not affected by the dependency assertion stuff)
@martinklepsch thanks a lot I will try with the dirac
task only
I put the assertion in both for coherence π
just a clarification: you can trust clojars[1] about transitive deps brought by the dirac library. In another words, all :scope βtestβ deps in diracβs project.clj do not have effect when bundling dirac library[2] [1] https://clojars.org/binaryage/dirac [2] https://github.com/binaryage/dirac/blob/master/project.clj#L107-L113
@richiardiandrea thanks for the release, I'm removing my manual stuff for cljs-devtools π―
@mynomoto i noticed the problem while working on figwheel and my branch solves that problem too ;)
@mynomoto you mean on-jsload
?
I use something like this:
(ns my.reload)
(defn on-js-reload []
(if (.startsWith js/window.location.pathname "/whatever")
(js/whatever.core.on_js_reload)
(js/something_else.core_js_reload)))
@richiardiandrea I'm really eager for that. Is it a good idea build your branch?
Well, there are three branches to buiud, depends how much tolerant you are ππ
@pesterhazy thanks! If the new stuff is not ready that will help a lot.
The last patch with multi on-jsload is still WIP
I will have time today for that so it is a matter of some patience and many things will not work for sure ππ
@richiardiandrea well I think I can wait a bit more. Being productive beats cool things π @pesterhazy solution will do for now π
Yep I think too π
@darwin thanks! so we basically just assert binaryage/dirac
-> https://github.com/boot-clj/boot-cljs-devtools/blob/master/src/powerlaces/boot_cljs_devtools.clj#L10
@richiardiandrea I'm getting
WARNING: :preloads should only be specified with :none optimizations
WARNING: :preloads should only be specified with :none optimizations
@mynomoto that's the compiler
check boot-cljs
options
yeah true π
the :preloads
feature is supposed to be a :none
thing by design (according to the D.Nolen law π)
yes exacly
sorry I got you
so even if you have :none
it shows the warning right?
could you open an issue by any chance? I will investigate
ok cool, so this can be a problem with boot-cljs
as well, dunno
I would start by opening an issue on boot-cljs-devtools
π
awesome thank you!
so is it true that the actual composition of the middleware functions occurs implicitly for you, via boot?
task and task2 are functions that take some configuration arguments that will be closed over by the middleware function that they each return
however, I didn't specify the order in which these middleware functions should be composed
@bcbradley yes it is like that, order left to right as in trasducers
invoking any middleware returns yet another function, this one takes the fileset as an argument (a map that is constructed by boot), and it is in this function that actual work is usually (not always) done, right?
and because composed middleware is also middleware, after the implicit composition of all middleware from left to right, boot will invoke the completely composed middleware in order to yield a single function that accepts the filset map that boot is responsible for generating, correct?
that's why you can easily compose tasks at the command line the same way as you would do with lisp expressions
I feel like the explanation on github could be a bit better though, I had to go digging for this info
what about the schematic here https://github.com/boot-clj/boot/wiki/Tasks#task-anatomy
http://tailrecursion.com/~alan/index.cgi/doc/tip/documents/2015-04-20_ClojureWestBoot.pdf around slide 12 maybe would be helpful?
by starting with something simpler and then aggregating i mean like this: http://www.braveclojure.com/appendix-b/
however, brave and true still sort of glazes over "why" this is, focusing too much on "how" it is
what is the motivation? Why should we want to compose tasks, why should we want to separate configuration from invocation?
it's important that the configuration of tasks doesn't change once the pipeline has started
i mean boot doesn't just seperate configuration and invocation, it seperates configuration, invocation and composition
because a task should not be able to see the effects of any operation that follows it in the pipeline
so once the tasks are invoked and the middleware formed, those options should not be changed
i guess the way I'd probably write it would be to start with a "bad" way of doing things: making one build per project and explaining / showing why its bad. Then I'd "solve" that by breaking things up into composable pieces, so adding 1 level of abstraction.
Then I'd "show" why that isn't totally great either, and motivate the need for adding another level of abstraction with seperation of composition and invocation
the only reason I was even able to make sense of the source code is because i'm already familiar with transducers
Idk I just feel like everyone who has worked on boot understands implicitly why its "the right way" because they've been shot in the foot by lein
but they aren't explaining why, which makes everyone else scratch their heads about "why 3 levels of abstraction"?
honestly i'm fine with the 3 levels now that I understand why they are needed / what problem they solve
the documentation right now is fantastic for explaining WHAT boot is doing under the hood
its like reading a solution to a math problem without being given the problem itself
and since the jvm and clojure are heavy weight processes we need to leverage incremental builds as much as possible
and we wanted to be able to write small unixlike tasks that can be composed in pipelines like you'd do in the shell
but i can still remember, just earlier this morning, that i didn't know hardly anything about boot
better yet, since boot is architected to separate composition from invocation and configuration,
the idea of the pipeline is based on the assertion that that is a fool's errand and impossible to do correctly
what we are really talking about has nothing to do with auto ordering and has a lot to do with information hiding / abstraction
what we are talking about really, is having a single foo that can be bound to any a, b, c, d, e, whatever
what i'm saying is something like
(deftask foo [sorter & more] (apply comp (sorter more)))
1. the user needs to be able to understand how the machine orders operations, so they can use the tools
2. the user needs to understand how the different operations relate to each other, so they can understand the ordering
3. given 1 and 2, we should cut out the middleman and make it easy for the user to just directly specify the order
because they already need to know all the information that makes the ordering process trivial
So about the order when there are dependencies among middleware I think what yogthos did for Macchiato interesting using metadata: http://yogthos.net/posts/2016-12-20-MacchiatoModules.html
now you not only need to know how to do it yourself, but you need to understand a complicated thing that is completely incidental that was bolted on
also i believe Make is such a system
in that it unifies the objects you want with the objects you already have via a process you specify
if you wanted lein's model, you'd provide some maven repository style total ordering "sorter" processor
the boot philosophy, if there is such a thing, is that the tasks shouldbe small enough to be easily understood by the user
Well I had lots of middleware bugs and if some tool can help avoid that by declaring dependencies I would use it. But in bootland that's a more rare occurrence.
I don't mean automation, only sanity checks if the declared order is know to be wrong.
or that the community as a whole has any way of making sure each task is "simple and small"
that example above is very simple, unless you have something that's going to reorder them
i think if it's difficult to know how to order the task then the tasks are not well designed or documented
so its impossible to automatically order it unless you have some way to encode the user's intention
if there were a way to symbolize user intentions, would it be less complex than a turing complete language or would it have to be turing complete?
like i don't think that boot should be a substitute for understanding what you are doing
cells in a multicellular organism's zygote (a small bundle of cells that eventualy develop into a fetus)
are able to work collaboratively to grow into an organism with a well defined shape and features
yeah i guess if we try to go too far down the rabbit hole programming will start to look less like specifying an exact process and more like selecting a mate for approximate features / "healthy" children / etc
like when i use boot it's basically just some extra work i need to do toget my primary task accomplished
well then i'd just note this: if we are going to pin ourselves to boot's level of abstraction, and not attempt to abstract further
i need to know enough about middlewares to know exactly what they do, why they do it, how they do it, and how that might interact or interfere with other middleware
you can study up on mathematical chaos to learn about nonlinear differential functions
like the middleware continuation thing plus the actual work of compiling or building something
where there is a function that accepts a fileset, does some work, and returns a fileset
i think he means that there might be tasks for which you do the same "kind" of operations in the same order
if there is a side effect that is produced by a middleware, and another middleware came before it but depends on that side effect
if a user wants to produce side effects based on the values in those maps, then he can do it himself
and you shouldn't have middleware that does that and does something else, like modify the map
i think there should be tasks that just read the fileset and return a new one (for the next handler)
you know it occurs to me there is a way to introduce purity even for middleware that does what you just said, and without duplicating the classpath
but they do it in a very organized fashion so that it looks immutable on the outside
the benefits that you gain are that you can't have a task "overwrite" the effects of a previous task
it would believe that there was some kind of statefulness going on, because it can't see the old map
however, anyone who dependend on the old map, and who doesn't want to be run over by "statefulness" still can
meaning an immutable fileset object that corresponds exactly to the state of the filesystem at this moment in time
does the fileset contain references to files, or does it actually contain the information that was in the filesystem (a copy)
the way it works is whenever you add a file to a fileset, like (add-resource fileset some-dir)
the filename in there is generated from a md5 hash of the contents plus the lastmod time
i would expect so, since the cpu cache is never invalidated as the information is immutable
when the cpu cache is invalidated it means it has to use the bus to reload into the cache from main memory the "new stuff"
if you just write once and read a bunch rather than write a bunch and read a bunch you are going to get some stupid high speeds
overwriting is only going to be worse than writing if you could avoid overwriting entirely
maybe in-memory vs ssd is a small difference, as i think ssds have pretty fancy caching and onboard memory for it
especially since tasks are deterministically regenerating the same things over and over
i'm also glad you didn't go down the rabbit hole of trying to do too much for the user
even though it means the burden is on the user to understand the semantics of the tasks he uses
i guess in the end he can't avoid it, he can only fool himself into thinking he's avoiding it, when really the complexity is transduced (as in energy) into a different place or form
i think there is something in information theory that says there is a certain amount of complexity in any given system that cannot be destroyed, but its form can be changed
trying to do things for the user (as with lein / maven) just splits up the complexity into a dozen pieces and makes it harder to understand
if you go with boot's approach its all in one spot and doesn't infect anything else
seems an awful lot like the principle of thermodynamics that says that thermal energy in a closed system cannot decrease
only thing i'd like to say is that if the boot community is really committed to helping eachother make simple, small tasks, then the official documentation needs to include a treatise on the motivation for separating composition from invocation from configuration
the more concrete you make it, the more likely the community is to produce "good" tasks
it's good to have the live reload and the cljs repl and so on be different separate tasks
what i mean is boot is a way of compiling clojure code, you have build.boot written in clojure and it runs on the jvm
pods are important for making small tasks because with lots of small tasks you would get terrible dependency hell if they all lived in the same clojure runtime
what if you had another version of boot for parsing a build.boot that is written in clojurescript
that way you could theoretically have the node.js boot invoke the jvm boot (or the more regular approach which is vice versa)
because it means clojurescript isn't sort of "bolted" on to the current incarnation of boot (which itself depends on jvm)
if you have boot the way it is currently you need to depend on clojure (and have a jvm)
if you do it the way I'm suggesting, you don't need to have any jvm or dependon clojure
for the same reason, if you wanted to run boot within boot, the clarity of what is going on increases
Hello again my knowledgeable friends π I have been trying to resolve this issue without any success.. I am hoping someone could help me figure it out: (basically, it looks like classloader related issue) I have a namespace with gen-class which extends a class from library (jnr-fuse, which uses jnr-ffi library). all the required libraries are listed in dependencies. When i run repl using boot, - i can import my generated class which extends the library, - i can instantiate the class which i am extending as well - but when i try to instantiate my class (generated), it throws ClassNotFound and NoClassDefFound exceptions
java.lang.ClassNotFoundException: jnr.ffi.provider.jffi.NativeClosureProxy
java.lang.NoClassDefFoundError: jnr/ffi/provider/jffi/NativeClosureProxy
java.lang.RuntimeException: java.lang.NoClassDefFoundError: jnr/ffi/provider/jffi/NativeClosureProxy
Now, today I tried to conver the project to leiningen project, and ran the same exact project in lein repl
and i can instantiate my class just fine. How do i work and fix this issue? I feel like this is because of different classloader for compiling and running the classes, but i was assuming both would have access to the classpath and would have no problem loading the classes found in the :dependencies
@micha this is the class failing to load https://github.com/jnr/jnr-ffi/blob/master/src/main/java/jnr/ffi/provider/jffi/NativeClosureProxy.java#L44
@micha may be it is because of this issue: https://github.com/jnr/jnr-ffi/issues/51
i think native libraries is one case where the system classloader is maybe the right way to go?
@bcbradley there is an attempt to build a clojure build tool in node.js here: https://github.com/eginez/huckleberry
it is almost a clean slate now and might be worth pitching some idea there too, the author is always on #cljs-node. About the JVM vs Node thing, we cannot have a fair comparison until we actually build boot
in node in terms of speed.
I have noticed myself that what really triggers my frustration is when I try to execute boot tasks a-la-carte (), so basically when I need a (bash?) script instead of spinning up a JVM and pay for its startup time
if you (like me) still want to be able to use cljs while scripting then I am going to suggest planck
or lumo
no startup cost upfront
I hear you, I had exactly the same problem yesterday, where my boot-reload
needed to know cljs options before boot-cljs
runs
but you can get around that
if you want to convert clojurescript files into javascript files, it seems like that should be a thing tantamount to boot itself
without that you just have some collection of compiler options that mean nothing other than implementation details
it is more powerful than a pom.xml
actually, because you can change it at boot
runtime
is it responsible for converting #{clojure, clojurescript, whatever, whatever, whatever} to {stuff stuf stuf stuf}
and i certainly don't think boot should try to take on the goal of being able to convert arbitrary A into arbitrary B
@micha there is a stale
directory in the target
directory, which has a file named: leiningen.core.classpath.extract-native-dependencies
and following content:
what happens if you do like find . -name 'libjffi-*.so'
in the project dir after running lein repl
@micha, does boot use context class loader for isolating and loading the dependency classes at run time?
this might be the issue: https://github.com/puniverse/javafs/issues/8
OOps sorry this is the root cause: https://github.com/jnr/jnr-ffi/issues/51