Giter Club home page Giter Club logo

Comments (13)

paldepind avatar paldepind commented on June 28, 2024

Sorry for taking so long to answer you question. I'm happy to hear that you think of Flyd as begin the sanest FRP library :)

Your project sounds very interesting!

My question for you is how to do this while still maintaining an easy to inspect, freeze, restore, debug concept of state. Are there any state libraries or techniques that go really well with flyd.

One thing I can say is that all Flyd streams have their current value stored in a property named val. Now, I don't know how you do you inspection. But if you do some form of inspection in a JavaScript debugger the value is right there to look at.

I'm currently working on implementing the Elm architecture in JavaScript with Flyd. When using that architecture the entire application state is handled in a single stream in a purely functional way. You then pass this stream through a render function that creates a virtual DOM tree based on the data and applies it to the real DOM.

Since all data is in one stream you can log the entire application state to the console or serialize it to JSON for inspection or persistence. You can also store the entire history and do time travel for debugging purposes. Your question is quite vague so I'm not sure, but it might be something like that you're after. I personally think it's an impressive technique and I'm very excited about it. If it sounds interesting to you I will write some more about it! :)

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

Thanks for responding!

I am very interested in static signal graphs and am currently watching Evan
Czaplicki's talk on them at https://www.youtube.com/watch?v=Agu6jipKfYw.
I think right now I am still learning and using intuition about which part
of FRP land is worth my time and I really apologize for the vagueness.

I would love to hear more from you on what you are doing because it sounds
exactly like what I want. I am very keen to log, inspect, and save the
entire application state as I find that technique to really increase safety
and the ability to debug my apps for clients.

What I am working on with Play is very similar as you can output a render
stream as well. I output keys and values instead of JSON or any other
data structure because I find them very easy to save and work with across
heterogenous environments like the iPhone, Mac, and a JS interpreter. In
general I am trying to build something that works with simple, easy to
inspect, serialize and debug streams and pure functions. I am interested
in as little magic as possible and as much safety and flexibility as
possible.

Please share more if you can and again many thanks!

On Fri, May 15, 2015 at 10:48 AM, Simon Friis Vindum <
[email protected]> wrote:

Sorry for taking so long to answer you question. I'm happy to hear that
you think of Flyd as begin the sanest FRP library :)

Your project sounds very interesting!

My question for you is how to do this while still maintaining an easy to
inspect, freeze, restore, debug concept of state. Are there any state
libraries or techniques that go really well with flyd.

One thing I can say is that all Flyd streams have their current value
stored in a property named val. Now, I don't know how you do you
inspection. But if you do some form of inspection in a JavaScript debugger
the value is right there to look at.

I'm currently working on implementing the Elm architecture
https://github.com/evancz/elm-architecture-tutorial in JavaScript with
Flyd. When using that architecture the entire application state is handled
in a single stream in a purely functional way. You then pass this
stream through a render function that creates a virtual DOM tree based on
the data and applies it to the real DOM.

Since all data is in one stream you can log the entire application state
to the console or serialize it to JSON for inspection or persistence. You
can also store the entire history and do time travel for debugging
purposes. Your question is quite vague so I'm not sure, but it might be
something like that you're after. I personally think it's an impressive
technique and I'm very excited about it. If it sounds interesting to you I
will write some more about it! :)


Reply to this email directly or view it on GitHub
#23 (comment).

from flyd.

paldepind avatar paldepind commented on June 28, 2024

I am very interested in static signal graphs and am currently watching Evan
Czaplicki's talk on them at https://www.youtube.com/watch?v=Agu6jipKfYw.
I think right now I am still learning and using intuition about which part
of FRP land is worth my time and I really apologize for the vagueness.

Since JavaScript isn't a pure language you can create all the streams you want. But if you choose to do so you can use only static streams and will thus get a static signal/stream graph as well.

If you can read Elm code I think you should take a look at [the tutorial on the Elm architecture](Elm architecture). Even if you can't going through it might be beneficial as well. With that architecture you will in every application have a signal/stream called model that contains the entire application state. The state is advanced by actions that typically will come from the view (DOM event for instance).

I have translated the first three examples in the before mentioned tutorial to JavaScript. I will wrap them up and post them tomorrow.

I output keys and values instead of JSON or any other
data structure because I find them very easy to save and work with across
heterogenous environments like the iPhone, Mac, and a JS interpreter.

How do those key value pairs look? How are they different from JSON (JSON objects are made up of key value pairs as well)? How do you turn them into a view?

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

It looks what you are doing in JS what this fella is doing in ClojureScript. https://github.com/jamesmacaulay/zelkova

I can’t wait to see your examples tomorrow!

Play is an app that lets a user configure visually (or write in the editor) simple functions called plays that emit one or more key value pairs to the playground. Play is built to allow much of the UI to be built visually. But taking a look at the underlying code every play is a simple function of the form:

play(playground:dict, input:dict) -> dict

Here is some sample output from a play (plays can currently be written in Obj-C or JS).

{
  "render": {
    "row": "layout.flex",
    "row.layout.flexDirection": "row",
    "row.view1": "ui.view",
    "row.view1.input.backgroundColor": "red",
    "row.view1.layout.width": "100",
    "row.view1.layout.height": "100",
    "row.view2": "ui.button",
    "row.view2.input.backgroundColor": "yellow",
    "row.view2.layout.width": "50",
    "row.view2.layout.height": "50",
    "row.view2.input.text": "Click Me"
  },
  "store": {
    "selectedView": "view1"
  },
  "play": {
    "root.helloWorld": "js.helloWorld",
    "root.helloWorld.input.message": "Hi World"
  }
}

Notice that we are using batches of key-values. Why not just use full blown deeply nested JSON? For a few pragmatic (perhaps crazy) reasons.

  • Encourage thinking in keys. Keys are fantastic ways to identify things :), like views.
  • Naming can take place in data and not just code, needed for the UI driving approach Play espouses.
  • Use only strings, no need to worry about interpreting the data until it reaches it's final source.
  • Store data in a KVC store like a SQLite table or RocksDB.
  • Keys can be sorted and this sort can match UI structure or layout structure.
  • Every language can handle simple dictionaries.
  • Don't deeply nest data, easier for debugging
  • Don't have to maintain deeper data structures than dictionaries.
  • Keys help during UI transitions to make sure elements are identified that need to stay on screen.

Batches are primarily ways for plays to tell the playground the intention of their function. Instead of having a framework that calls render like React, we create a very general framework that just calls functions and then can do high level things with it like rendering, data storage, and kicking off other plays.

The first batch you see above is a render batch. This data is intended for rendering. The playground differs these keys with the play's last render batch, to create a new render batch that is sent to a layout object and then a renderer. After the diff, Play will forward to a renderer a processed batch like the following:

{
"viewsToRemove": {},
"viewsToAdd":  {
   "root.view1": "ui.view",
   "root.view1.view2": "ui.button"
},
"viewFramesToUpdate": {
   "root.view1": "{0,0, 100, 100}",
   "root.view1.view2": "{0,0, 50, 50}"
},
"viewPropsToUpdate": {
  "root.view1.input.backgroundColor": "red",
  "root.view2.input.backgroundColor": "yellow",
  "root.view2.input.text": "Click Me"
}
}

All the layout has taken place so there are no keys with layout. Play comes with a css flexbox layout system, and now the renderer knows exactly what to render. I have a renderer for iOS, Mac and Web under development. The renderers simply have to place the views on screen in absolute position with the right properties. This also illustrates an important design goal of Play and "batches of keys" approach. Processing occurs in stages and different actors only get batches of things they need.

Plays can also store data in the playground, read data from the playground and call other plays. This is a basic mechanism of global state.

The batch type play is a way for plays to call other plays. In the example above the play is calling another JavaScript based play helloWorld and passing it an input message. The keys facilitate this easily.

Open questions I have.

  • Should I stream the keys through the plays or let the plays iterate over keys in the playground? That is why I am here in your project to learn the benefits of streaming.
  • How to make writing keys more safe? Should I serialize the writes in a queue, how to make things atomic?
  • How to handle threads? Should each playground run in one thread (GCD queue on Mac) or should I have special batches of keys that are moved to background threads for processing?
  • How to make everything super explicit, debuggable, replayable?

from flyd.

paldepind avatar paldepind commented on June 28, 2024

@mrjjwright I've been coding like a crazy all day :) I don't have time to write much right now. But my JavaScript translation of three out of the four examples in the Elm architecture tutorial are available here.

In all of the examples the entire state lives in a single stream. Here, here and here. I've also added a commented out logger to each of the examples.

Every state change is triggered by an action from the action stream (named action$) in the code. Every state change is applied by the update function. All functions are pure and the number of streams is kept to a minimum. You can read more about the benefits here.

Please ask all the questions you might have. I'll write more later – including a reply to your last comment.

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

Don’t worry about responding to my posts. I am just a newb trying to translate the principles of pure functions, immutability, and explicit side affects to something practical I can use in my day to day apps. I would rather learn from what you have here.

I have been anxiously awaiting these and now I am digesting them. So exciting! Great work, more feedback later.

On May 16, 2015, at 11:24 AM, Simon Friis Vindum [email protected] wrote:

@mrjjwright https://github.com/mrjjwright I've been coding like a crazy all day :) I don't have time to write much right now. But my JavaScript translation of three out of the four examples in the Elm architecture tutorial are available here https://github.com/paldepind/noname-functional-frontend-framework/tree/master/examples/counters.

In all of the examples the entire state lives in a single stream. Here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/1/main.js#L35, here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/2/main.js#L43 and here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/3/main.js. I've also added a commented out logger to each of the examples.

Every state change is triggered by an action from the action stream (named action$) in the code. Every state change is applied by the update function. All functions are pure and the number of streams is kept to a minimum. You can read more about the benefits here http://elm-lang.org/learn/Architecture.elm.

Please ask all the questions you might have. I'll write more later – including a reply to your last comment.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

What, you created a new faster vdom lib! You are on fire.

On May 16, 2015, at 11:24 AM, Simon Friis Vindum [email protected] wrote:

@mrjjwright https://github.com/mrjjwright I've been coding like a crazy all day :) I don't have time to write much right now. But my JavaScript translation of three out of the four examples in the Elm architecture tutorial are available here https://github.com/paldepind/noname-functional-frontend-framework/tree/master/examples/counters.

In all of the examples the entire state lives in a single stream. Here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/1/main.js#L35, here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/2/main.js#L43 and here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/3/main.js. I've also added a commented out logger to each of the examples.

Every state change is triggered by an action from the action stream (named action$) in the code. Every state change is applied by the update function. All functions are pure and the number of streams is kept to a minimum. You can read more about the benefits here http://elm-lang.org/learn/Architecture.elm.

Please ask all the questions you might have. I'll write more later – including a reply to your last comment.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

Converting my app to flyd. I love it, I was trying way too hard and this is making everything really simple.

On May 16, 2015, at 11:24 AM, Simon Friis Vindum [email protected] wrote:

@mrjjwright https://github.com/mrjjwright I've been coding like a crazy all day :) I don't have time to write much right now. But my JavaScript translation of three out of the four examples in the Elm architecture tutorial are available here https://github.com/paldepind/noname-functional-frontend-framework/tree/master/examples/counters.

In all of the examples the entire state lives in a single stream. Here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/1/main.js#L35, here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/2/main.js#L43 and here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/3/main.js. I've also added a commented out logger to each of the examples.

Every state change is triggered by an action from the action stream (named action$) in the code. Every state change is applied by the update function. All functions are pure and the number of streams is kept to a minimum. You can read more about the benefits here http://elm-lang.org/learn/Architecture.elm.

Please ask all the questions you might have. I'll write more later – including a reply to your last comment.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

Also I am using snabbdom which is working great so far, hope to extend it with support for some native props. And I am using LiveScript which I love as a great functional programming language.

I like that with flyd I can take my “batching” approach (representing side affects as batches of properties intended for layout, rendering, storage, mutation, etc…) and represent these as streams. Streams are very convenient for sending and receiving data from the native environment, something I need to do with my Mac and iOS apps as well.

On May 17, 2015, at 10:24 AM, John Wright [email protected] wrote:

Converting my app to flyd. I love it, I was trying way too hard and this is making everything really simple.

On May 16, 2015, at 11:24 AM, Simon Friis Vindum <[email protected] mailto:[email protected]> wrote:

@mrjjwright https://github.com/mrjjwright I've been coding like a crazy all day :) I don't have time to write much right now. But my JavaScript translation of three out of the four examples in the Elm architecture tutorial are available here https://github.com/paldepind/noname-functional-frontend-framework/tree/master/examples/counters.

In all of the examples the entire state lives in a single stream. Here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/1/main.js#L35, here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/2/main.js#L43 and here https://github.com/paldepind/noname-functional-frontend-framework/blob/master/examples/counters/3/main.js. I've also added a commented out logger to each of the examples.

Every state change is triggered by an action from the action stream (named action$) in the code. Every state change is applied by the update function. All functions are pure and the number of streams is kept to a minimum. You can read more about the benefits here http://elm-lang.org/learn/Architecture.elm.

Please ask all the questions you might have. I'll write more later – including a reply to your last comment.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

paldepind avatar paldepind commented on June 28, 2024

I've read through your post about your Play. Your project sounds very cool! I think you're on fire as well ;) Your project sounds like something that could be useful to a lot of people.

So, if I understand correctly, a play takes a dictionary representing the playground, a dictionary of input and returns a dictionary that represent all the things is want to be done? But it doesn't do anything itself – your system carries out the tasks?

Do you have a dictionary that represents the entire playground? If yes that is a bit like the model$ stream in the Elm architecture. Then you've ensured that inspection of the state will be very easy! But does a play receive the entire playground or only a part of it?

A play can invoke other plays with the play batch type. But how are plays invoked besides that?

In the Elm architecture external input always originate in the action$ and the module at the very top routes the action to other modules. The modules at the very top also passes along subsets of the data to other modules. This nesting of modules is fundamental. It ensures that a module will only receive te tiny subset of the global data relevant to it. It also ensures that modules will only receive the actions that I can and should handle.

LiveScript is indeed pretty cool!

I'm happy that you find my stuff useful. Don't hesitate to ask questions if you have any. I'll also have to let you know that I'm planning some small breaking changes to Snabbdom. I'll probably also rename it to fun-dom as well. It sounds more fun and indicates that it's really a library to work with the DOM in a more functional way.

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

You kind of drove to the heart of what I was struggling with in Play.

What I learned from Elm was the value of pure functions and all side affects being handled by the system. Hence the play in a Playground idea.

This weekend I converted the whole playground to be based on flyd streams and now I am using the full power of functional programming instead of trying to recreate some weird version of it. Instead of batches, I simply create streams that represent side effects like rendering and storing data. It is so much more natural and very powerful.

My goal is to create an editor that lets a user compose up their UI iteratively and visually with minimal code, dropping in pure functions that act on streams where appropriate, right inside the editor.

I am using snabbdom. Break whatever you want. I created a nice DSL (secret gist): https://gist.github.com/mrjjwright/5dbb76c925cd676e9c4a https://gist.github.com/mrjjwright/5dbb76c925cd676e9c4a.

Everything is super sloppy for me right now. My next steps are modularizing everyone as you said, hooking up my playground to React native rendering, my Mac document architecture and coming up with an approach to let user easily work with streams and create their own plays. Don’t try to understand too much, I will post updates as I get further along. Just want to show you how nice LiveScript is with flyd and snabbdom.

On May 18, 2015, at 10:05 AM, Simon Friis Vindum [email protected] wrote:

I've read through your post about your Play. Your project sounds very cool! I think you're on fire as well ;) Your project sounds like something that could be useful to a lot of people.

So, if I understand correctly, a play takes a dictionary representing the playground, a dictionary of input and returns a dictionary that represent all the things is want to be done? But it doesn't do anything itself – your system carries out the tasks?

Do you have a dictionary that represents the entire playground? If yes that is a bit like the model$ stream in the Elm architecture. Then you've ensured that inspection of the state will be very easy! But does a play receive the entire playground or only a part of it?

A play can invoke other plays with the play batch type. But how are plays invoked besides that?

In the Elm architecture external input always originate in the action$ and the module at the very top routes the action to other modules. The modules at the very top also passes along subsets of the data to other modules. This nesting of modules is fundamental. It ensures that a module will only receive te tiny subset of the global data relevant to it. It also ensures that modules will only receive the actions that I can and should handle.

LiveScript is indeed pretty cool!

I'm happy that you find my stuff useful. Don't hesitate to ask questions if you have any. I'll also have to let you know that I'm planning some small breaking changes to Snabbdom. I'll probably also rename it to fun-dom as well. It sounds more fun and indicates that it's really a library to work with the DOM in a more functional way.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

mrjjwright avatar mrjjwright commented on June 28, 2024

So to answer a couple more of your questions:

  1. The purpose of passing a read only view of the whole “playground" to each play was to allow each play to operate across the whole playground. The play could read any keyPath in the playground but writing only to keys under it’s keyPath, and the writing would be done as a request to the playground like other side effects. The idea was that this would mimic an Excel spreadsheet where you can read from any cell but only write to your own.

This may all seem silly and ignoring the principle that each module/component should only see the data that is relevant to them but the problem with that rule is a technique is needed to enforce it, techniques like a global atom with cursors, a stream/signal based approach or some other more language oriented approach. I was hoping in Play to have the only code be the pure play functions, which have no programming language environment except the playground and input they are passed. I don’t want to focus on building another programming language but a practical programming app. Imagine if Excel users were limited in what data they could read in a particular cell.

However, working in Flyd this weekend and with LiveScript has made me realize how useful functional programming can be and I admit to being a bit confused as to where to go next. I have some pressing client work and might have to abandon this all together for a while if I can’t get something extremely practical working soon.

  1. How do other plays get called besides being “called” by other plays (also done as a request to the playground since the type of play determines how it is called)? Well the only other way I considered is plays can listen to other keyPaths and the playground will run the play whenever data in the keyPath changes.

On May 18, 2015, at 10:22 AM, John Wright [email protected] wrote:

You kind of drove to the heart of what I was struggling with in Play.

What I learned from Elm was the value of pure functions and all side affects being handled by the system. Hence the play in a Playground idea.

This weekend I converted the whole playground to be based on flyd streams and now I am using the full power of functional programming instead of trying to recreate some weird version of it. Instead of batches, I simply create streams that represent side effects like rendering and storing data. It is so much more natural and very powerful.

My goal is to create an editor that lets a user compose up their UI iteratively and visually with minimal code, dropping in pure functions that act on streams where appropriate, right inside the editor.

I am using snabbdom. Break whatever you want. I created a nice DSL (secret gist): https://gist.github.com/mrjjwright/5dbb76c925cd676e9c4a https://gist.github.com/mrjjwright/5dbb76c925cd676e9c4a.

Everything is super sloppy for me right now. My next steps are modularizing everyone as you said, hooking up my playground to React native rendering, my Mac document architecture and coming up with an approach to let user easily work with streams and create their own plays. Don’t try to understand too much, I will post updates as I get further along. Just want to show you how nice LiveScript is with flyd and snabbdom.

On May 18, 2015, at 10:05 AM, Simon Friis Vindum <[email protected] mailto:[email protected]> wrote:

I've read through your post about your Play. Your project sounds very cool! I think you're on fire as well ;) Your project sounds like something that could be useful to a lot of people.

So, if I understand correctly, a play takes a dictionary representing the playground, a dictionary of input and returns a dictionary that represent all the things is want to be done? But it doesn't do anything itself – your system carries out the tasks?

Do you have a dictionary that represents the entire playground? If yes that is a bit like the model$ stream in the Elm architecture. Then you've ensured that inspection of the state will be very easy! But does a play receive the entire playground or only a part of it?

A play can invoke other plays with the play batch type. But how are plays invoked besides that?

In the Elm architecture external input always originate in the action$ and the module at the very top routes the action to other modules. The modules at the very top also passes along subsets of the data to other modules. This nesting of modules is fundamental. It ensures that a module will only receive te tiny subset of the global data relevant to it. It also ensures that modules will only receive the actions that I can and should handle.

LiveScript is indeed pretty cool!

I'm happy that you find my stuff useful. Don't hesitate to ask questions if you have any. I'll also have to let you know that I'm planning some small breaking changes to Snabbdom. I'll probably also rename it to fun-dom as well. It sounds more fun and indicates that it's really a library to work with the DOM in a more functional way.


Reply to this email directly or view it on GitHub #23 (comment).

from flyd.

dumblob avatar dumblob commented on June 28, 2024

@mrjjwright it seems you had some demo partially working, but I can't find it anywhere. Did you publish it? I find your approach quite interesting and would like to learn from the code you wrote.

from flyd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.