Re: [nodejs] new concept for structured asynchronous programming

468 views
Skip to first unread message

Mark Hahn

unread,
Dec 28, 2012, 3:34:48 PM12/28/12
to nodejs
I find it very interesting as I have always liked data-flow.

My main concern is that the processing of the analysis, particularly
the func.toString(), is going to slow down function execution by
orders of magnitude.

Also, there still seems to be a lot of boilerplate and the semantics
seem somewhat overwhelming for the simple end result.

From an academic standpoint it is fascinating, but I cannot see using
it in everyday code.

On Thu, Dec 27, 2012 at 5:03 PM, Alex ("Tatumizer") <tatu...@gmail.com> wrote:
> I'm trying to come up with a better concept for asynchronous programming. My
> first library (mesh.js) was an attempt to use a promising line of attack,
> but it introduced a lot of boilerplate, which no one liked (myself
> included)..
>
> After a lot of head-scratching, I found the way to eliminate all boilerplate
> and syntactic noise, and eventually came up with completely new design -much
> simpler one, and much more powerful: just two functions and their
> combinations do the job in most practical cases. I renamed the concept to
> "circuit" - it's a better name for this device.
>
> https://github.com/tatumizer/circuit/blob/master/README.md
>
> At this stage, it's a design doc only, specifically targeting nodejs. I
> think the concept of circuit could simplify nodejs programming..
> What is equally important that it uses all existing nodejs conventions and
> interfaces AS IS: no code generation, no wrappers, no conversions of f(x,y)
> into fubar(f,x,y) or anything - just pure nodejs code.
>
> I would be very interested to know opinions (even negative opinions) to
> improve design and find potential flaws.
>
> Thanks,
> Alex
>
> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines:
> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com
> To unsubscribe from this group, send email to
> nodejs+un...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en?hl=en

greelgorke

unread,
Dec 28, 2012, 4:05:32 PM12/28/12
to nod...@googlegroups.com
just a question: how differs your solution from https://github.com/caolan/async#series ?

Eldar

unread,
Dec 28, 2012, 4:10:18 PM12/28/12
to nod...@googlegroups.com
I have something similar called make-flow. Details are not documented yet but an example from circuit's Readme looks like
// definition
var app = Flow()
.def('sum1', function (done) {
add(1, 2, done)
})
.def('sum2', function (done) {
add(3, 4, done)
})
.def('result', function (sum1, sum2, done) {
add(sum1, sum2, done)
})
 
// usage
app.run().eval('result', function (err, result) {
// do something with result
})

Jake Verbaten

unread,
Dec 29, 2012, 2:39:28 AM12/29/12
to nod...@googlegroups.com
You can implement the same idea with two functions

Here the code is explicit about how it runs code.

```js
var execute = require("execute")
    , serial = require("serialize") // unimplemented see https://gist.github.com/4405173

var run = serial([
    function (cb) {
        execute({
            sum1: function (cb) { add(1, 2, cb) }
            , sum2: function (cb) { add(3, 4, cb) }      
        }, cb)
    }
    , function (result, cb) {
        add(result.sum1, result.sum2, cb)
    }
])

run(printResult)

function printResult(err, result) {
    if (err) {
        throw err
    }
    console.log("result", result) // prints "result=10" 
}
```

Although your idea is interesting, it's hard to build something that's cleaner then just being explicit about how you do things.

Also notice that because we are using clean functional abstractions they compose trivially ( http://jsfiddle.net/fvz7N/4/ ) like functions should.

Your ideas however are interesting, the problem is that they are far more complex to grok and require trust on self organizing code. Also it's full of implicit magic by the very definition of self organizing code.

It should be noted substack had a similar idea with disorder ( https://github.com/substack/node-disorder#disorder )

Eldar

unread,
Dec 29, 2012, 3:16:39 AM12/29/12
to nod...@googlegroups.com
@Raynos, @greelgorke I would recommend reading Out of the tarpit. It argues that traditional imperative approach with control flow being messed with logic leads to complex unmaintainable just ugly software. 

Tatumizer

unread,
Dec 29, 2012, 2:46:48 PM12/29/12
to nod...@googlegroups.com
I'd like to address some concerns
@Mark: no, there's no slowdown. Compilation is done only once in a lifetime of a function, results are cached. 
@Raynos: please note how elegant and readable the circuit solution is: it speaks for itself in 3 lines, and it does not have and "russian dolls" in it - plain code, much like sequential one; BUT it knows itself what is parallel and what is sequential. So, with almost no extra noise it supports parallelism, which is very important in server applications.
"Nothing cleaner than being explicit"? I think circuit is as explicit as it gets.

about "disorder": yes, there are many libraries that are based on the raw idea of  "reactive programming". 

The difference is:
I tried to make CONCEPT out of this raw idea so that all details associated with NODEJS async programming I'm aware of fit into it nicely. Central point of control is important. Loops (over streams) are important. Debugging. Timeouts. Circuit KNOWS its structure (no other solution I'm aware of knows it), Based on this knowledge, you can build nice debugging tool that shows the graph , etc. Based on this knowledge, you can parallelize beyond one processor.

I am not sure many people read the entire writeup, and I'm sorry I couldn't keep it shorter (really takes time to read), but I wanted to tell the entire story.

Isn't it interesting that circuit.run() and circuit.loop() cover A LOT of real world use cases?

Guys, let's discuss it, I think it can make nodejs programming more accessible, help to bring it more mainstream. I need your criticism really. Is there something that is missing from the picture?
Something wrong? Of 2 versions of syntax, which is better? Is it really as "elegant" as I imagine? If not, what should be changed? Etc.

I will appreciate any feedback

Thanks,
Alex

Forrest L Norvell

unread,
Dec 29, 2012, 2:47:35 PM12/29/12
to nod...@googlegroups.com
That was an interesting paper, and thank you for sending it along. I often find myself describing the essential problems I have working in Node as rooted in resolving the tensions inherent in JavaScript. This is precisely due to the presence in JS of both OO and functional paradigms.

Some things to consider, though:

1. JavaScript uses OO techniques to manage state, especially when performance is a consideration. It is much faster to use direct mutation on an object than it is to create any kind of persistent data structure.
2. JavaScript has a simply-typed functional core. While there is imperative control flow, in most circumstances JS developers are encouraged to use anonymous functions passed to higher-order functions to achieve most common goals.
3. Node.js's fundamental control flow paradigm is the asynchronous execution of chains of callbacks. In some ways this is similar to continuation-passing style, but because it is the result of ad hoc design decisions (as opposed to the result of a mechanical transformation applied by a compiler or macro system), user and library code can make few assumptions about control flow beyond those specified by their own interfaces.
4. "Simplicity" in the Node world is coming to mean "composability" first and foremost. Each module should export one unit of functionality, and then users can choose the modules that they feel will work best to solve their particular problems. This places a premium on the traditional software engineering values of loose coupling and tight cohesion. It also means that the streams of data passed between modules tend to be basic data types rather than structures, with Buffers being about the most complex type commonly encountered.
5. Node was designed to build fast web services. As such, it's accumulated a body of lore that can be used to work with V8's JIT, the system calls for each platform, and other things that frequently result in awkward combinations of JS's twin OO and functional natures.

Jake's sketched-out solution does a good job of reconciling some of the contradictions inherent in Node's approach. It's stateful but not based on mutation, it uses two simple functions to define control flow, and it's quite clear and explicit about how it works without slapping a pile of abstractions in the way.

Node is built to do a certain class of tasks as quickly and efficiently as possible. Its design decisions were made with an eye towards simplicity and performance, not elegance or purity. The emerging consensus of the community seems to be that the best way to deal with the rough edges of Node's use of JavaScript is to keep things small and simple, but also idiomatic. New techniques for control flow are fun to develop and play with, but the more they become controlling abstractions, the less useful they are to the general body of Node developers. IMHO, at least.

--

Tatumizer

unread,
Dec 29, 2012, 11:45:26 PM12/29/12
to nod...@googlegroups.com
What you describe as "small and simple, but also idiomatic", can be said also about assembly language. 
Basically, what is the reason for having high-level languages? Everything can be done more efficiently in assembly, for sure. 

The problem of this logic is that it discounts the "costs", and there's more than one type of costs (though all of them eventually have $$ expression).

Imagine writing program consisting of 300 async calls in the "idiomatic" way you propose. Handling correctly all exceptions... Debugging such program... MAINTAINING it (300 is a number of async calls in a modest size project I saw recently). 

I don't know. If nodejs team believes current solutions are optimal, so be it. 








Mark Hahn

unread,
Dec 30, 2012, 12:16:58 AM12/30/12
to nodejs
> Imagine writing program consisting of 300 async calls

My app currently has several thousand such calls.  

 
>  If nodejs team believes current solutions are optimal

There is no optimal solution.  If there were one everyone would jump on it.

I think it is great that you developed an interesting approach to the async problem.  I think every programmer new to node should write an async library.  I wrote such a library and I learned a lot, not just about programming node, but about the nature of async code.  I used it for a while.

Over the last several years I have found it easier and easier to just use "boilerplate" as you described it.  Here are some examples ...

Linear code ...

doThing1 = ->
    blah blah blah
    doThing2()

doThing2 = ->
    blah blah blah
    done()

doThing1()


Looping ...

angryBirds = [bird1, bird2, bird3]
do flingOneBird = ->
    if not (bird = angryBirds.shift()) then done(); return
    bird.fling()
    flingOneBird()

I have used this boilerplate so many times that I can type it without thinking.  It has also become very easy to read.  I don't think it is hard for others to read, but I may be wrong.

Martin Cooper

unread,
Dec 30, 2012, 12:22:31 AM12/30/12
to nod...@googlegroups.com
On Sat, Dec 29, 2012 at 8:45 PM, Tatumizer <tatu...@gmail.com> wrote:
What you describe as "small and simple, but also idiomatic", can be said also about assembly language. 
Basically, what is the reason for having high-level languages? Everything can be done more efficiently in assembly, for sure. 

The problem of this logic is that it discounts the "costs", and there's more than one type of costs (though all of them eventually have $$ expression).

Imagine writing program consisting of 300 async calls in the "idiomatic" way you propose. Handling correctly all exceptions... Debugging such program... MAINTAINING it (300 is a number of async calls in a modest size project I saw recently). 

One of the issues you're facing right now, I think, is that many people here already have large systems built on Node, so they know exactly what's involved, from direct experience. But with Circuit, all we have today is a readme with some examples of adding and squaring numbers. There's a huge gulf between those two things.

What would be very helpful to your cause, I think, is one or more of the following:

* An example of a real Node app built using Circuit, so that people can see how it would be used to do real work (as opposed to adding numbers).

* An explanation, with an example, of how (if at all) this fits in with Node's event model, and how it can help with common scenarios such as stream processing.

* Some code that people can actually play around with to see how it works.

Right now, we don't have any of those, so we can only speculate about what it might look like if we tried to use it for something real.

--
Martin Cooper
 

I don't know. If nodejs team believes current solutions are optimal, so be it. 

greelgorke

unread,
Dec 30, 2012, 4:22:34 AM12/30/12
to nod...@googlegroups.com
@Mark: kudos for you. totally right. I think, that all the claims about how bad async coding style is, just comes because the developers come from languages, which do not know this style. its only unfamiliarity with this paradigm. i guess subroutines had a hard start too as they appeared.

callback chains can be hard to maintain, but long sequential methods, deeply nested control structures, wide-spread call hierarchy also. there are built in methods to reduce nesting, EventEmitters + Streams, If you design your code to reduce the need of closures, you can just write simple functions like Marks example, so your code has a max nesting of 2, the function itself and simple if-else or if-return checks. 

i think it's not only good to write own async-lib, it's worth to look into functional languages as Haskel, LISP, Scala to understand how functional code can be written.  

Bruno Jouhier

unread,
Dec 30, 2012, 6:39:08 AM12/30/12
to nod...@googlegroups.com
FWIW the problem of implementing async/await semantics with a pure JS library has been cracked: http://smellegantcode.wordpress.com/2012/12/28/a-pure-library-approach-to-asyncawait-in-standard-javascript/

Unfortunately it involves a lot of extra grinding. So preprocessors and fibers are still the best practical options.
Message has been deleted

Isaac Schlueter

unread,
Dec 30, 2012, 11:00:06 AM12/30/12
to nodejs
A lot has been mentioned in this thread regarding what the "node team"
thinks or agrees with.

Here's the official policy of the node team:
https://github.com/joyent/node/wiki/node-core-vs-userland

If we don't absolutely need something to be done in node core, we're
not going to.

The feature set of node core is considered roughly complete at this
point. We're not going to add brand new features. We are in the
phase of polishing and refining what we have. (For example, with the
new streams API, or the modifications being made to Domains as more
people use them and find issues.)

A control flow pattern fancier than callbacks and event emitters will
probably never land in node core. This kind of stuff belongs in npm
for many many reasons. We try to minimize the amount of stuff we have
to all agree on.

If there was anything at this point that I could manage to *remove*
from node-core, I'd do it gladly. Node is way too big as it is.


On Sun, Dec 30, 2012 at 6:56 AM, Tatumizer <tatu...@gmail.com> wrote:
>> I have used this boilerplate so many times that I can type it without
>> thinking.
>
> I don't see much of error processing there. It's like programming without
> exception mechanism - you have to handle "err" return code in each line.
> Doubles the amount of code, in the end you can't see forest for the trees (I
> already can't see forest for the trees in the proposed optimal solution, but
> maybe it's only me)
>
>> My app currently has several thousand such calls.
> There are many very successful systems written completely (or to the large
> part) in assembly language.
>
> COSTS is the keyword.
>
>>Its design decisions were made with an eye towards simplicity and
>> performance, not elegance or purity.
>
> Elegance SELLS.
>
> But again, if there's no problem, no point to discuss the solution.

Mark Hahn

unread,
Dec 30, 2012, 3:27:13 PM12/30/12
to nodejs
  you have to handle "err" return code in each line. Doubles the amount of code

I don't know what you mean "for each line".  The line `x=2` can't throw an error.  I find I have to do a line like this after each call with a possible error callback ...

      if err then log "module bird: fling failed for bird: ', bird.name; return err

I just looked at some random code files from my app and here are the results for several files ...

file1: 63 lines, 1 err line
file2: 291 lines, 12 err lines
file3: 42 lines, 4 err lines

So it ranges from 2% to 10% of the lines in my code.  Even if my selection of random files were accidentally biased, the results will not be near the 50% you claimed.  Your eyesight is really bad if those err lines make the forest hard to see.

BTW, some very famous language designers at Google are forcing everyone to use this error handling technique in the new GO language.

 in the proposed optimal solution

Once again you are talking about this mythical *optimal* solution.  What solution are you talking about?  There is no such thing. Handing async callbacks is inherently hard and I doubt there will ever be a magic fix.

A lot of people would like this magic fix but it ain't gonna happen.  Get over it.


Ciprian Dorin Craciun

unread,
Jan 8, 2013, 6:51:56 AM1/8/13
to tatu...@gmail.com, nod...@googlegroups.com
On Fri, Dec 28, 2012 at 3:03 AM, Alex ("Tatumizer") <tatu...@gmail.com> wrote:
> After a lot of head-scratching, I found the way to eliminate all boilerplate
> and syntactic noise, and eventually came up with completely new design -much
> simpler one, and much more powerful: just two functions and their
> combinations do the job in most practical cases. I renamed the concept to
> "circuit" - it's a better name for this device.
>
> https://github.com/tatumizer/circuit/blob/master/README.md


I've quickly read through your proposal (and the other comments to
this thread), and tried to understand the context, the problem and the
solution:
* all in all I tend to agree that asynchronous callbacks tend to
get messy especially when they are a lot of them chained together;
* but I also tend to think that most of the time the problem is in
the code itself and not in the language / environment (i.e. NodeJS),
as with a little bit of refactoring things could look better again;


But on the topic of your proposal, I see it more as a DSL (Domain
Specific Language) than as a library (or framework) to solve
asynchronous composition. (This stems from the fact that your current
solution for JavaScript is based on source code inspection, or
explicitly through crafted strings at beginning of functions; although
I do understand that this is only one of the possible solutions.)

This DSL approach makes me think that maybe it isn't very
appropriate for a programming language lacking syntax flexibility. To
be more clearer: I would say that your approach could be a perfect
match for a language like Lisp (or Scheme) which has prime support for
syntax manipulation. It could also work for other languages like Ruby
(which also has a more "sugary" syntax), or even Python (by using
decorators and its AST library), but most likely it would be broken
with compiled languages (like C, Go, etc.)

As such I tend to see JavaScript as a challenging language to
implement your proposal.


What you are describing seems very much similar to a workflow
engine, that takes as input the recipes of the steps and then deduces
the order. Maybe a more explicit approach would be better, taking your
example and moving the "crafted" string outside the function body,
which would eliminate the function source code parsing while keeping
intact your idea:
~~~~
var circuit=new Circuit({
"->sum1" : function() { add(1, 2, this.setter.sum1) },
"->sum2" : function() { add(3, 4, this.setter.sum2) },
"sum1,sum2->result" : function() { add(this.sum1, this.sum2,
this.setter.result) },
"->" : "result" // this is the actual output of the workflow
})
circuit.run(printResult);
~~~~
(Of course the keys have to be unique, but you could label them
like this "step1:a,b->c", "step2:a,b->d".)


As an ending note, what I think the NodeJS community could be
doing instead (and maybe it has already done, and I didn't see it, as
I currently strained away from NodeJS) are the following:
* laying out "best practices" both for library developers and
users; (like the error argument as the first one for each callback,
etc.);
* providing a generic function composition library (in the line of
"underscore"), allowing things as functional composition but taking
into account the callback nature, i.e.:
~~~~
work(composeCallback(f, g))
~~~~
which should be equivalent to
~~~~
work(function(err, out) {
if (err!=nil) g(err, nil);
// continue with a call to f which has as callback g
f(out, g);
}
~~~~


Ciprian.

Tatumizer

unread,
Jan 8, 2013, 2:17:37 PM1/8/13
to nod...@googlegroups.com, tatu...@gmail.com
Good idea indeed. If we write it like this:

var circuit=new Circuit({
   "->sum1" : function() { add(1, 2, this.setter.sum1) },
   "->sum2" : function() { add(3, 4, this.setter.sum2) },
   ...
})
circuit.run(printResult);

- it solves 2 problems:
1) makes parsing of the body of function unnecessary
2) makes annotations unnecessary.

Thanks for suggestion! I will update the proposal.
Alex


Tatumizer

unread,
Jan 8, 2013, 4:23:38 PM1/8/13
to nod...@googlegroups.com, tatu...@gmail.com
I made just one small change to Ciprian's idea: we can use "=>" to specify the output of entire circuit operation:

var
circuit=new Circuit({

   "->sum1" : function() { add(1, 2, this.setter.sum1) },
   "->sum2" : function() { add(3, 4, this.setter.sum2) },

   "sum1,sum2=>result" : function() { add(this.sum1, this.sum2, this.setter.result) }
})



Angel Java Lopez

unread,
Jan 8, 2013, 9:25:03 PM1/8/13
to nod...@googlegroups.com
Hi people!

Alex: very interesting idea.

I was exploring Go language channels, futures, promises, and I implemented some form of channels in other language. I tried to implement Storm project in Node.js, too, I need to define distributed topologies.

Now, reading your syntax, I just wrote my module:


As I read today in this thread, you can use strings insteadn of this.property, to define your communication variables. In my implementation, I don't need the use of an arrow, the name of the pipe is enough.

English is not my mother tongue, so I can't explain in a clear way all the ideas I want to implement with this module. The main differences with your ideas:

- The variables to use to communicate functions are named "pipes".
- The pipe can be reused: that is, a system of pipes can run for ever, receiving input message and processing them.
- The values received in a pipe, are given to the associated function as arguments, you don't need to refer the pipe object to get a value.

Quick sample:

var flow = simplepipes.createFlow(
    "pipe1",
    function (val) {
        console.log(val);
        this.pipe2.send(val + 1);
    },
    "pipe2",
    function (val) {
        console.log(val);
        test.done();
    }
);

flow.start();
flow.pipe1.send(1);


I planned to add:

flow1.pipe1.pipe(flow2.pipe3); to chain pipes

A pipe could send the message to more than a pipe, and you can define the strategy to use: send the message to all output pipes, or to one choose at random, or one using round-robin, etc...

And I want  to have a distributed pipe: the message entering a pipe, is received by other pipe in another machine. I wrote similar examples using other of my modules, so I thing it could be added with ease.

I think I could re implement pipes using streams, but I should learn about stopping an stream when the pipe is not consumed.

Thanks for kicking so many ideas!

Angel "Java" Lopez
@ajlopez

On Thu, Dec 27, 2012 at 10:03 PM, Alex ("Tatumizer") <tatu...@gmail.com> wrote:
I'm trying to come up with a better concept for asynchronous programming. My first library (mesh.js) was an attempt to use a promising line of attack, but it introduced a lot of boilerplate, which no one liked (myself included).. 

After a lot of head-scratching, I found the way to eliminate all boilerplate and syntactic noise, and eventually came up with completely new design -much simpler one, and much more powerful: just two functions and their combinations do the job in most practical cases. I renamed the concept to "circuit" - it's a better name for this device.


At this stage, it's a design doc only, specifically targeting nodejs. I think the concept of circuit could simplify nodejs programming..
What is equally important that it uses all existing nodejs conventions and interfaces AS IS: no code generation, no wrappers, no conversions of f(x,y) into fubar(f,x,y) or anything - just pure nodejs code.

I would be very interested to know opinions (even negative opinions) to improve design and find  potential flaws. 

Thanks,
Alex

--

nin jin

unread,
Jan 9, 2013, 5:40:51 AM1/9/13
to nod...@googlegroups.com
I rewrite your example using harmony-proxy and node-fibers:

======================================================
require( 'jin' )( function( $ ){

    var add= $.jin.sync( function( x, y, done ){
        console.log( 'add', x, y )
        setTimeout
        (   function( ){
                done( null, x + y )
            }
        ,   10
        )
    } )
    
    var div= $.jin.sync( function( x, y, done ){
        console.log( 'div', x, y )
        setTimeout
        (   function( ){
                if( y == 0 ) throw new Error( 'Division by zero' )
                done( null, x / y )
            }
        ,   10
        )
    } )
    
    try {
        console.log( 'first:', div( add( 5, 3 ), add( 1, 3 ) ) )
        console.log( 'second:', div( 10, add( 1, -1 ) ) )
    } catch( error ){
        console.log( error )
    }

}
======================================================

Output:

add 5 3
add 1 3
div 8 4
first: 2
add 1 -1
div 10 0
Error: Division by zero


пятница, 28 декабря 2012 г., 5:03:11 UTC+4 пользователь Tatumizer написал:

Tatumizer

unread,
Jan 9, 2013, 10:37:16 AM1/9/13
to nod...@googlegroups.com
I opened an issue to discuss the best syntax. In fact, there are more alternatives than I could put into the article - they can be found in the issue discussion:

@nin jin:
I might be wrong, but I think the goal of fibers is to HIDE asynchronous nature of functions.
The goal of circuit is the opposite: to create elegant and succinct notation where asynchronous functions shine. And you see, it's really getting closer to that goal (gradually).

@ajlopez:
Please don't hesitate to open new issues in the circuit project if you know what to improve/add/etc. It's better to document suggestions there, or else they will be lost.
Even if something is tangentially related, let it better be on github. Many apparently different problems are inter-related in fancy ways.

Just one more point. Turns out, circuit can be regarded as fine-grained implementation of mediator patter,
Good presentation of mediator pattern can be found in this paper:
It's interesting how essentially the same concept applies in two completely different sets of circumstances. h/t Ates Goral [@atesgoral](https://github.com/atesgoral)

Thanks everybody for comments! Please send more!

犀利な天使

unread,
Jan 9, 2013, 3:39:52 PM1/9/13
to nod...@googlegroups.com
Circuit also hides async nature. That marshal functions (that contains chunks of code and uses fields instead of local variables) in one line. And reinvent control flow syntax that already exists in javascript (conditions, loops, error handling etc).

I already use fibers in gecko and i love its. Try and you :)


2013/1/9 Tatumizer <tatu...@gmail.com>

Alex Tatumizer

unread,
Jan 9, 2013, 4:08:03 PM1/9/13
to nod...@googlegroups.com
Fibers practically turn asynchronous code into synchronous one. We throw the baby out with the bathwater. The whole idea of fibers is based on belief that asynchronous code is evil. If you believe it's evil, why not to program in java? No fibers required. And you can even use javascript, if you wish (Rhino).. Many people believe this way (web is full of rants on this matter).

This is a misconception. Asynchronous functions are *natural*. The *nature* is full of asynchronous functions (any fibers running in the Universe?)

In fact, if you need a path to automatic parallelization, asynchronous functions is the only way to go. I mean REAL parallelization, not just while waiting for I/O.

It's somewhat a philosophical issue though.

I think switching to fibers is admitting a failure to come up with a good concept that facilitates thinking about async code, and writing async code. Circuit is my attempt to provide such concept. It doesn't hide asynchronous functions to the same extent as fibers, just makes the notation more concise using syntax sugar. Semantics remains absolutely the same.




犀利な天使

unread,
Jan 10, 2013, 12:39:59 AM1/10/13
to nod...@googlegroups.com
This is ideology. I do not understand this. I prefer practice. In practice i want load 2 files at the same time, than process it and save to another. This code is all i need:

function updateConfig( ){
    try {
        var localConfig= $.fs.readFileSync( './config.tree' )
    } catch( error ){
        console.log( error )
    }
    
    var remoteConfig= $.http.getSync( 'http://example.org/config.tree' )
    
    var resultConfig= localConfig ? mergeConfig( localConfig, remoteConfig ) : remoteConfig
    
    $.fs.writeFileSync( './config.tree', resultConfig )
}

I do not want native or surrogate, sync or async. I want do more, write less and do not fall to hell of callbacks.

2013/1/10 Alex Tatumizer <tatu...@gmail.com>

greelgorke

unread,
Jan 10, 2013, 4:05:10 AM1/10/13
to nod...@googlegroups.com
@Eldar: thank you for the link to this paper. very interesting.

Alex Tatumizer

unread,
Jan 10, 2013, 9:45:02 AM1/10/13
to nod...@googlegroups.com
@nin jin; everything is ideology at some level. When you say "practice" - the notion is full of ideology.
My point is that if you prefer "practice" in a very narrow sense, the same program in your example can be rewritten in 100 of other languages in a much simpler form.
Why limit yourself to nodejs? What benefits do you get?

Try java programming - you will like it! :) And absolutely no need to reinvent the wheel with fibers, etc.

P.S. Turns out, fibers are not a magic bullet either:






--

Tatumizer

unread,
Jan 10, 2013, 12:01:32 PM1/10/13
to nod...@googlegroups.com
I'm trying to eliminate remaining boilerplate in circuit callback syntax. I don't really like expression
this.setter.sum1. Tried to use "out" instead of "setter" (this.out.sum1) - shorter, but not necessarily better.
Now I have another idea which may look stupid, but any idea is either old or stupid or some combination of those
:)
How do you like this: writing (this.sum1) in parentheses instead of this.setter.sum1
var circuit=new Circuit({ function() { add(1, 2, (this.sum1)) }, function() { add(3, 4, (this.sum2)) }, function() { add(this.sum1, this.sum2, (this.result)) } })

There's interesting implementation trick: output tokens still can be distinguished by parsing
(due to those parentheses);

Now, whenever token is known to be an output token of the gate, system
MODIFIES token variable behind the scenes, turning it into function dynamically, before executing gate.

What is interesting about it is: program analyzes its own code, and makes changes to environment dynamically to make
this code execute correctly. Isn't it an exciting idea? :)






Angel Java Lopez

unread,
Jan 10, 2013, 12:07:12 PM1/10/13
to nod...@googlegroups.com
Ummm... too much work, IMO.

I still prefer declare the variables by names as string
Message has been deleted

犀利な天使

unread,
Jan 10, 2013, 12:19:56 PM1/10/13
to nod...@googlegroups.com
I like js and i like fibers - all of them exists in node.js. I was using java - this is a monster.

> Unfamiliarity for other Javascript developers

Fibers, as sync, as async, as circuit, as many tons of other wheels, - library that needs to learn to use. But fibers really reduce complexity in client code. 

> No Windows Support

I was developing my library in windows. Fibers works fine.

> Browser Incompatible

Most of nodejs code is browser incompatible. But Mozilla already implement generators from Harmony (http://wiki.ecmascript.org/doku.php?id=harmony:generators). And all browsers will support fibers by generators in future.

> More Difficult Debugging

This is delirium. Stacktrace in callbacks is fully useless. Fibers libraries rebuilding stacktrace for debugging support. 



2013/1/10 Alex Tatumizer <tatu...@gmail.com>
Message has been deleted
Message has been deleted

Tatumizer

unread,
Jan 10, 2013, 4:46:46 PM1/10/13
to nod...@googlegroups.com
Time for me to move on, too
If someone is interested in contributing or just exchange ideas, please open an issue at
https://github.com/tatumizer/circuit

or send email to me directly to tatumizer at gmail

Thanks everybody for lively discussion.

Alex


Reply all
Reply to author
Forward
0 new messages