1,721 karma · joined May 4, 2008
http://krisjordan.com
http://twitter.com/KrisJordan
Here's a link to the node_modules loading algorithm since v0.4, if you haven't checked it out, it's worth the quick read: http://nodejs.org/docs/latest/api/modules.html#loading_from_...
This module loading algorithm is what opens the door for npm to install nested dependencies in recursive node_modules subdirectories.
In object-oriented programming, you can define a base class "Animal" with a method "makeNoise" and subclasses with a method "makeNoise" with that will return "bark" if you call a Dog's makeNoise or "meow" if you call a Cat's. When you first defined the Animal's "makeNoise" method you didn't need to know how anything about the subclasses that would eventually implement it. Your algorithms could depend on "makeNoise" returning the noise specific to the animal in question.
Multimethods are a functional approach to polymorphism without a class/prototype hierarchy. The second example in the post shows how you might implement a multimethod that calculates the area of shapes. Perhaps a separate module introduces new kinds of shapes (like new kinds of subclasses in OO). These shapes can register their area implementations with the 'area' multimethod. Other algorithms that use the 'area' multimethod will now be able to operate on these new kinds of shapes. Multimethods provide a means to polymorphism while keeping data and functionality decomposed.
Like swannodette says more beautifully and concisely, though, it's an even more generic/flexible dispatch than thinking in terms of OO polymorphism.
To illustrate this flexibility in the context of fib, multimethod.js, and CoffeeScript:
> fib = multimethod()
.when(0, 0)
.when(1, 1)
.default (n) -> fib(n)
> fib 20
6765
> fib.dispatch (n) -> n.numberVal or n
> fib 20
6765
> fib { numberVal: 20 }
6765
> fib.when 2, 1
> fib.when 3, 2
> fib 20
6765 (now "optimized" with fewer recursive calls than before)Performance will depend on a number of factors, such as how complex your dispatch function is, how complex your dispatched values and match values are (deep equality becomes more expensive as the compared objects grow in complexity), and how many methods are registered. In general, it is much more expensive than native switch statements or prototype chain lookups.
If performance is of utmost importance and you can substitute a switch statement or prototype hierarchy for a multimethod, you should. Multimethods are a useful pattern for achieving things that either aren't possible in switch (add/remove cases dynamically, deep equality case matching) or are not naturally/painlessly expressed with a prototype hierarchy.
This is running on a 256mb Ubuntu virtual server and it's overkill for both processor and memory. Kind of neat watching the story climb HN (currently #4) and watching `top` without being able to tell anything is happening on the server at all: 0,0,0,0%user,100%idle -- a testament to the light weight beauty of node,redis,nginx.
One of the things you are paying for with S3 is a pretty solid guarantee that your files will A) not get lost and B) always be available.
Edit: I wrote about some of my favorite features of CoffeeScript when we added CoffeeScript support to our CMS app HiFi... http://www.gethifi.com/blog/hosted-cms-coffeescript-support
tl;dr:
1) Lightweight function declarations (with default values!)
2) Implicit Returns
3) Everything is an Expression
4) Object Literal YAML-like syntax
5) Simple, Classical OO Features (you don't have to use them and can still directly access prototypal features, too)
6) (Not in the post) Binding 'this' to the scope's 'this' using => is awesome.
My project simply proxies client fetch/save/destroy calls via Backbone.sync to the server. Through a RESTful URL convention and Express.js the model and collection of the client's request are recreated, any transformations applied and persisted, then sent back down the pipe. Server-side, models and collections extend their client-side bases and introduce additional functionality (i.e. per-user access control). Models and collections are not kept in memory server-side beyond the duration of a request.
PS1='\[\e[1;31m\][\u@\h \W]\$\[\e[0m\] '
We use this in our production environments and the red prompt, though not as jarring as a red background, is still scary enough to serve its purpose.
One upside in setting this up on the server, as opposed to local like the OP, is that all connections in will get the red prompt.
There are three paths to authentication presently.
1) Anonymous - Anonymous is a subject in the system with explicit permissions. When no authentication is presented the system assumes you are the anonymous subject. This is the common case because most website content, for the types of websites we've seen on HiFi, are made up of entirely publicly readable content.
2) Cookie Based - We use your typical web app SHA1 hash with generated salt. Not the greatest form of authentication, susceptible to replay, but preferable to HTTP Basic.
3) HTTP Basic Based - Want to get rid of this sooner than later. Need to invest in digest but it has its problems. This is not used in the app but is useful for server-server API consumption, cURL scripts, etc.
As Joel mentioned, the backend is largely XHR driven. Results are rendered primarily with an evolution of Resig's JS templates (http://ejohn.org/blog/javascript-micro-templating/). When time permits we'll move to the now official jQuery templates (http://api.jquery.com/jquery.tmpl/). Most website frontends consume the API directly in template while still server-side. Some go further and leverage the API from JS/XHR to make pages more interactive.
Recess has been somewhat dormant while focusing on product. I've slowly and infrequently been readying the 5.3 branch. 5.3 has so much upside and has now been out for over a year I see very little value in doing new work. The 5.3 branch packages modules for individual consumption rather than taking a kitchen sink approach. It feels more functional, in the lambda-y sense, given 5.3's anonymous function support. I've started a new SQL generation layer that is in the same spirit as Recess' SQLBuilder but much more powerful and flexible with heavy inspiration from Arel.
I don't want to make any promises but its my full intention to package up the lessons of the last year or so into a great set of 5.3 libraries of Recess lineage.
From what I've read Google's index runs in around 20 MapReduce jobs.
The argument for the $ sign is not readability. If it were you'd see JavaScripter's prefixing all of their variables with a dollar sign, too. var $foo = 'bar'; is completely valid JavaScript. (Aside: $ prefix is handy in JS when holding references to jQuery objects ie $container = $('#container');)
The argument is for simplified string manipulation with magic quotes and is an homage to unix shell scripting.
Without the $ prefix string manipulation would be reserved to concatenation/printf/replacement/etc. With the $prefix you can do things like:
$base = __DIR__;
$user = (object)array('name'=>'Foo','dir'=>"foo");
$size = "lg";
$image = "$base/users/$user->dir/images/$size.jpg";
vs: image = base + "/users/" + user.dir + "/images/" + size + ".jpg"
When doing a lot of string manipulation and scripting the $ is quite handy.The dollar sign also enables variable variables and dynamic property access. i.e.
$foo = 'Hello, world.';
$bar = 'foo';
echo ${$bar}; // 'Hello, world.'
- and - $user = (object)array('name'=>'Foo','dir'=>"foo");
$prop = 'name';
echo $user->{$prop}; // 'Foo'
The dollar sign for variable variables is weak because variable variables is usually an indication of code gone awry. Dynamic property access, on the other hand, is much more useful in a dynamic language like PHP/JavaScript. That said, I believe JavaScript's solution is much more elegant. i.e.: var user = {name: "Foo", dir: "foo"};
var prop = "name";
alert(user[prop]); // 'Foo'
By overloading the index operator on objects to accept a string that dereferences to an object's property you get the same benefit in a much more elegant way.Thus the $'s primary justification is magic strings and string manipulation.
I'm surprised they're looking to switch stacks entirely as opposed to a consistent hashing / distributed hash table (a la chord, dynamo, etc.)
High points:
the performance numbers were against PHP with APC op-code caching enabled
eval, create_function, and preg_replace with /e (basically eval), and conditional flow based on the existance of functions are the only features not supported.
Currently PHP5.2 with a roadmap of 5.2.12 compliant in the next month and 5.3 being the focus after that.
Currently works off of the PHP 5.2 language specs
Compiles to a stand-alone libevent-driven web server or CLI executable
Not based on Zend's runtime/code
Currently no windows support
Intended for 'drop in' PHP replacement - if it runs on PHP and doesn't use a few things like eval() it will compile with HipHop
"droid keyboard"
"droid apps"
"droid camera"
"droid development"
"droid customization"
"droid widgets"
"droid batteries"
All of these subjects are covered in their Flash and they have content for but Google can't index or link you to any of it. So instead of Verizon owning these terms, which they easily could be, you're taken to 3rd party sites on the internet.
Even in their first result of "Droid" their misuse of a meta description (it's way too long) means you get 0 relevant information in the result Google displays.
Hope this Regular Expression tool is useful to other HN readers!