Live data from Hacker News

Callbacks are imperative, promises are functional

blog.jcoglan.com

31–40 of 154 posts

Re: Callbacks are imperative, promises are functional

#31
post #20

All the code and such a big abstraction for the first example when it could have done like this: var result = []; paths.forEach(function (i, file){ fs.stat(file, function (err, data){ result.push(data); if (i === 0) { // Use stat size } if (result.length === paths.length) { // Use the stats } }); }); Fairly understandable, more efficient and without introducing logic patterns foreign to many. It also meet his require…

> without introducing logic patterns foreign to many Consider your use of the forEach() abstraction when you could have used a for() loop just as easily. (That said, I agree the article in general could do a better job of describing the "other" side)

Nope, the shared scope would obligate me to create a function with binded params for each iteration so "i" is not the last value (e.g. path.length) in every call. Examples: http://stackoverflow.com/questions/1451009/javascript-infamo...

Re: Callbacks are imperative, promises are functional

#32
Not to focus too myopically on the given example, but I can’t help but wonder why it’s a requirement that the first file be handled specially? A less contrived example would make the argument more convincing.

If I wanted to compute the size of one file relative to a set, I’d probably do something like this:

  queue()
      .defer(fs.stat, "file1.txt")
      .defer(fs.stat, "file2.txt")
      .defer(fs.stat, "file3.txt")
      .awaitAll(function(error, stats) {
        if (error) throw error;
        console.log(stats[0].size / stats.reduce(function(p, v) { return p + v.size; }, 0));
      });
Or, if you prefer a list:

  var q = queue();
  files.forEach(function(f) { q.defer(fs.stat, f); });
  q.awaitAll(…); // as before
This uses my (shameless plug) queue-async module, 419 bytes minified and gzipped: https://github.com/mbostock/queue

A related question is whether you actually want to parallelize access to the file system. Stat'ing might be okay, but reading files in parallel would presumably be slower since you'd be jumping around on disk. (Although, with SSDs, YMMV.) A nice aspect of queue-async is that you can specify the parallelism in the queue constructor, so if you only want one task at a time, it’s as simple as queue(1) rather than queue(). This is not a data dependency, but an optimization based on the characteristics of the underlying system.

Anyway, I actually like promises in theory. I just feel like they might be a bit heavy-weight and a lot of API surface area to solve this particular problem. (For that matter, I created queue-async because I wanted something even more minimal than Caolan’s async, and to avoid code transpilation as with Tame.) Callbacks are surely the minimalist solution for serialized asynchronous tasks, and for managing parallelization, I like being able to exercise my preference.

Re: Callbacks are imperative, promises are functional

#33

Earlier quoted context omitted.

... and what does that haves to do with promises? And in such case you would only do this once outside the listeners of http/or-whatever connections so it would be done just once regardless of the number of concurrent activity.

The point is that a properly designed API wouldn't require any amount of scaffolding. You'd go: fs.statMany(filenames, function (stats) { ... }); or: var statsPromise = fs.statMany(filenames); And then in either case, you'd just use a for-loop or forEach or whatever your preference on the result. No thinking about how to preserve complex invariants or whatever is necessary. Hell, with ES6 generator-y expressions you…

Sorry, I don't see no clarity there. And how would that fix the fact that stat works in individual files?, and more importantly, how does a function like that handles error? Individual level, group level? It is confusing.

Re: Callbacks are imperative, promises are functional

#34

This is an interesting perspective. But to me, even having spent a year on a large node.js project, I just don't see how promises would have simplified things at all. If you have some crazy graph of dependencies, I can see how breaking out promises could help simplify things. But I don't feel like that's a super-common scenario. The author says: > * [Promises] are easier to think about precisely because we’ve delegat…

The project I'm working on right now is about 6 months old. Promises have greatly simplified our data access layer. My argument here is mostly syntactic (not semantic, like the OP), but being able to assign promises to a variable has improved the readability of the code and the intent of the code, improving readability, testability, and flexibility. I don't claim that promises are the One True Way, but they get a lot of noise out of my way and let me focus more on what our code is doing than on how it's doing it.

Re: Callbacks are imperative, promises are functional

#35
post #13

I feel this is twisting the meaning of functional programming. Excel is not functional. It is declarative. You declare the relationships between the cells and Excel uses those to propagate changes. Just like a makefile is not functional but declarative. The dependency of the relationships are enforced to produce action. SQL is another example of declarative language and it is nowhere near as functional.

declarative is an orthogonal attribute to functional. The two attributes are not mutually exclusive. You may as well say something like: "A bicycle isn't a vehicle at all! A Bicycle is a metallic object!"

Following that logic, OO is an orthogonal attribute to functional. Both of them can define functions, and thus OO is functional.

Re: Callbacks are imperative, promises are functional

#36
post #19
post #13

I feel this is twisting the meaning of functional programming. Excel is not functional. It is declarative. You declare the relationships between the cells and Excel uses those to propagate changes. Just like a makefile is not functional but declarative. The dependency of the relationships are enforced to produce action. SQL is another example of declarative language and it is nowhere near as functional.

"Excel is not functional. It is declarative. You declare the relationships between the cells and Excel uses those to propagate changes." Whereas in functional languages, the functions declare relationships between values and the language uses the evaluation model to propagate the results between function evaluation. Where's the difference?

Functional language has the declarative aspect while declarative language lacks the functional aspect. Just because A => B doesn't mean B => A.

Re: Callbacks are imperative, promises are functional

#37
post #35

Earlier quoted context omitted.

declarative is an orthogonal attribute to functional. The two attributes are not mutually exclusive. You may as well say something like: "A bicycle isn't a vehicle at all! A Bicycle is a metallic object!"

Following that logic, OO is an orthogonal attribute to functional. Both of them can define functions, and thus OO is functional.

First of all, that's not what "functional" means.

Second, OO is an orthogonal attribute to functional.

Third, your argument commits a formal fallacy of this form:

All cats have whiskers

Cats can have stripes

Tony has stripes

therefore tony is a cat.

---The possibility of an attribute in X, and Y containing that attribute does not imply that Y is an X.

the point is that whether something is declarative has no bearing on whether it is functional or not. It's an irrelevant point to bring up. Whether something is OO is equally irrelevant. That is what "orthogonal" means. I would go on to define for you "functional" "declarative", "formal fallacy" "logic", but this seems like a bottomless rabbit hole. I can only hope you'll try and find out what these words actually mean yourself.

Re: Callbacks are imperative, promises are functional

#39

This is an interesting perspective. But to me, even having spent a year on a large node.js project, I just don't see how promises would have simplified things at all. If you have some crazy graph of dependencies, I can see how breaking out promises could help simplify things. But I don't feel like that's a super-common scenario. The author says: > * [Promises] are easier to think about precisely because we’ve delegat…

The point is promises free you from wanting or needing to know about the order that things happen in. I hear you saying you fear promises, because it means it would get in the way of your ability to know that. But the truth is once you embrace them, that need becomes unimportant. The idea that webservers are "all about side effects" gives me a chill. The whole architecture concept of HTTP is no side effects , so to c…

I think his point is that there's usually a very strict ordering to the events on an HTTP server - you parse and sanitize your input, make some database calls, and generate a response - at best, letting something else do the sequencing and composition for you doesn't gain you much, as it might in a reactive GUI. At worst it leaves room for subtle bugs or code that's less clear (arising from the statefulness of the Promse object itself).

Using a Promises, as opposed to reducing a list of computations async-style, also limits you to the Promise object's interface, so you lose (or at least add cruft to) the flexibility and composability of using native lists. By sequencing computations with lists, if I want some insight into what's happening, I just List.map(apply compose, logFunc). With promises, I have some work to do.

Promises have their uses, but it's definitely a tradeoff, and for most HTTP servers, I'd argue that their utility does seem a bit limited. I'd similarly say that making a point of using FRP to build a server would probably be a bit overkill for the task.

Re: Callbacks are imperative, promises are functional

#40

This is an interesting perspective. But to me, even having spent a year on a large node.js project, I just don't see how promises would have simplified things at all. If you have some crazy graph of dependencies, I can see how breaking out promises could help simplify things. But I don't feel like that's a super-common scenario. The author says: > * [Promises] are easier to think about precisely because we’ve delegat…

The point is promises free you from wanting or needing to know about the order that things happen in. I hear you saying you fear promises, because it means it would get in the way of your ability to know that. But the truth is once you embrace them, that need becomes unimportant. The idea that webservers are "all about side effects" gives me a chill. The whole architecture concept of HTTP is no side effects , so to c…

> The idea that webservers are "all about side effects" gives me a chill. The whole architecture concept of HTTP is no side effects, so to claim that it's all about side effects seems odd. It should only be the case for POST PUT or DELETE methods, and only in very specific ways.

There's nothing incongruous about that. It is the case that side effects should only happen on POST, PUT, and DELETE methods (and the like), but almost all webservers are written because of a need to use these.

If your webserver is all GETs and HEADs, then it is either trivial and you would have used someone else's instead of writing your own, or its sole purpose is to repackage and serve existing data from other sources - a rare use case among all webservers.

If you were to take an inventory of all the webservers out there, you would doubtless find that almost all of them exist in large part in order to create side effects.

Post reply on HN