Fork me on GitHub
#boot
<
2015-06-20
>
juhoteperi09:06:01

Any Windows users? I fixed the most obvious problems with Perun and Windows

martinklepsch10:06:49

@juhoteperi: :thumbsup::thumbsup::thumbsup::thumbsup:

juhoteperi12:06:42

@micha: Fileset doesn't keep metadata from previous watch runs?

juhoteperi13:06:20

https://github.com/hashobject/perun/pull/29/files Pods for reloading the clj code for each run.

juhoteperi13:06:53

I'll probably add a check to only use new pod when clj or cljc files have been changed, should make it lot faster when only changing css or posts.

juhoteperi16:06:45

Does anyone know Java syntax highlighters?

juhoteperi16:06:46

I found Jygments but looks like it is not published on mvn

micha16:06:46

deraen: i have an example of using pygments in a jython pod, would that work for you?

juhoteperi16:06:22

Not sure. I think it would be easiest to transform the hiccup using postwalk on :code blocks.

juhoteperi16:06:32

But that might be hard with pods

micha16:06:45

i use pygments to generate cljs actually

micha16:06:47

for hoplon

micha16:06:01

s expressions can be converted to hiccup if you desire

micha16:06:25

i use pygments in a jython pod from a cljs macro

juhoteperi16:06:30

I guess I could create hiccup in one task and transform it using another and write to file in third

micha16:06:32

it rules, basically

micha16:06:46

the macro emits hoplon code

micha16:06:04

but underneath are functions you can use to emit whatever you need

micha16:06:17

one sec, i'll find it anyway

juhoteperi16:06:44

For now I'll just use highlight.js, I might get back to this later, probably highlightjs doesn't work in RSS anyway

micha16:06:04

this does it at compile time

micha16:06:23

i mean if you're using cljs where you have macros etc

juhoteperi16:06:55

Hyphenation would also very cool to have on blog.

micha17:06:29

i used to use hyphenate.js which worked really well

micha17:06:46

people complained that it made things appear to load more slowly

juhoteperi17:06:51

Pff, no need for JS

juhoteperi17:06:59

It can be done as build step

micha17:06:08

how can it know where to hyphenate?

micha17:06:22

without knowing how the browser will do the layout and typesetting?

juhoteperi17:06:39

Some task should just insert &shy; in the text and then browser can show the necessary hyphens.

juhoteperi17:06:51

It is a "soft-hyphen" it is not normally displayed

micha17:06:56

dude this is huge

micha17:06:06

i want this immediately

micha17:06:20

it's so much nicer to read properly typeset prose

juhoteperi17:06:26

Then start looking what Java lib could be used to hyphenate the text

juhoteperi17:06:41

I guess some apache lib will do it

micha17:06:02

man, this will be really awesome for my hoplon things

micha17:06:15

i can inject hyphenation at any level

micha17:06:23

lol uh oh

micha17:06:27

fop is my nemesis

juhoteperi17:06:23

It doesn't indeed to be a pure hyphenation lib 😄

micha17:06:34

how do you mean?

juhoteperi17:06:02

"Apacheâ„¢ FOP (Formatting Objects Processor) is a print formatter driven by XSL formatting objects (XSL-FO)" I have no idea what it is supposed to do

micha17:06:17

i was imagining a function in a pod that you can call, pass in a string and you get a string back with &shy; in there

micha17:06:34

you can then incorporate that into macros or whatever

micha17:06:54

i guess pass in string + language or something

micha17:06:12

or maybe it's smart enough to detect language on its own

micha17:06:32

since it's working via dictionaries it should be able to tell which dictionary to use

micha17:06:56

if you need hyphenation you'll have enough text that it will be unambiguous

juhoteperi17:06:57

Where are the FOP Api docs

micha17:06:13

man i had some bad times with fop

micha17:06:01

we should just make a pure clojure implementation of liang

micha17:06:21

it would be quicker than setting up fop and their utter nonsense

juhoteperi17:06:37

It is a shame that (afaik) cló code is not available: https://www.youtube.com/watch?v=824yVKUPFjU

micha17:06:15

look at the python

micha17:06:27

it's just a one page clojure program

juhoteperi17:06:34

Yeah that looks simple enough to implement in Clj

micha17:06:39

i'm sure it'll fit on a single gist

juhoteperi17:06:02

Just make clj-hyphenate

micha17:06:55

the young donald knuth looks like the nerd from the big bang theory show

micha17:06:59

which i hate, of course

micha17:06:36

also the pic of him at that organ

micha17:06:47

that looks like a pretty awesome machine

juhoteperi17:06:02

Do you want to convert the hyphenate.py to clj or should I do it?

micha17:06:28

i'm still reading the paper

micha17:06:40

so please feel free to doit simple_smile

micha17:06:06

i'm not that familiar with python

juhoteperi17:06:01

Okay. I visited toilet so I have a great idea about the API 😄

micha17:06:19

haha, the "idea factory"

micha17:06:47

do you do any ruby stuff?

micha17:06:14

i'm overhauling the ruby client for the adzerk api

micha17:06:23

looking at swagger maybe

juhoteperi17:06:56

I'm writing Clj/Cljs/JS/Bash/Python/C++/C/Php nowdays (this order)

juhoteperi17:06:47

Luckily I don't have to touch php maybe more often that once a year

micha17:06:16

haha yeah

micha17:06:39

i actually prefer php to python or ruby honestly

micha17:06:04

i very dislike the way dynamic OOP works

micha17:06:18

like passing parameters to functions via inheritance

micha17:06:21

basically

micha17:06:35

my brain just doesn't work that way

juhoteperi17:06:54

In my experience quite lot of existing php stuff uses OOP heavily

micha17:06:07

yeah i dislike that too, lol

juhoteperi17:06:24

It is possible to write functional code is python too

micha17:06:37

i worked a lot on older php apps

micha17:06:52

the worst thing you find there is just completely unstructured code

micha17:06:00

but everything else is just functions

juhoteperi18:06:31

I wonder if it would be better to convert Hypnator.js algorithm, it would support multiple languages

juhoteperi18:06:31

90% of the 3000 lines code there would be unnecessary

micha18:06:17

yeah i think so

micha18:06:22

it's using liam too

micha18:06:45

i mean liang

micha18:06:21

reading the liang paper i'm wondering if a dictionary approach might be feasible with modern computing power

micha18:06:34

for latex they needed to make it fast on weak machines

micha18:06:57

so they use a heuristic algorithm

micha18:06:56

hmm, i don't see readily available hyphenation dictionaries in google

juhoteperi18:06:51

Wouldn't work in e.g. finnish

micha18:06:25

presumably there is a dictionary for finnish that includes hyphenation points

juhoteperi18:06:39

because there are around 1000 inflections for each word so dictionary would be very large

micha18:06:56

large things are easy to work with in java

micha18:06:07

on the order of large for language anyway

micha18:06:47

i mean if i look up a word in a finnish dictionary it doesn't have the syllables separated out?

micha18:06:57

english dictionaries do

micha18:06:09

dic-tion-a-ry

juhoteperi18:06:12

Yeah but the dictionary would be impractically large

juhoteperi18:06:36

Voikko, the Finnish hyphenator and grammar checker implements the inflection rules etc.

micha18:06:12

but a js script hyphenates correctly?

juhoteperi18:06:26

I doubt it is perfect

juhoteperi18:06:40

For Finnish it uses Voikko simple_smile

micha18:06:07

it uses that to generate some configuration for a more general purpose hyphenation engine, right?

micha18:06:31

i see a patgen(1) program in there

micha18:06:51

proper hyphenation makes a huge difference imo

juhoteperi18:06:53

I'm not sure. OO options lists multiple different hyphenators.

micha18:06:33

having paragraphs that are visually regular with lines that don't have to be too long

micha18:06:57

so much more restful and easy to read

juhoteperi18:06:56

Probably simple rules work quite well for Finnish but e.g. compound words require that the algorithm understands loads of rules.

micha18:06:55

don't tell me, there are 27 words for sauna in Finnish?

micha18:06:57

word inflection, does english have anything similar?

juhoteperi19:06:00

@micha: Nouns have 15 inflections. But you can also make a verb: "saunoa" (go to sauna), and verbs have some hundreds of forms ( http://wiki.verbix.com/Verbs/AllFormsOfFinnishVerb#toc5) http://www.verbix.com/webverbix/Finnish/saunoa.html

podviaznikov21:06:31

anyone using boot on heroku? is this buildpack https://github.com/pandeiro/heroku-buildpack-boot/ way to go?

micha21:06:51

podviaznikov: another one i know of is here https://github.com/upworthy/heroku-buildpack-boot

micha21:06:02

i haven't deployed anything to heroku lately though

micha21:06:18

so i don't know which ones have which features, etc

podviaznikov21:06:26

Thanks @micha. Trying the one from upworthy now. Seems to work so far. The first one I posted doesn’t work and has few unmerged PRs.

micha21:06:47

i think pandeiro was waiting for 2.0.0 to be released

micha21:06:15

podviaznikov: perun looks great btw!

micha21:06:41

podviaznikov: i hope to investigate it for a project i have coming up soon

micha21:06:14

we haven't decided yet whether we want to go with static or spa yet

podviaznikov21:06:51

thanks @micha! perun has very small codebase because of boot which gives composition of tasks and filesystem model

micha21:06:37

prismic is like a CMS with just an admin interface and a JSON API

micha21:06:42

no frontend

micha21:06:06

but it has a good admin interface with support for a professional style publication workflow

micha21:06:30

and pretty good support for defining content types, tagging, structured content, etc

micha21:06:50

also the publication model is basically the git workflow

micha21:06:02

all content is immutable and content-addressed

micha21:06:12

all cached to CDN etc

micha21:06:32

uses a hypertext REST model

micha21:06:04

(i.e. you discover the current HEAD via a special URI, but everything from there on out is URIs pointing to immutable resources)

micha21:06:22

with hyperlinks from one resource to related ones

micha21:06:05

also it's CQRS, which of course I'm instantly down with

micha21:06:52

one option we have is to use perun to build a static site for each prismic "commit"

micha21:06:45

perun's decoupling of composable modules makes it easy for us to implement such a thing i bet

micha21:06:12

have some task that transpiles prismic json --> input for perun

podviaznikov21:06:45

so it’s seems that http://prismic.io is similar to https://www.contentful.com/. There is metalsmisth plugin for contentful (https://github.com/contentful-labs/contentful-metalsmith) which pulls json data from API and passes to other tasks. Seems like totally doable with perun model

micha21:06:13

the killer feature of prismic is the admin ui and workflow

micha21:06:27

that's what i mean about cqrs in this context

micha21:06:33

you don't just read and write

micha21:06:10

when you write you do it via a workflow that is completely decoupled from the api you use to retrieve resources

micha21:06:31

it has support for the editing, approval, publishing workflows

micha21:06:49

publishing things at specific times or intervals

micha21:06:14

with a ui that creative and management folks can use to do everything they need

micha21:06:39

but at the same time it doesn't have any customer-facing ui at all

podviaznikov21:06:02

workflow, versioning and also pricing for prismic sounds really god. Going to investigate it more. It’s sounds like super useful tool. Also reading about CQRS now (http://martinfowler.com/bliki/CQRS.html)

micha21:06:43

or re-frame

micha21:06:25

the idea that the "shape" of writes can be completely decoupled from the shape of the data you read

micha21:06:50

writes are basically opaque commands to a black box

micha21:06:11

that may or may not result in a change in something you can read

micha21:06:40

there is no structural coupling between the two

micha21:06:16

datomic is also a cqrs architecture i would say

micha21:06:38

the peers are able to get the current state of the database whenever they like

micha21:06:51

they are decoupled from the transactor

micha21:06:13

to write you send a command to the transactor to perform some operation

micha21:06:27

when you do that you don't get data in the response

micha21:06:39

you get only whether the command was accepted or not

micha21:06:02

the peers asynchronously learn about changes to the database state via a side channel

micha21:06:14

that is completely separate from the transactions and command

micha21:06:45

it's a really powerful pattern for distributed computing i think

podviaznikov21:06:27

Martin Fowlers’ blog is interesting (need to read more about topic). So you are saying that hoplon implementation can be described as CQRS? I see that separate blocks (blue) are responsible for storing data and also separate(red) for querying?

micha21:06:01

that diagram is hoplon+castra

micha21:06:07

castra is the rpc framework

micha21:06:14

the blue lines are the commands

micha21:06:21

the red are queries

micha21:06:40

note that in the app everything is either red or blue, except for one part

podviaznikov21:06:55

yes, I noticed that

micha22:06:10

the one part that is both is simply managing an async command that is really two separate things

micha22:06:17

which you can see in the backend diagram

micha22:06:32

with castra you make a function in your backend like #'my.ns/foo

micha22:06:45

you ues the castra ring middleware to export that via rpc

micha22:06:14

the castra clientside library lets you define a rpc stub function, (castra/mkremote 'my.ns/foo {...})

micha22:06:19

actually no

micha22:06:52

(def foo (castra/mkremote 'my.ns/foo query-cell error-cell loading-cell {...}))

micha22:06:09

that defines a function foo that you can call like a regular cljs function

micha22:06:23

like (foo 100 {:a "map" :of "things"} :etc)

micha22:06:34

it calls the function on the backend which is the command in cqrs

micha22:06:50

that function might write to the database or do whatever it does, for side effects only

micha22:06:04

however, associated with that foo function on the backend is a query

micha22:06:17

the query is completely decoupled from foo, it shares nothing

micha22:06:37

that query is over the database, it returns the state of the database after the command compeltes

micha22:06:05

the query-cell, error-cell and loading-cell parameters we passed to mkremote are javelin cells

micha22:06:10

like spreadsheet cells

micha22:06:27

query-cell is where the result of the cqrs query goes

micha22:06:44

sometimes the query returns a value thta is the same as before

micha22:06:51

i.e. the command didn't change anything

micha22:06:05

in that case it's just like a spreadsheet; nothing in the app changes either

micha22:06:42

if, however, the new value of the query-cell is different then updates will propagate to all formulas that reference that cell

micha22:06:53

you can see those as the red lines and red boxes in the diagram

micha22:06:15

the main idea here is that in the client the foo function doesn't return data

micha22:06:35

it might result in the query-cell getting a new value asynchronously

micha22:06:40

but again it might not

micha22:06:50

and the thing that calls foo doesn't need to know about any of that

micha22:06:17

this completely transforms the architecture and dataflow in the client

micha22:06:42

with mvc you have controllers that push changes to different parts of the application as messages basically

micha22:06:06

in a hoplon app parts of the application synchronize around cells instead

micha22:06:14

so there isn't a top-down controller tree

micha22:06:30

there is a graph instead

micha22:06:46

so the login rpc function might be called by a login widget

micha22:06:01

this widget doesn't know anthing about what to do if login succeeds

micha22:06:28

but the login rpc function might be storing a query in a cell like user-data

micha22:06:36

which is a query over the backend db for this user

micha22:06:50

when login succeeds on the backend that query will now return data

micha22:06:57

if you're not logged in the query returns nil

micha22:06:42

so when the login rpc function is called by the widget, if login succeeds the user-data cell will contain a map like {:login "micha" :name "Micha Niskin" :admin? false ...}

micha22:06:48

or something

micha22:06:16

so i could have the login widget inside another widget, which removes itself when user-data isn't nil

micha22:06:24

via a formula cell

micha22:06:57

in hoplon you'd do like (div :toggle (cell= (not (empty? user-data))) ...)

micha22:06:42

what's cool about this is that the different parts of the UI are synchronizing around cells that are completely separate from each other

micha22:06:53

each cell represents some part of the appliaction state

micha22:06:24

the login widget doesn't need to know about any other part of the application

micha22:06:30

each part manages its own state

micha22:06:48

and they respond to these cells

micha22:06:20

one cool consequence of this is that you can totally package a workflow in a JAR

micha22:06:38

backend rpc functions + frontend remotes and "stem cells"

micha22:06:58

you can even knit together multple jars like this into one application

micha22:06:17

just like you can make charts that pull data from multiple worksheets in excel

micha22:06:35

in hoplon the UI is essentially a chart over spreadsheet cells and formulas

micha22:06:30

the "stem cells" are basically formula cells whose values come from queries over the backend db

micha22:06:45

when the result of these queries changes those cells update

micha22:06:57

and the rest of the formulas and charts (ui) update accordingly

podviaznikov22:06:33

I think now I understand how hoplon works:) which is good because it means it’s approachable and model is not complex. I’d like to try it in some project. looking into demos now: http://tailrecursion.github.io/hoplon-demos/

micha22:06:42

the goal of hoplon is to make it possible to create libraries of custom elements that compose, and the designer assembles these into an application

micha22:06:59

not the designer really, but the person implementing new parts of the app

micha22:06:26

each custom element exposes attributes that control its state and behavior

micha22:06:38

the programmer would hook these up to cells

micha22:06:49

and custom elements can have children like any dom element

micha22:06:13

the cells you set as attributes can be anonymous

micha22:06:16

which is huge

micha22:06:24

that's what makes composability possible

micha22:06:52

compare to cursors in om or the way react apps need state to flow down through a tree from the root

micha22:06:59

nothing can be anonymous there

micha22:06:07

which means you can't make higher order abstractions

micha22:06:29

our hoplon applications are assembled, not programmed

micha22:06:47

the application itself is simply a composition of custom elements

micha22:06:26

behind the application itself are libraries of custom elements which can involve some pretty complex programming

micha22:06:52

(google-map
            :css                  {:height "600px"
                                   :width  "100%"
                                   :margin "0 auto"
                                   :border "1px solid red"}
            ::m/center            san-francisco
            ::m/markers           pins
            ::m/polygons          polyline
            ::m/marker-click      #(bounce-marker %2)
            ::m/marker-rightclick #(.log js/console %1 %2 %3 %4 %5)
            ::m/map-click         #(.log js/console %1)
            ::m/map-rightclick    #(do (.log js/console %2) false)
            ::m/fit-pins          auto?
            ::m/opts              opts
            ::m/layer-bicycling   true)

micha22:06:31

most of those attributes are assigned to cells that change over time

micha22:06:43

the map and pins etc update accordingly automatically

podviaznikov23:06:54

going to try hoplon in the next side project for sure. Thanks for the intro and explanation of benefits