Leiningen gets messy when trying to define complicated build paths combining Clojure, ClojureScript and possibly multiple artefacts, CSS compilations etc in one build process/configuration file.
Since Clojure 1.7.0 there can be support for multiple platforms in one codebase through cljc-files. This is awesome but must be leveraged.
Boot solves a lot of these problems by composing builds just like ordinary functions. To overcome problems with mutable file systems, boot uses an immutable file system called Filesets. Very clever.
I'm investigating wheter a semi-complex build process would benefit from moving from two repos containing a backend server and an administration client respectively.
I found out that there's no selective auto-reloading of code like in the amazing Figwheel. This limits the usability of boot for doing rich web app development at the moment. I'm sure this will change very soon.
I'll stick with Leiningen for some more, but keeps my eyes wide open for improvements in the Boot project.
Multimethods
torsdag 6 augusti 2015
söndag 5 april 2015
Terse explanation of re-frame
Re-frame is an single page web app event-loop machinery built on Reagent/React.js.
Application state app-db is stored in one (1) reagent atom.
By using reagent's reactions, one can build up a graph, chained reactions, where more costly operations can be "shielded" behind reactions which wont report a change if the reactions view from a new app-db is the same immutable data structure as it was in the previous app-db.
The redrawing of the DOM/screen is triggered by requestAnimationFrame. Given a standard refresh rate of 60 Hz, this trigger will occur every 16.67 ms, if the program is done with it's previous recalculation by then.
Re-frame uses hiccup-style syntax feed to the Reacts Virtual DOM.
There can be several related reagent atom-constructs called reactions, containing derived state ("views") of the app-state.
To make state changes in the application, initialization code or callback functions from event-emitters like the DOM, timers, network connections should send dispatch messages. These are put in a core.async channel and handled by registered handlers.
There's two special types of dispatch, dispatch-sync which handles the event directly, and does not put it in the core.async channel. The other special dispatch is putting ^:flush-dom metadata on the dispatched event, which doesn't wait for a requestAnimationFrame event before re-rendering the reactive data structures.
Events are sent as a very simple vector format. Like a lisp sexpression the first item of the vector should be a symbol (keyword) for which function (handler) that should be handling this sexpression (event). The rest of the vector is a free-form argument vector.
Handlers are registered with (register-sub :name-of-event handler-fn)
The handler-fn has the same purpose as a clojure reduce-function, its arguments are the app-state (derefed!) and the incoming event.
The handler-fn returns the new application-state, which re-frame will reset! into app-db.
Re-frame offers a simple middleware-abstraction, where debug/logging-statements can be put. Another powerful middleware is path, that works as a lens, making the handler-fn simpler by making it work on a specific path in the app-db.
I guess one could create some middleware for simplifying the use of datascript as application state atom.
The handler should implement the logic on what should happend to an incoming event, potentially based on the app-db state. The re-frame readme mentions finite state machines as a fruitful abstraction.
Application state app-db is stored in one (1) reagent atom.
By using reagent's reactions, one can build up a graph, chained reactions, where more costly operations can be "shielded" behind reactions which wont report a change if the reactions view from a new app-db is the same immutable data structure as it was in the previous app-db.
The redrawing of the DOM/screen is triggered by requestAnimationFrame. Given a standard refresh rate of 60 Hz, this trigger will occur every 16.67 ms, if the program is done with it's previous recalculation by then.
Re-frame uses hiccup-style syntax feed to the Reacts Virtual DOM.
There can be several related reagent atom-constructs called reactions, containing derived state ("views") of the app-state.
To make state changes in the application, initialization code or callback functions from event-emitters like the DOM, timers, network connections should send dispatch messages. These are put in a core.async channel and handled by registered handlers.
There's two special types of dispatch, dispatch-sync which handles the event directly, and does not put it in the core.async channel. The other special dispatch is putting ^:flush-dom metadata on the dispatched event, which doesn't wait for a requestAnimationFrame event before re-rendering the reactive data structures.
Events are sent as a very simple vector format. Like a lisp sexpression the first item of the vector should be a symbol (keyword) for which function (handler) that should be handling this sexpression (event). The rest of the vector is a free-form argument vector.
Handlers are registered with (register-sub :name-of-event handler-fn)
The handler-fn has the same purpose as a clojure reduce-function, its arguments are the app-state (derefed!) and the incoming event.
The handler-fn returns the new application-state, which re-frame will reset! into app-db.
Re-frame offers a simple middleware-abstraction, where debug/logging-statements can be put. Another powerful middleware is path, that works as a lens, making the handler-fn simpler by making it work on a specific path in the app-db.
I guess one could create some middleware for simplifying the use of datascript as application state atom.
The handler should implement the logic on what should happend to an incoming event, potentially based on the app-db state. The re-frame readme mentions finite state machines as a fruitful abstraction.
söndag 29 mars 2015
bigdec, decimal?, integer?
The function bigdec returns a java.math.BigDecimal.
If you want to test it you can use decimal? instead of defining your own function bigdec?
integer? does not test the value for not having decimals, but for being some natively decimal number type.
(defn no-decimal-part?
"converts the number to bigdec,
make sure a division by
zero has remainder exactly zero"
[number]
(zero? (.remainder (bigdec number) java.math.BigDecimal/ONE)))
is better to use to make sure the bigdec does not have any decimals.
If you want to test it you can use decimal? instead of defining your own function bigdec?
integer? does not test the value for not having decimals, but for being some natively decimal number type.
(defn no-decimal-part?
"converts the number to bigdec,
make sure a division by
zero has remainder exactly zero"
[number]
(zero? (.remainder (bigdec number) java.math.BigDecimal/ONE)))
is better to use to make sure the bigdec does not have any decimals.
måndag 29 december 2014
Limit in Datomic
It's possible to use limit (SQL-style) in Datomic when using the new Pull API. The Pull API seems to be a very ambitious API which can even make graph-walks and more.
torsdag 23 oktober 2014
Talk about a web application architechture
This Monday I held a talk at my company Agical presenting a sketch of an interesting web application architecture. One could call me a Cognitect fan-boy, but I'm proud of it.
Before getting to the technical stuff I discussed a bit on modelling things.
I've always think modelling things are super complicated to get right, especially with ie SQL or single tables like Excel. Probably I try to take to many things into account at the same time, but hey, the world is complicated, so why shouldn't I try to model it at least a bit more like how it really is?
The architechture, then.
Something along these lines: React/Om talking with DataScript via core.async channels and to the server. The server running Pedestal and Datomic (and whatever other data source necessary - Datomic would be the transaction engine).
It's a bit bold to claim that even database queries could be reused in the client, this is likely not the case, but the model could be similar in structure on both client and server.
The controller in the client and server would consist of a core.async pub/sub setup, although it feels a bit hard to make sure everything is setup right, it feels a bit like we are in multimethods all over again.
The start and stop of the application would be taken care of through Component. And off we go!
Extremely useful resources
for preparing this talk was
CatChat (a DataScript example app)
David Nolen's blog posts of both core.async and Om
Om intermediate tutorial on Datomic integration
O'Reilly's Webinar about Pedestal with Ryan Neufeld (2 h YouTube video)
Things I stumbled upon was
Trying to visualize even a simple Pedestal router setup was quite error prone. The interceptors got wrong and all over the place.
Setting up ClojureScript to compile Om. It's mostly the Leiningen project.clj options that's hard to understand. Validation of options or warnings when unused options occur would be useful.
Programming core.async channels in the nRepl often locked up the repl in strange ways, from which I had to re-require the namespaces.
Getting my head around Om and it's quite messy formatting syntax, especially when it comes to catching events from various things. Shouldn't one put small functions inside the elements maps? Maybe listeners should be defined separately from the DOM-structure.
Maybe there's even room for an abstraction over the events, because now most of it is quite OO that one has to get take back tree-element by element.
There are many fascinating papers about CRDT and similar techniques, but still it's not clear on how to structure the events from the application and the event "schema" between client and server, especially with regards to CRDT at similar. An especially delicate thing close to my heart is the ability to show where other people are editing, so edits not collide to badly.
Pub/sub "reactions" I think could be replaced with transducers.
I've always think modelling things are super complicated to get right, especially with ie SQL or single tables like Excel. Probably I try to take to many things into account at the same time, but hey, the world is complicated, so why shouldn't I try to model it at least a bit more like how it really is?
The architechture, then.
Something along these lines: React/Om talking with DataScript via core.async channels and to the server. The server running Pedestal and Datomic (and whatever other data source necessary - Datomic would be the transaction engine).
It's a bit bold to claim that even database queries could be reused in the client, this is likely not the case, but the model could be similar in structure on both client and server.
The controller in the client and server would consist of a core.async pub/sub setup, although it feels a bit hard to make sure everything is setup right, it feels a bit like we are in multimethods all over again.
The start and stop of the application would be taken care of through Component. And off we go!
Extremely useful resources
for preparing this talk was
CatChat (a DataScript example app)
David Nolen's blog posts of both core.async and Om
Om intermediate tutorial on Datomic integration
O'Reilly's Webinar about Pedestal with Ryan Neufeld (2 h YouTube video)
Things I stumbled upon was
Trying to visualize even a simple Pedestal router setup was quite error prone. The interceptors got wrong and all over the place.
Setting up ClojureScript to compile Om. It's mostly the Leiningen project.clj options that's hard to understand. Validation of options or warnings when unused options occur would be useful.
Programming core.async channels in the nRepl often locked up the repl in strange ways, from which I had to re-require the namespaces.
Getting my head around Om and it's quite messy formatting syntax, especially when it comes to catching events from various things. Shouldn't one put small functions inside the elements maps? Maybe listeners should be defined separately from the DOM-structure.
Maybe there's even room for an abstraction over the events, because now most of it is quite OO that one has to get take back tree-element by element.
There are many fascinating papers about CRDT and similar techniques, but still it's not clear on how to structure the events from the application and the event "schema" between client and server, especially with regards to CRDT at similar. An especially delicate thing close to my heart is the ability to show where other people are editing, so edits not collide to badly.
Pub/sub "reactions" I think could be replaced with transducers.
måndag 6 oktober 2014
Clojure web security
This post about Clojure web security is a must read. Not only does it summarize many things that can go bad, but also shows just how severe it can be to read data with read-string - it looks like it can execute almost any code and construct any availiable java class! Scarier than I knew. Thanks.
tisdag 12 augusti 2014
Steam-roller for nested Clojure data structures
There was a question on the Clojure Google group about structural sharing in rrb-vectors visavi a zipper-construction.
As we all know, it's not very easy to be certain of how much memory is allocated in Java/Clojure since the pointers are sometimes reused, and the situation gets even more complicated (for the better) when we have structural sharing and immutable objects.
The Clojure data structures are constructed from Object arrays, which creates shallow nested trees of either vector elements or key-value pairs in the case of PersistentMaps. Likely one could use reflection to dig deeper into the the inner parts of these data structures and arrays, Iroh and Clj-wallhack seems both worthy to try out.
I created a small function for getting a pointer to every Clojure data structure from a nested structure (without taking care of it's aforementioned internals, though).
I think the best way would be to count objects with VisualVM or some other profiler, though.
As we all know, it's not very easy to be certain of how much memory is allocated in Java/Clojure since the pointers are sometimes reused, and the situation gets even more complicated (for the better) when we have structural sharing and immutable objects.
The Clojure data structures are constructed from Object arrays, which creates shallow nested trees of either vector elements or key-value pairs in the case of PersistentMaps. Likely one could use reflection to dig deeper into the the inner parts of these data structures and arrays, Iroh and Clj-wallhack seems both worthy to try out.
I created a small function for getting a pointer to every Clojure data structure from a nested structure (without taking care of it's aforementioned internals, though).
I think the best way would be to count objects with VisualVM or some other profiler, though.
Prenumerera på:
Inlägg (Atom)