- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
首先,让我为不认识的人定义short-cut fusion。考虑以下JavaScript中的数组转换:
var a = [1,2,3,4,5].map(square).map(increment);
console.log(a);
function square(x) {
return x * x;
}
function increment(x) {
return x + 1;
}
[1,2,3,4,5]
,其元素首先平方
[1,4,9,16,25]
,然后递增
[2,5,10,17,26]
。因此,尽管我们不需要中间数组
[1,4,9,16,25]
,我们仍然可以创建它。
var a = [1,2,3,4,5].map(compose(square, increment));
console.log(a);
function square(x) {
return x * x;
}
function increment(x) {
return x + 1;
}
function compose(g, f) {
return function (x) {
return f(g(x));
};
}
map
和
map
函数,将两个单独的
square
调用合并为一个
increment
调用。因此,不会创建中间数组。
square
和
increment
数组的每个元素,但是我们可能不需要所有结果。
[2,5,10]
,而无需计算后2个结果
[17,26]
,因为不需要它们。
var List = defclass({
constructor: function (head, tail) {
if (typeof head !== "function" || head.length > 0)
Object.defineProperty(this, "head", { value: head });
else Object.defineProperty(this, "head", { get: head });
if (typeof tail !== "function" || tail.length > 0)
Object.defineProperty(this, "tail", { value: tail });
else Object.defineProperty(this, "tail", { get: tail });
},
map: function (f) {
var l = this;
if (l === nil) return nil;
return cons(function () {
return f(l.head);
}, function () {
return l.tail.map(f);
});
},
take: function (n) {
var l = this;
if (l === nil || n === 0) return nil;
return cons(function () {
return l.head;
}, function () {
return l.tail.take(n - 1);
});
},
mapSeq: function (f) {
var l = this;
if (l === nil) return nil;
return cons(f(l.head), l.tail.mapSeq(f));
}
});
var nil = Object.create(List.prototype);
list([1,2,3,4,5])
.map(trace(square))
.map(trace(increment))
.take(3)
.mapSeq(log);
function cons(head, tail) {
return new List(head, tail);
}
function list(a) {
return toList(a, a.length, 0);
}
function toList(a, length, i) {
if (i >= length) return nil;
return cons(a[i], function () {
return toList(a, length, i + 1);
});
}
function square(x) {
return x * x;
}
function increment(x) {
return x + 1;
}
function log(a) {
console.log(a);
}
function trace(f) {
return function () {
var result = f.apply(this, arguments);
console.log(f.name, JSON.stringify([...arguments]), result);
return result;
};
}
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
square [1] 1
increment [1] 2
2
square [2] 4
increment [4] 5
5
square [3] 9
increment [9] 10
10
如果不使用惰性评估,则结果将是:
square [1] 1
square [2] 4
square [3] 9
square [4] 16
square [5] 25
increment [1] 2
increment [4] 5
increment [9] 10
increment [16] 17
increment [25] 26
2
5
10
但是,如果您看到源代码,则每个函数
list
,
map
,
take
和
mapSeq
返回一个中间的
List
数据结构。不执行捷径融合。
Immutable
also provides a lazySeq
, allowing efficient chaining of collection methods likemap
andfilter
without creating intermediate representations. Create someSeq
withRange
andRepeat
.
Seq
数据结构可高效链接诸如
map
和
filter
之类的收集方法,而无需创建中间表示(即,他们执行捷径融合)。
Seq
describes a lazy operation, allowing them to efficiently chain use of all the Iterable methods (such asmap
andfilter
).Seq is immutable — Once a Seq is created, it cannot be changed, appended to, rearranged or otherwise modified. Instead, any mutative method called on a Seq will return a new Seq.
Seq is lazy — Seq does as little work as necessary to respond to any method call.
Seq
确实是懒惰的。但是,没有任何示例显示确实没有创建中间表示(他们声称这样做)。
Lazy.range(1, 1000)
.map(square)
.filter(multipleOf3)
.take(10)
.each(log);
function square(x) {
return x * x;
}
function multipleOf3(x) {
return x % 3 === 0;
}
function log(a) {
console.log(a);
}
<script src="https://rawgit.com/dtao/lazy.js/master/lazy.min.js"></script>
map
,
filter
和
take
函数产生中间
MappedSequence
,
FilteredSequence
和
TakeSequence
对象。这些
Sequence
对象本质上是迭代器,无需中间数组。
Sequence
结构。
Lazy(array).map(f).map(g)
这样的表达式会产生两个单独的
MappedSequence
对象,其中第一个
MappedSequence
对象将其值提供给第二个对象,而不是第二个通过完成两者的工作来替换第一个(通过函数组合) )。
最佳答案
我是Immutable.js的作者(也是Lazy.js的粉丝)。
Lazy.js和Immutable.js的Seq是否使用捷径融合?不,不完全是。但是它们确实删除了操作结果的中间表示。
捷径融合是一种代码编译/翻译技术。您的例子很好:
var a = [1,2,3,4,5].map(square).map(increment);
var a = [1,2,3,4,5].map(compose(square, increment));
As far as I know they get rid of intermediate arrays by emulating lazy evaluation via sequence objects (i.e. iterators). However, I believe that these iterators are chained: one iterator feeding its values lazily to the next. They are not merged into a single iterator. Hence they do not "eliminate intermediate representations". They only transform arrays into constant space sequence objects.
var a = [1,2,3,4,5];
var b = a.map(square); // b: [1,4,6,8,10] created in O(n)
var c = b.map(increment); // c: [2,5,7,9,11] created in O(n)
var a = [1,2,3,4,5];
var f = compose(square, increment); // f: Function created in O(1)
var c = a.map(f); // c: [2,5,7,9,11] created in O(n)
var a = [1,2,3,4,5];
var i = lazyMap(a, square); // i: Iterable created in O(1)
var j = lazyMap(i, increment); // j: Iterable created in O(1)
var c = Array.from(j); // c: [2,5,7,9,11] created in O(n)
[1,4,6,8,10]
的数据结构。
compose
的结果是一个新函数。功能组合(手写或捷径融合编译器的结果)与Iterable组合非常相关。
lazyMap
的简单实现可能是这样的:
function lazyMap(iterable, mapper) {
return {
"@@iterator": function() {
var iterator = iterable["@@iterator"]();
return {
next: function() {
var step = iterator.next();
return step.done ? step : { done: false, value: mapper(step.value) }
}
};
}
};
}
关于javascript - Immutable.js或Lazy.js是否执行捷径融合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27529486/
我输入了一个包含两个元素的 vector 。然后我将另一个元素 push_back 到它,并期望什么结果类型也是一个 vector 。但事实并非如此。 例子: typedef boost::fusio
首先让我先说,我以前在这里问过类似的问题,但从来没有得到解决我缺乏知识/问题的好答案。 首先,让我从一个分支策略提案开始。这就是我们的工作,我很高兴听到其他评论,以及为什么这很糟糕。但要明白它通常对我
所以我将一个带有 javascript 的字符串发送到 php 页面: if(cp.value!=''){ s+=cp.name +" LIKE '%"+ cp.value +"%'";
我有一个简单的问题,我该如何使用 which和 which.max同时。 我想选择最大值epnum为行 id == B13639J2 . 我需要检索 row number因为我需要对变量进行一些手动更
我想将带有 Groovy 脚本的文件上传到 Confluence。 As this Pythonscript example!我开始将代码翻译成 groovy, // Groovy def serve
我有一个融合 vector ,其元素具有多个不同类型的成员数据,我想创建一个新的融合 vector ,它将仅投影特定的数据成员。我已经对此进行了一段时间的研究,但没有任何进展。 #include #
我正在尝试使用 Python 的 xmlrpclib 创建一个新的页面以汇合。我已经知道如何更新现有页面的内容,但如何创建一个全新的页面? 我使用了以下脚本来更新内容: import xmlrpcli
我正在使用 Pow 在 Mac OS X 上为 Rack 应用程序提供服务。http://myapp.dev正确显示应用程序。在同一台机器上,我使用 VMware Fusion 运行 Windows
我检查了 Cassandra 和 Infinispan 的主要特性。它们似乎具有并提供非常相似的特性和功能: NoSQL 数据存储 坚持 去中心化 支持复制 可扩展性 容错 MapReduce 支持
我在Drupal 7网站中使用Search API和Elasticsearch Connector。我已经在AWS中托管了elasticsearch。搜索完美无误。但是我想像在Drupal.org搜索
我最近重新打开了几年前参与的一个项目。我写了一个小的 python 脚本来构建项目。我想将其移植到 CMake。 我遇到的问题是脚本使用了 pkg-config在 linux 上找到 fuse 头文件
我正在尝试访问 Yelp fusion API。我正在关注documentation并来到这段代码: const request = require('request'); // As you can
这是一个 vanilla Ubuntu 16.04 LTS,准确地说是基于 Xubuntu core。所以我需要自己安装包。除了 meld 之外,一切都很顺利,开始时,我会得到: (meld:4188
我正在尝试对惰性求值在 Java 流 API 中的应用形成一个简洁而连贯的理解。 这是我目前的理解: 元素仅在需要时才被消耗,即流是惰性的,中间操作也是惰性的,例如过滤器,仅在需要时进行过滤。 中间操
我使用 conluent jdbc-sink 将数据从 kafka 加载到 oracle。 但是我用数据编写了关于值(value)的模式。 我不想用数据编写模式,如何在 kafka 主题上编写模式,然
我在这里编写了一个 2D 融合套索代码。 [m n] = size(circle); cvx_begin variable theta(m, n); minimize( norm(ci
目前我正在开发一个使用 dx9 创建叠加层的应用程序。现在我遇到了一个问题,自从我将 Windows 10 升级到最新版本(Creators Update)后,它无法使用 alpha channel
我正在尝试编写类似 fiber 的代码,这样我就可以进入任务并从中退出。我试过的代码: class TaskActivity { CancellationTokenSource _m=new
我使用 NPM 在 React.js 中创建了一个前端。作为 IDE,我在这里使用 IntelliJ IDEA。该项目将使用我单独创建的 Spring Boot 编写的后端,也在 IntelliJ I
Cassandra 连接器在融合升级到 3.3.0 后失败。 Cassandra驱动的版本是3.3。堆栈如下。 [2017-09-14 08:56:28,123] ERROR java.lang.re
我是一名优秀的程序员,十分优秀!