day8 / re-frame

A ClojureScript framework for building user interfaces, leveraging React
http://day8.github.io/re-frame/
MIT License
5.41k stars 715 forks source link

Yes! #2

Closed StefanScott closed 8 years ago

StefanScott commented 9 years ago

Hi -

I would like to congratulate you on this new project, and I am eagerly looking forward to your progress.

I don't have much experience yet programming ClojureScript and Reagent, but I've been reading up on this stuff for the past few months, and I hope start getting more involved soon once I understand it better.

I must say that the ReadMe for re-frame was one of the best tutorials I've ever seen on this subject.

Re-frame gets so many things right!

Prefers reagent instead of the other Clojurescript/React libraries... yes!

Views CRUD as a kind of discrete, dynamic, asynchronous, push FRP... yes!

Avoids om's cursors... yes!

Defines a single db (like an SQL schema) rather than a bunch of classes (like in O-O)... yes!

Pays homage to elm-lang... yes!

Views a ratom not as immutable data, but as a value that changes over time (eg, a signal)... yes!

Nice long conceptual / tutorial ReadMe... yes!

"So much incidental complexity evaporates."... yes!

The re-frame ReadMe is one of the best tutorials available regarding FRP-like programming

I must say, this is the first time I every really "got" all this stuff about React, FRP etc. - and I've been reading everything I can get my hands on for months (Elm-lang, Bacon, ThreePenny, Apfelmus, Reactive Banana, the various React / Flux frameworks and libraries, the various ClojureScript wrappers over them).

This lengthy, well-thought-out, heavily referenced, clearly written ReadMe which you have provided is a major contribution to the understanding of "reactive" programming in the browser. This is a new topic, which many front-end JavaScript programmers are struggling with as people try to make the transition from MVC to something resembling FRP.

People are coming up against a lot of conceptual barriers - and the excellent tutorial which you provided will clear up a lot of confusion. It was a big help to me. In fact, it's the first time I ever really "got" what's going on with FRP-like programming. (In my case, the lightbulb lit up when I realized that re-frame's computation is similar to a "dependency" in an older version of the functional language K I had studied years back - more details on this below. Somehow this had never occurred to me while reading any of the other tutorials and papers on FRP. But re-frame's ReadMe really helped make the connections.)

Related concepts in theoretical computer science

Ultimately I suspect that the asynchronous event-handling we're dealing with in JavaScript front-end frameworks and libraries involves what some theoretical computer scientists call "co-algebraic process types" (perhaps also called "streams" in other contexts) - which would be dual to "algebraic data types".

The "alegbraic data type" literature has percolated from academia to the world of practical programming - we do induction on algebraic data types all the time, it's called "recursion".

But the "co-algebraic process type" literature remains pretty much only in the academic world, and we don't often (explicitly, formally) do "co-induction" on "co-algebraic process types" - which seems to be what the older MVC JavaScript front-end frameworks (as well as the newer React/Flux JavaScript front-end frameworks) are (somewhat informally or naïvely) trying to deal with.

https://www.google.com/?gws_rd=ssl#q=coalgebra+streams+jan+rutten+nijmegen

A related implementation in an older version of the K language

Meanwhile, a blast from the past:

You may have heard of a language called K - a tiny, lightning-fast, functional, vector-processing (or columnar database) interpreted language in the APL family, also somewhat related to LISP. It's not very well known, but it's used by a handful of investment banks. Anyways, an earlier version of K happened to include a feature called "dependencies" (as well as "triggers"). It's interesting to note that a dependency in K appears to be fairly similar to a computation in re-frame (or a signal in elm-lang, etc.).

Below is an archived PDF of an early version of the K reference manual, which describes "dependencies":

http://web.archive.org/web/20050504070651/http://www.kx.com/technical/documents/kreflite.pdf

You can search the PDF for occurrences of "dependenc" (to match either "dependencies" or "dependency") as well as "trigger".

A time-limited trial version of the K interpreter may still also be floating around online somewhere. I can also send a copy if anyone is interested. There is also a newer version of the language out now, called Q or KDB, which also has a trial version, but it no longer includes the wonderful dependency / trigger features of that earlier version of K. The newer version does however apparently implement something similar, called views. I imagine they got rid of dependencies and triggers in K because they also involved a native GUI (in Windows and Linux), which actually worked fine at the time, but which might have been a hassle to keep up-to-date with OS upgrades.

There is also a simple example of a dependency in K on this page:

http://88.97.16.226/apl/APL/Reviews/kreview.htm

A major development in front-end programming

It is encouraging to see that web front-end developers now starting to use these efficient and easy-to-reason-about "dataflow" constructs / architectures which have occasionally popped up in a few functional languages in the past.

This is one of the things that makes ClojureScript such a great language: functional / immutable data structures + the syntactic power of LISP (able to manipulate abstract syntax trees directly by defining macros). You always have the abstract syntax tree available, parsable - so you can define something like re-frame's computation macro to act on it, and have the computation macro implement this sort of dataflow or FRP style of programming (instead of doing something clunky in a language which merely lets you call eval on a monolithic - ie, unparsed - string).

mike-thompson-day8 commented 9 years ago

@StefanScott Those are kind and encouraging words, many thanks! And I'm completely delighted that you found the readme helpful. Made my day.

Surprisingly, I have programmed a bit in k, q, and j (the children of APL), but mostly q over the last 10 years. But I never realised that Arthur Whitney had put this dependency feature into early k. He's a very impressive guy. (I just wish I could read his code).

I've had a quick look at "co-algebraic process types" and frankly I'm intimidated. :-) It will take me some time to wrap my head around it. But thanks for the pointer!!

StefanScott commented 9 years ago

Wow, that's so interesting that you've programmed in k, q, and j. There are some interesting examples at nsl.com (no stinkin' loops) showing a couple of spreadsheets programmed in the old version of k, which made use of the dependency feature. The programs are really short - less than a page each.

http://nsl.com/papers/spreadsheet.htm

The syntax x..d:"a+b" says that whenever a or b changes, x will be re-computed to equal a+b. It's a bit shorter than in ClojureScript / Reagent / re-frame - but in k, it's defined as a monolithic string (ie, it's not parsed), whereas in ClojureScript / Reagent / re-frame it's already a (parsed) abstract syntax tree.

I also have a hard time wrapping my head around about co-induction on co-algebraic process types, but there are some introductory papers by Jan Rutten which can make it a bit more accessible.

http://homepages.cwi.nl/~janr/papers/files-of-papers/2011_Jacobs_Rutten_new.pdf

I imagine there is some sort of analogy (duality?) between composing functions on algebraic data types and composing observers (or listeners? or consumers?) on co-algebraic process types (also sometimes called "streams") - and this may be why the FRP-like approaches are so expressive and powerful and easy to reason about.

Doing induction (recursion) on algebraic data types is pretty commonplace now in functional languages - and I think FRP-like approaches might be intuitively certain things which would be like co-induction (co-recursion?) on co-algebraic process types in "FRP-like" languages.

Just as languages such as Clojure, J, K, and Q have a handy higher-order functional "reportoire" of constructs for composing functions on algebraic data types in various ways (eg, map, foldr, foldl, scan, etc. - called "adverbs" in J and K), perhaps someday a repertoire will be developed of higher-order constructs for composing observers (or listeners or consumers?) on co-algebraic process types - maybe also taking inspiration from Tony Hoare's CSP (or Robin Milner's CCS).

I believe the async library in Clojure was explicitly based on CSP for instance, and something like this is also used in Elang and GoLang.

I also recall that the most successful approaches in this area (another example might be Unix pipes) treat named (and sometimes also typed) channels as first-class citizens.

What's going on in browsers seems to mainly involve processes or streams of events (although there is also data of course). As we know, it can lead to spaghetti code of observers and listeners in callback hell.

This might indicate that approaches involving co-algebraic process types could help bring some mathematical clarity to front-end development. In particular it is interesting how the terminology "observer" is used in front-end development, and "observational equivalence" (and something called "bisimulation") appears in co-algebras.

https://www.google.com/?gws_rd=ssl#q=bisimulation

I have only dabbled in co-algebra myself, but I am intrigued how several of the concepts in your presentation of re-frame (using ClojureScript and Reagent and ideas from FRP languages such as Elm-lang - and independently re-inventing the dependency construct from an earlier release of Arthur Whitney's K) are rather suggestive of how there might be some interesting relationships between front-end JavaScript browser development and co-induction on co-algebraic process types (or "streams").

jhund commented 8 years ago

@mike-thompson-day8 I'm just getting up to speed with re-frame, and I want to second that your tutorial is fantastic. I love the conversational tone and the great references. I have mostly stayed away from front-end development for the last few years, however seeing re-frame gets me excited and wanting to dive in. It's so clean and makes so much sense. Thanks again for this great tool.

mike-thompson-day8 commented 8 years ago

I've left this issue open longer than I should have, probably because it provided some early validation, and was motivating. But, given it doesn't actually represent an issue, I really should do the right thing tidiness-wise and close it.

Samstiles commented 8 years ago

If it means anything Mike, I'm another user and agree with all of the above :) chatting about reframe in my talk this week at a conference because I'm so excited about it :)

ericfode commented 8 years ago

Me too! I have used reframe on a few projects now, and it makes me smile every time. (Especially after being tortured with plain JS). Your the best!

ioRekz commented 8 years ago

I'm using re-frame for my last 5 projects and it's so cool. Make me smile while looking people getting excited on redux

On Fri, Jun 3, 2016 at 7:37 PM, Eric Fode notifications@github.com wrote:

Me too! I have used reframe on a few projects now, and it makes me smile every time. (Especially after being tortured with plain JS). Your the best!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Day8/re-frame/issues/2#issuecomment-223643781, or mute the thread https://github.com/notifications/unsubscribe/AAqChhunDTszo7oGE2ThOTogjPeFQEKsks5qIGZfgaJpZM4Dj4X6 .