package.json
8.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{
"_args": [
[
{
"raw": "lazy@~1.0.11",
"scope": null,
"escapedName": "lazy",
"name": "lazy",
"rawSpec": "~1.0.11",
"spec": ">=1.0.11 <1.1.0",
"type": "range"
},
"/root/junhukang/node_modules/nssocket"
]
],
"_from": "lazy@>=1.0.11 <1.1.0",
"_id": "lazy@1.0.11",
"_inCache": true,
"_installable": true,
"_location": "/lazy",
"_npmUser": {
"name": "pkrumins",
"email": "peteris.krumins@gmail.com"
},
"_npmVersion": "1.2.14",
"_phantomChildren": {},
"_requested": {
"raw": "lazy@~1.0.11",
"scope": null,
"escapedName": "lazy",
"name": "lazy",
"rawSpec": "~1.0.11",
"spec": ">=1.0.11 <1.1.0",
"type": "range"
},
"_requiredBy": [
"/nssocket"
],
"_resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz",
"_shasum": "daa068206282542c088288e975c297c1ae77b690",
"_shrinkwrap": null,
"_spec": "lazy@~1.0.11",
"_where": "/root/junhukang/node_modules/nssocket",
"author": {
"name": "Peteris Krumins",
"email": "peteris.krumins@gmail.com",
"url": "http://www.catonmat.net"
},
"bugs": {
"url": "https://github.com/pkrumins/node-lazy/issues"
},
"dependencies": {},
"description": "Lazy lists for node",
"devDependencies": {
"expresso": ">=0.7.5"
},
"directories": {},
"dist": {
"shasum": "daa068206282542c088288e975c297c1ae77b690",
"tarball": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz"
},
"engines": {
"node": ">=0.2.0"
},
"homepage": "https://github.com/pkrumins/node-lazy#readme",
"keywords": [
"lazy lists",
"functional"
],
"license": {
"type": "MIT"
},
"main": "./lazy.js",
"maintainers": [
{
"name": "pkrumins",
"email": "peteris.krumins@gmail.com"
}
],
"name": "lazy",
"optionalDependencies": {},
"readme": "Lazy lists for node\n===================\n\n\n# Table of contents:\n\n[Introduction](#Introduction)\n \n[Documentation](#Documentation)\n\n<a name=\"Introduction\" />\n# Introduction\nLazy comes really handy when you need to treat a stream of events like a list.\nThe best use case currently is returning a lazy list from an asynchronous\nfunction, and having data pumped into it via events. In asynchronous\nprogramming you can't just return a regular list because you don't yet have\ndata for it. The usual solution so far has been to provide a callback that gets\ncalled when the data is available. But doing it this way you lose the power of\nchaining functions and creating pipes, which leads to not that nice interfaces.\n(See the 2nd example below to see how it improved the interface in one of my\nmodules.)\n\nCheck out this toy example, first you create a Lazy object:\n```javascript\n var Lazy = require('lazy');\n\n var lazy = new Lazy;\n lazy\n .filter(function (item) {\n return item % 2 == 0\n })\n .take(5)\n .map(function (item) {\n return item*2;\n })\n .join(function (xs) {\n console.log(xs);\n });\n```\n\nThis code says that 'lazy' is going to be a lazy list that filters even\nnumbers, takes first five of them, then multiplies all of them by 2, and then\ncalls the join function (think of join as in threads) on the final list.\n\nAnd now you can emit 'data' events with data in them at some point later,\n```javascript\n [0,1,2,3,4,5,6,7,8,9,10].forEach(function (x) {\n lazy.emit('data', x);\n });\n```\n\nThe output will be produced by the 'join' function, which will output the\nexpected [0, 4, 8, 12, 16].\n\nAnd here is a real-world example. Some time ago I wrote a hash database for\nnode.js called node-supermarket (think of key-value store except greater). Now\nit had a similar interface as a list, you could .forEach on the stored\nelements, .filter them, etc. But being asynchronous in nature it lead to the\nfollowing code, littered with callbacks and temporary lists:\n```javascript\n var Store = require('supermarket');\n\n var db = new Store({ filename : 'users.db', json : true });\n\n var users_over_20 = [];\n db.filter(\n function (user, meta) {\n // predicate function\n return meta.age > 20;\n },\n function (err, user, meta) {\n // function that gets executed when predicate is true\n if (users_over_20.length < 5)\n users_over_20.push(meta);\n },\n function () {\n // done function, called when all records have been filtered\n\n // now do something with users_over_20\n }\n )\n```\nThis code selects first five users who are over 20 years old and stores them\nin users_over_20.\n\nBut now we changed the node-supermarket interface to return lazy lists, and\nthe code became:\n```javascript\n var Store = require('supermarket');\n\n var db = new Store({ filename : 'users.db', json : true });\n\n db.filter(function (user, meta) {\n return meta.age > 20;\n })\n .take(5)\n .join(function (xs) {\n // xs contains the first 5 users who are over 20!\n });\n```\nThis is so much nicer!\n\nHere is the latest feature: .lines. Given a stream of data that has \\n's in it,\n.lines converts that into a list of lines.\n\nHere is an example from node-iptables that I wrote the other week,\n```javascript\n var Lazy = require('lazy');\n var spawn = require('child_process').spawn;\n var iptables = spawn('iptables', ['-L', '-n', '-v']);\n\n Lazy(iptables.stdout)\n .lines\n .map(String)\n .skip(2) // skips the two lines that are iptables header\n .map(function (line) {\n // packets, bytes, target, pro, opt, in, out, src, dst, opts\n var fields = line.trim().split(/\\s+/, 9);\n return {\n parsed : {\n packets : fields[0],\n bytes : fields[1],\n target : fields[2],\n protocol : fields[3],\n opt : fields[4],\n in : fields[5],\n out : fields[6],\n src : fields[7],\n dst : fields[8]\n },\n raw : line.trim()\n };\n });\n```\nThis example takes the `iptables -L -n -v` command and uses .lines on its output.\nThen it .skip's two lines from input and maps a function on all other lines that\ncreates a data structure from the output.\n\n<a name=\"Documentation\" />\n# Documentation\n\nSupports the following operations:\n\n* lazy.filter(f)\n* lazy.forEach(f)\n* lazy.map(f)\n* lazy.take(n)\n* lazy.takeWhile(f)\n* lazy.bucket(init, f)\n* lazy.lines\n* lazy.sum(f)\n* lazy.product(f)\n* lazy.foldr(op, i, f)\n* lazy.skip(n)\n* lazy.head(f)\n* lazy.tail(f)\n* lazy.join(f)\n\nThe Lazy object itself has a .range property for generating all the possible ranges.\n\nHere are several examples:\n\n* Lazy.range('10..') - infinite range starting from 10\n* Lazy.range('(10..') - infinite range starting from 11\n* Lazy.range(10) - range from 0 to 9\n* Lazy.range(-10, 10) - range from -10 to 9 (-10, -9, ... 0, 1, ... 9)\n* Lazy.range(-10, 10, 2) - range from -10 to 8, skipping every 2nd element (-10, -8, ... 0, 2, 4, 6, 8)\n* Lazy.range(10, 0, 2) - reverse range from 10 to 1, skipping every 2nd element (10, 8, 6, 4, 2)\n* Lazy.range(10, 0) - reverse range from 10 to 1\n* Lazy.range('5..50') - range from 5 to 49\n* Lazy.range('50..44') - range from 50 to 45\n* Lazy.range('1,1.1..4') - range from 1 to 4 with increment of 0.1 (1, 1.1, 1.2, ... 3.9)\n* Lazy.range('4,3.9..1') - reverse range from 4 to 1 with decerement of 0.1\n* Lazy.range('[1..10]') - range from 1 to 10 (all inclusive)\n* Lazy.range('[10..1]') - range from 10 to 1 (all inclusive)\n* Lazy.range('[1..10)') - range grom 1 to 9\n* Lazy.range('[10..1)') - range from 10 to 2\n* Lazy.range('(1..10]') - range from 2 to 10\n* Lazy.range('(10..1]') - range from 9 to 1\n* Lazy.range('(1..10)') - range from 2 to 9\n* Lazy.range('[5,10..50]') - range from 5 to 50 with a step of 5 (all inclusive)\n\nThen you can use other lazy functions on these ranges.\n\n\n",
"readmeFilename": "README.md",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/pkrumins/node-lazy.git"
},
"scripts": {
"test": "expresso"
},
"version": "1.0.11"
}