Fork me on GitHub
#hoplon
<
2016-05-30
>
micha01:05:42

@flyboarder: hoplon doesn't itself

micha01:05:51

but there are a number of libraries you can use

micha01:05:03

in combination with the on! multimethod

micha01:05:31

hoplon basically supports the events that jquery supports

flyboarder01:05:53

so if I wanted to use jquery mobile, do i just need to include the lib?

micha01:05:17

does that add events to jquery's event system?

micha01:05:23

if so then yes

micha01:05:58

i have used hammerjs in the past with good results

micha01:05:50

that's an example

micha01:05:12

it won't work as is, needs to be updated for hoplon 6

flyboarder01:05:31

the demo there seems to use regular jquery when accessing the touch events

micha01:05:06

should work

flyboarder01:05:53

that will have to be a tomorrow thing ๐Ÿ˜›, what namespace changes are happening for on!/do! i saw that circulating here earlier

micha01:05:33

so on! and do! are multimethods

micha01:05:47

which will be defined in hoplon.core as always

micha01:05:04

but multimethods can be implemented anywhere

micha01:05:21

eg the individual implementations of the multimethod functions

micha01:05:39

so for instance (div :css {:width 100} ...)

micha01:05:52

somewhere there would need to be a

micha01:05:05

(defmethod do! :css ...

micha01:05:25

but not necessarily in the same namespace as where do! multimethod itself is defined

flyboarder01:05:49

oh ok, so the implementations are moving

micha01:05:57

so we can move the existing implementations, which are based on jquery, to a special namespace

micha01:05:09

and make ones based on goog or whatever

micha01:05:47

then whichever one of those namespaces you require in your program will be the one that provides the implementation for the multimethod

flyboarder01:05:23

can you override the implementations? like :click for example?

micha01:05:48

multimethods are just basically mutable maps

micha01:05:54

underneath

flyboarder01:05:47

ok im thinking of making click call tap on mobile so I dont need to implement both everywhere

flyboarder01:05:16

but ill look into that more tomorrow i think

micha01:05:19

you can call one multimethod from another of course

micha01:05:30

or use get-method

flyboarder01:05:24

thats interesting tho, having multiple implementations of attributes

micha01:05:11

yeah hoplon itself really doesn't need to provide things like :click and :css etc

micha01:05:41

just the framework for those to be implemented in

lewix13:05:42

how does working with hoplon compare to reframe

micha13:05:36

like how do you mean?

micha13:05:56

anything in particular?

lewix13:05:11

hoplon seems a tad old to me since it only relies on jquery. Am I missing something?

micha13:05:41

well when you manipulate the dom you need to have a dom compatibility layer

micha13:05:55

and frankly jquery is miles ahead of anything else

lewix13:05:03

no virtual DOM

micha13:05:16

even virtual dom things need a dom compatibility layer

micha13:05:20

when they manipulate the dom

micha13:05:45

but with hoplon you don't use jquery directly

lewix13:05:01

micha: have you worked with 'anything else' before/

micha13:05:03

it's just what hoplon uses underneath to do simple things

micha13:05:54

like when reactjs diffs the dom and applies changes, it needs to manipulate the dom

dm313:05:04

there's a nice presentation by Micha

dm313:05:52

trying to find in Hoplon Wiki...

lewix13:05:33

micha: did you just say that hoplon uses the virtual DOM underneath to do simpel things?

micha13:05:53

@lewix: no virtual dom in hoplon

lewix13:05:08

dm3: I'm listening to it right now; with a very open mind - however, I must admit I'm not convinced

micha13:05:19

it uses jquery to do simple things like event handlers, reliably set css, attributes, etc

dm313:05:54

what's exactly holding you back? jQuery?

lewix13:05:32

I'm coming from a react/redux workflow, I tried reagent, reframe/reagent, and rum, now I'm looking into hoplon ; I'm still not sure what the later brings to the table compared to the aforementioned @dm3

dm313:05:12

for me personally - sane javscript integration through absence of React and simple state management through plain vars in namespaces

lewix13:05:51

dm3: have you used react or any react-related libs before?

dm313:05:17

yes, one Om project, one with Re-Frame

lewix13:05:35

Om doesn't count ๐Ÿ™‚ It's rocket science

dm313:05:02

not Om.next

lewix13:05:36

how far did you go with re-frame dm3

lewix13:05:24

micha: nice presentation

dm313:05:38

not sure how to answer that ๐Ÿ™‚ a "working project" far?

lewix13:05:00

dm3: I see. how's Hoplon performance?

dm313:05:40

fine for my use case

micha13:05:05

performance is fine in real-world applications

micha13:05:16

not for games maybe, i dunno i do't make games

micha13:05:38

todomvc with a million todo items probably not good performance, but that's a useless application even with good "dom rendering" performance

lewix13:05:10

micha: so in a nutshell in terms of performance virtual dom > than javelin ?

micha13:05:23

depends what you mean by performance

micha13:05:34

i'm saying that that's never the bottleneck

micha13:05:39

in my experience

micha13:05:52

so it's a pointless exercise

micha13:05:28

the bottleneck is interaction with servers and working around the limited memory available and nonexistent local caching options

micha13:05:35

hoplon naturally minimizes dom manipulation operations

micha13:05:45

but in a different way than reactjs

micha13:05:03

i think in most cases hoplon actually performs fewer dom manipulations

micha13:05:20

maybe in all cases

micha14:05:12

in react the dom manipulations are pruned at the DOM layer

micha14:05:23

via "dirty checking" (diffing)

micha14:05:38

in hoplon that's done in the data layer, in javelin

lewix14:05:10

stupid question: is javelin built on top of rxjs or something?

micha14:05:22

no it's a clojurescript library

micha14:05:27

no dependencies

micha14:05:48

well no dependencies other than the priority-map datastructure

dm314:05:58

One thing that I think works smoother in Re-frame land is hot reloading. Re-frame forces you to keep most of the state in one map and :on-jsreload rerenders pretty much the same state you had. In Hoplon you have a lot of state scoped to the defelems that gets thrashed on reload.

lewix14:05:19

micha: thanks for the info

micha14:05:39

any time! good luck ๐Ÿ™‚

lewix14:05:08

do you have a global store in Hoplon (kind of like redux)

micha14:05:50

you mean a single atom containing the entire state?

lewix14:05:49

in react we use flux like pattern to manage complex state. a predictable state container, the only way to change the state of the app is to emit an action that transform the state tree

micha14:05:56

hoplon is most similar to reframe

micha14:05:13

i believe a lot of it was based on things in hoplon

micha14:05:29

unidirectional dataflow, etc

micha14:05:46

there is no framework around it, as such

micha14:05:57

it just naturally falls out of the choice of abstractions

micha14:05:31

i.e. the javelin cell reference type and the hoplon linkage between cells and element properties

micha14:05:37

there's a diagram there you can see

micha14:05:47

and compare with re-frame

micha14:05:17

that library, castra, is the cqrs backend rpc thing

micha14:05:43

similar to like falcor or whatever

micha14:05:02

separate from hoplon itself, optional

micha14:05:50

there is no need for a state container or to emit actions in hoplon

micha14:05:09

because the javelin cells correctly process updates in dependency order

lewix14:05:35

micha: I see. thanks ill give it a try

micha14:05:41

and suppress spurious updates, so the update fns don't need to be pure

micha14:05:52

which is pretty crucial in a real-world application

lewix14:05:47

what's crucial? didn't get that part

micha14:05:25

having stateful reactive things

micha14:05:39

like with reflux your updaters need to be pure fns

micha14:05:51

javelin formulas do not need to be pure

micha14:05:10

this eliminates a ton of framework and special conventions

micha14:05:38

and this, in turn, makes it possible to form abstractions that are better factored

micha14:05:02

you can achieve a better separation of concerns when you don't have layers of framework that introduce coupling

lewix14:05:52

I don't think that reflux updaters need to be be a pure; and I believe that having pure fns make your UI code easier to reason about

micha14:05:09

i was under the impression that updates could happen more than once, and that the order they happen in is not guaranteed

micha14:05:37

and that would of course make it extremely difficult to reason about any side effects performed in there

micha14:05:49

javelin does not suffer from this problem

micha14:05:00

it's really easy to reason about side effects in formula cells

micha14:05:31

consider for example, this debounce function

micha14:05:44

the separation of concerns here makes it very easy to understand the side effects and statefulness there

micha14:05:58

there is very little code there, and it avoids the common mistakes with something as simple as a debouncing mechanism

micha14:05:30

i have the same thing implemented in core.async, and it's much harder to reason about

micha14:05:51

and it had a bug we missed because it was hard to reason about

micha14:05:20

the bug was with the handling of the first update after a long pause

lewix14:05:57

I see; I cannot understand the code because I haven't learned one bit of hoplon yet

lewix14:05:17

I'll get to that later today, and see for myself

micha14:05:16

that gist was just jaevlin

micha14:05:35

which is its own separate thing, used in hoplon

lewix14:05:41

it'd be nice to have an actual graph comparing hoplon to react kind of like http://elm-lang.org/blog/blazing-fast-html

micha14:05:17

my interest isn't in blazing fast anything

micha14:05:27

because that's premature optimization

lewix14:05:31

micha: if I understand correctly, javelin is a frp framework just like rxjs. However it's implement in clojurescript?

micha14:05:45

the bottleneck in any SPA i've ever made was not in the dom

micha14:05:50

at least not with hoplon anyway

micha14:05:04

we've never even had any need to optimize for blazing

micha14:05:22

so there is a lot of opportunity there if anyone ever wants to do it

lewix14:05:52

maybe your UI don't require you too, and are not fully SPA, I haven't worked with SPAs for long before I reached performance issues

micha14:05:11

we've made large hoplon SPAs

lewix14:05:17

especially with angular 1; I eventually swithced to react

micha14:05:30

well angular doesn't use javelin etc

micha14:05:51

so it's doing a lot of extra work all the time to achieve "reactive" things

lewix14:05:11

right but my point was in regard to you saying that the bottelneck in any SPA is not in the dom

micha14:05:27

i guess i mean in a hoplon application

micha14:05:48

it rarely touches the dom, just as a result of the choice of abstractions

lewix14:05:58

can i see your large hoplon SPAs just so I can refer to it while learning

micha15:05:23

they're all business applications that are behind logins, unfortunately

lewix15:05:39

so wouldn't it be nice to compare the speed without premature optimization?

micha15:05:53

we used to have a pretty large SPA on http://hoplon.io, with all the docs etc

micha15:05:11

but we decided to move the actual content to github wiki for ease of contribution

micha15:05:19

so that went away

micha15:05:39

but it was pretty large, like 50k elements probably

micha15:05:47

and zero performance issues there

lewix15:05:04

oh one more question. is it possible to have custom made middlewares like reframe or redux?

micha15:05:33

what is that, exactly?

micha15:05:41

middle of what?

lewix15:05:55

micha: I understand. I still maintain that it wouldn't remove anything to hoplon to just compare the speed to other frameworks without optimization

micha15:05:18

you're welcome to add hoplon in there, if you like ๐Ÿ™‚

micha15:05:31

although i maintain that it's not a helpful metric

lewix15:05:45

it is helpful

lewix15:05:52

it might not be helpful to you

micha15:05:08

like you will never reach the limit in a real application

micha15:05:41

the benchmarks are imho mostly foolish ones that are testing bizarre artificial situations

micha15:05:53

like we made a missile command game one time

micha15:05:04

just to show why this kind of thing is unnecessary

lewix15:05:15

after working with angular and react i can confirm that the metrics are not artificial

micha15:05:18

we could have thousands of missiles in flight simultaneously

micha15:05:27

with explosions and sound effects

micha15:05:34

and maintain 60fps easily

micha15:05:56

our render loop was on a 100ms interval

micha15:05:19

60fps means a frame every 16ms or so

micha15:05:24

how did we do it?

micha15:05:37

we used svg animations and interpolated paths

micha15:05:43

which we would update every 100ms

micha15:05:58

100ms is way faster than the human nervous system can see

micha15:05:11

so you can separate those concerns

micha15:05:30

one part of the application is a highly optimized animation thing

micha15:05:44

we used svg transforms and animations, but you could use velocityjs or whatever

micha15:05:31

our actual game logic just updated the paths in the svg rtansforms now and then as the user interacts with the game and the internal state of the application changes

micha15:05:00

so talking about how many dom elements you can craete per second does not apply to hoplon

micha15:05:04

because you don't need to do that

micha15:05:18

if you can't separate those orthogonal concerns then yes, everything in the world is an important, relevant metric

micha15:05:32

but if you can separate them then some of them are not relevant

lewix15:05:32

so in theory it could be faster...You should market it as such then. It might sounds odd but some people care about those things - react is not actually that much faster than other libs, they just capitalized on that. Sometimes marketing a good lib is as important as working on the lib IMO

micha15:05:50

yes but that's a race to the bottom

micha15:05:05

i just want to make applications that make people money in their business

micha15:05:25

and have the applications not be disposable junk in 6 months

micha15:05:00

the people i work for don't care about benchmarks

micha15:05:11

if the app is slow maybe they would

lewix15:05:16

and how do those people make money? through marketing for the most case - how do you reach them? probably through marketing too...marketing is underrated in software development. Bad libs are more popular than better ones sometimes just because of better marketing

micha15:05:21

but that has never been a problem

micha15:05:56

that's true

micha15:05:29

i'm not good enough with that to enter the world of the-latest-big-thing

micha15:05:43

like facebook is

micha15:05:06

bro culture doesn't feel good to me

lewix15:05:18

I can't wait to go home and play with hoplon cause you sold it well enough to me

micha15:05:37

hahaha that's nice of you to say ๐Ÿ™‚

micha15:05:57

i hope you enjoy at least playing with a weird thing

micha15:05:51

we're working on separating out the jquery parts into an optional namespace btw

lewix15:05:02

I'm basically looking for the the right framework for my next SPA.

micha15:05:07

because the base hoplon functionality doesn't use it

micha15:05:37

jquery is used only in some of the "custom attributes" that hoplon ships with

micha15:05:01

in the past we had that just so you'd have a more or less complete environment out of the box

lewix15:05:25

are you guys the same people doing boot?

micha15:05:29

but now there is a case for separating it out, as an optional :require

micha15:05:19

boot was originally the lein-hoplon plugin

micha15:05:21

๐Ÿ™‚

micha15:05:46

then we realized we were like 75% of the way toward implementing a complete build tool in there

micha15:05:53

so we said fuckit onward

lewix15:05:51

thanks a lot man. you were super helpful

micha15:05:58

awesome, any time!

lewix15:05:15

I should probably head back to work. I'll hit you up tonight while trying to grok hoplon

micha15:05:15

you are welcome to talk about re-frame/om/whatever in here btw

lewix15:05:59

oh I took a look at om, and it felt like rocket science especially for someone new to clojure/clojurescript

micha15:05:11

vue.js then!

lewix15:05:26

I liked reagent and reframe, played with it for about a week but I didn't like the attitude of the creator

lewix15:05:57

rum seems nice too

micha15:05:23

it's nice to see comparisons

micha15:05:31

here is one, i will find a link

dm315:05:50

the biggest hurdle for me when coming from Re-Frame/Reagent was not passing things down the "component tree", but rather rethinking the UI in terms of separate namespaces holding pieces of state

micha15:05:06

yes that's probably the biggest difference between hoplon and react-based things

micha15:05:36

with react you usually have the single atom, so you can have transactional updates

micha15:05:58

and then you need lenses or cursors or action signals, etc

micha15:05:10

hoplon inverts that

micha15:05:36

instead you just make cells, which are almost like cursors

micha15:05:51

and they knit themselves together into a single dependency graph

micha15:05:05

which automatically enforces the transactions

lewix15:05:14

where can i learn about all those concepts: lenses, cursors, action signals, dependency graph...

dm315:05:18

there's also an issue of making "reusable" components

micha15:05:31

those are om words

micha15:05:52

but the approaches are pretty similar across react frameworks as far as i've seen

lewix15:05:02

dm3: no reusable components?

dm315:05:15

you just have to think about them differently

dm315:05:41

in Re-frame you get a reusable component by completely decoupling it from the app state

dm315:05:51

so you have to pass everything in explicitly

dm315:05:13

callbacks and such

dm315:05:57

in Hoplon you can have state in the namespace, and you pass in Javelin cells instead of callbacks

piotrek20:05:38

@dm3 you can have reusable components in hoplon. You just need to pass cells to those components as attributes instead of defining them as a global vars in componentโ€™s namespace

piotrek20:05:00

or create cells as local vars inside custom element function