Fork me on GitHub
#hoplon
<
2017-01-25
>
thedavidmeister02:01:44

@qqq @micha i think d3 has key functions too, for diffing data structures that need to be rendered to the dom (not just strings), so the approach a lot older/more common than just a react internal

chromalchemy18:01:37

Hi guys, i have some vague questions about about how to approach working with structured data for a to-do list app.

chromalchemy18:01:33

I am used to working in outliners, so I'm looking at zippers, and trying to understand TheLarch Hoplon example.

chromalchemy18:01:39

ps. I noticed a commented out reference to thelarch in Panoply. https://github.com/hoplon/panoply Since Panoply is a todo list, is there any relation?

alandipert18:01:59

we're not sure what panoply will be yet, last idea is a chat app lol

alandipert18:01:12

i just lifted the oauth code

chromalchemy18:01:23

I still have to digest Hoplon TodoFRP too https://github.com/hoplon/demos/tree/master/todoFRP, But I think that doesn't have any nesting.

chromalchemy18:01:06

I have heard Micha talk down on clojure.zip in favor of Jquery as a zipper library. But in what context? I think I will be working with clojure data (immutable?)

chromalchemy18:01:00

And I've heard others distance themselves from zippers in favor of Specter (which in addition to the lens approach, has it's own zipper library)

chromalchemy18:01:11

Does Specter play nice with Javelin? Are there advantages to using it over Javelin lenses? I don't want to get to far away from Hoplony goodness 🙂

chromalchemy18:01:39

I'm doing primarily cljs with Firebase ala @flyboarder Brew library. https://github.com/hoplon/brew/blob/master/src/hoplon/firebase.cljs.hl Since I still have not figured out how to deploy a proper clojure app (Heroku noob)

chromalchemy18:01:01

I am still a clojure noob in general, and am eager to get something working. Should I be wary of zippers, in favor of lenses, for easier grokking?

chromalchemy18:01:59

@alandipert Thanks for the Orcus link, I didn't have that one

chromalchemy18:01:50

... Or should I stick to the theLarch pattern as pretty idiomatic Hoplon/Javelin?

chromalchemy18:01:12

In my outliner apps, I like to use aliases and saved queries on metadata. So then the tree really becomes a graph. So should I be looking past zippers for more graph-oriented patterns? Perhaps Datomic/Datascript?

chromalchemy18:01:40

Again, I want to edit this thing with Hoplon UI, so I dont want to steer to far from Javelin

chromalchemy18:01:29

ps. maybe with all of this I need to be less focused on fancy libraries and getting more familiar with Clojure data (Zippers, Seqs, patterns, etc)

chromalchemy18:01:43

Any guidance would be appreciated.

chromalchemy18:01:54

@micha I know your have some experience with zippers so I would love your opinion. Thanks!

micha18:01:24

i think i was referring to "functional zippers", meaning the immutable things

micha18:01:34

like where you operate on a zipper to get a new zipper

micha18:01:42

leaving the original untouched

micha18:01:04

imo that has little value as an abstraction over the dom

micha18:01:10

because the dom is not immutable

micha18:01:27

zippers can be useful for navigating immutable data

micha18:01:36

i think we did something like that in thelarch

micha18:01:19

but if you want to do stuff to elements in the dom, i find the immutable zipper abstraction to be inferior to like jquery for example

chromalchemy18:01:50

I am thinking more like I have data that I CRUD w Firebase, then render to and edit in a page.

chromalchemy19:01:21

Am I correct that my case is a different one than accessing the Dom-as-data (with zippers, etc), and that the functional zippers might be very appropriate (vs Jquery)?

micha19:01:33

definitely

chromalchemy19:01:24

@micha Ok. What do you think of clojure.zip vs Specter vs Javelin Lenses? (especially on the cljs side for Specter vs Javelin)?

chromalchemy19:01:15

and all that vs Datomic/Datascript?

chromalchemy19:01:41

I guess if I had datomic I wouldn't need Firebase. I am not at the level to re-implement my own database. But I like how Firebase seems simple and accessible, (and client-only deploy) and might be very good as an accessory db.

micha19:01:19

i like the idea of firebase

micha19:01:39

specter could be used in javelin formulas, no?

micha19:01:52

it's just functions right?

chromalchemy19:01:15

I tried something and got errors, I'll have to try again.

chromalchemy19:01:06

Is using Specter redundant considering I already have Javelin lenses at the ready? What is the conceptual overlap?

micha19:01:02

i haven't used specter, but isn't it a library for destructuring clojure data, basically?

micha19:01:28

i don't think there is any overlap with javelin really

micha19:01:51

the specter functions can be used in javelin formulas

micha19:01:56

or lenses or whatever

chromalchemy19:01:38

"abstraction called navigators which complete the story around immutable programming and make it easy to transform and query nested data structures. It allows you to concisely specify what you want to change within a data structure, and get a new data structure back with only your changes applied – everything else is reconstructed and the types of data structures throughout don't unexpectedly change."

chromalchemy19:01:07

" Specter is (at least in main use cases) Haskell's lens package"

micha19:01:09

looks like it's just functions

micha19:01:21

you can use any function in a javelin cell, no problem

micha19:01:23

you can do (def banks (cell= (user->bank world-cell name-cell amt-cell)))

chromalchemy19:01:52

"Definitely more lens than zipper. If you think of a lens, in simple form, as a path into a structure then a zipper is a structure plus a path into itself. This constrains the form that a zipper can take. If you examine these paths on their own then you get into general "optics" which is where the lens type lives and where specter lives (it seems). In particular, we start talking about generalized folds and traversals."

chromalchemy19:01:23

Ok , thanks for the insight. I'm just trying to orient. I haven't used it barely at all yet.

chromalchemy19:01:59

I thought that if Specter is promising an easier approach than zippers. But if it is essentially lenses, and Javelin has lenses, maybe Specter is redunant for my purposes.

chromalchemy19:01:21

I remember @laforge49 had a project with both Specter and Javelin lenses in it. Javelin on the client, Specter on the server.

micha19:01:30

specter works on immutable data

micha19:01:58

specter doesn't provide a "reference type"

micha19:01:31

javelin, on the other hand, doesn't do anything but provide a reference type

micha19:01:39

so there isn't any overlap really

micha19:01:02

in other words

micha19:01:14

specter's api is a collection of functions, correct?

micha19:01:16

and macros

micha19:01:30

let's call those f, g, ...

micha19:01:49

there is no reason why you couldn't do (cell= (f x))

micha19:01:59

where x is some other cell perhaps

chromalchemy19:01:48

Ok, I'll play with them both together. Thanks for the clarification.

chromalchemy19:01:45

@laforge49 What is your impression of Javelin lenses (strengths, limitations?) after doing your own lens implementation https://github.com/hoplon/demos/tree/master/lens, and also using Specter

laforge4919:01:53

Javelin lenses are best on the browser, where the scope is narrow enough (single user) and the resources per user is maximal (100%). And Javelin has a number of optimizations that can at times be helpful. On the server side, specter looks really great and I used it, once. I just don't seem to encounter enough use cases, for which I am currently blaming myself. I've ended up adding notifications capability to my Datomicish database, but even there the usage to date is minimal.

alandipert19:01:07

competes with specter in the 'get' arena. no facilities for update

alandipert19:01:07

also, wildly inefficient. but that could easily change... https://github.com/halgari/odin is another recent thing that uses a different logic language

chromalchemy19:01:47

@alandipert Very interesting! I definitely want to play with Datalog

chromalchemy19:01:56

@alandipert Can Intension be used in cljs?

alandipert19:01:11

hypothetically

alandipert19:01:31

ok, yes it can

alandipert19:01:36

not much to it

chromalchemy19:01:08

Cool! Will try it out.

mynomoto21:01:11

@chromalchemy http://github.com/mynomoto/github-client is a project using hoplon and datascript if you want to take a look.

qqq21:01:11

@alandipert : although I like hoplon's frp model more than I like reagent's reactive model, re-frame's re-com and re-frisk (amazing!) has won me over; I hope hoplon / javlin / casatra have more public libraries soon!

qqq21:01:59

damn you're a good salesman

alandipert21:01:29

haha, 'one last thing'

qqq21:01:41

is there a live demo of all gui widgets? I can't find it on https://github.com/hoplon/ui/wiki

alandipert21:01:59

no, it's sort of a well-kept secret, very close to 1.0 release tho afaik

alandipert21:01:23

nothing we have has the momentum of reagent/react/re-frame

dm321:01:33

they're piggybacking on React

qqq21:01:58

@dm3: why would "piggybacking on React" be an advantage of a cljs lib ?

alandipert21:01:15

it's good for marketing

dm321:01:25

all the devs coming to Cljs go: Google [React clojurescript]

alandipert21:01:29

at this point the cljs web devs i know won't even look at something that doesn't involve react

alandipert21:01:46

which has kind of stunted our growth a bit... but we are still slowly growing

qqq21:01:05

you need to market Hoplon as "CLJS Beyond React"

dm321:01:09

not: Google [react too complicated clojurescript ui]

qqq21:01:11

so it also gets all the "CLJS React" searches

qqq21:01:09

in fact, I'd go a step further and rename the "hoplon" oroject to "cljs-beyond-react"

alandipert21:01:41

yeah i dunno

alandipert21:01:54

it's not really related to or inspired by react in any way, other than that it solves a similar set of problems

alandipert21:01:10

so it would be disingenous to say we're going beyond react when we haven't even used react yet 🙂

dm321:01:18

it's an alternative

dm321:01:29

with React you can use stuff like React-native

dm321:01:08

I've used React (via reagent, re-frame, om)

dm321:01:30

adds nothing over Hoplon for web-apps

dm321:01:41

or, I guess, adds a number of pre-defined patterns of how to structure the application which matters once you grow to a certain size

alandipert21:01:54

a lot of people like that

alandipert21:01:06

people with more rails type mindsets, and junior people. clear directions

dm321:01:10

I wouldn't recommend Hoplon to a team of 5 people where noone is experienced with it

dm321:01:16

much easier to start off with re-frame

qqq21:01:32

I'd say that reagent offers nothing over hoplon, but re-frame's single db source of truth + subscribers + event handling system is neat

dm321:01:58

it's neat, but the single db is isomorphic to the network of cells

qqq21:01:03

javelin / reagent basically provide the same primitives, with javelin/cell == reagent/ratom

dm321:01:05

so you ultimately gain nothing

alandipert21:01:08

that's the part i personally would avoid.. having built a medium-sized eventbus-based thick client 5 yrs ago

alandipert21:01:27

its part of the reason we decided it was important that cells can be anonymous

micha21:01:41

that's the difference between javelin and ratoms i think

micha21:01:46

the dependency graph

micha21:01:01

plus the cell manifesto type guarantees

micha21:01:14

ie each cell updates at most once per propagation

qqq21:01:23

javelin gets dependency graph via macro analying the code; and re-frame gets it via running the reaction, and looking at what's dereferenced -- right?

micha21:01:34

javelin doesn't need macros

micha21:01:41

that's just syntax sugar

qqq21:01:43

isn't cell= a macro?

qqq21:01:56

without macros, how do you analyE which cell depends on which cell ?

micha21:01:56

but it just expands to a call to the formula function

qqq21:01:12

how do you figure out what cell depends on which cell -- do you do it at compile time or at runtime?

micha21:01:30

(cell= (+ a b))
;; same as
((formula +) a b)

micha21:01:46

where formula is just a function

qqq21:01:19

(cell= (+ (* a b) (/ c d))) expands to ((formula +) (* a b) (/ c d)) ... but now, isn't this fucked, because we need to know it depends on a b, c, d, -- rather than use their values ?

micha21:01:21

if you macroexpand (cell= (+ a b)) you'll see that's what it emits

micha21:01:36

no that's not how it works

micha21:01:54

(cell= (+ (* a b) (/ c d)))
;; same as
((formula (fn [v w x y] (+ (* v w) (/ x y))) a b c d)

micha21:01:32

it doesn't "hoist" core names, like +, *, or /

micha21:01:36

but if you did like

micha21:01:17

(cell= (f (g a b) (h c d)))
;; same as
((formula (fn [x1 x2 x3 x4 x5 x6 x7] (x1 (x2 x3 x4) (x5 x6 x7)))) f g a b h c d)

qqq21:01:42

can se say: cell= finds all the "leaves" of the following sexp cell= then cfeates a new function, where there ar e"holes" for each leaf, and it applies formula new-func leaves

micha21:01:58

it hoists names that could be cells

micha21:01:08

by deep code walking macrology

micha21:01:32

it knows how to extract names of things that could be referring to cells

micha21:01:36

syntactically

micha21:01:49

there is also the formula-of macro

micha21:01:07

(cell= (+ a b))
;; same as
(formula-of [a b] (+ a b))

qqq21:01:10

okay, so very broad strokes of cell= ` (cell= sexp) leafs <- leafs of sexp possible-cells <- filter [some matic function] leafs new-func <- sexp as a function with holes for "possible-cells returns [ formula new-func possible-cells ]

micha21:01:55

there is also fomulet

micha21:01:34

but the dependency graph is important

micha21:01:40

if you have like

qqq21:01:42

yeah, that's where you run topolotical sort

qqq21:01:46

to ensure everthigni is updated only once?

micha21:01:01

yeah to guarantee they are updated in the correct order and only at most once

qqq21:01:07

reagent's "possible multiple update" is quite annoying

qqq21:01:18

I don't understand why they don't just run topolotical sort after they extract dependency graph

micha21:01:19

so no formula can see the world in an incomplete state

micha21:01:52

the ratom depends on dynamic vars and stuff

qqq21:01:54

that's intersting; I never considred out-of-sync udpates as "world in incomplete state"

micha21:01:12

it's not a real reference type, as in first class as far as i know

micha21:01:53

a javelin formula is more of a declarative way to establish an invariant

micha21:01:03

and less of an event handler

micha21:01:11

the ratom seems more like an event handler

qqq21:01:33

this is kinda disguisting; but maybe I can use javelin / reagent / re-com

micha21:01:43

when you want to make complex things from small pieces the dependency graph becomes important

qqq21:01:51

so my dependency graph is expressed via javelin

qqq21:01:01

then at the edges of the javelin cells (i.e. the leaves with no children), I attacha reagent atoms

qqq21:01:08

those regent atoms then lets me use re-com ui elements

qqq21:01:23

this is frankenstein, but I like it

micha21:01:32

haha maybe it will work?

qqq21:01:42

I will let you know in a few hours 🙂