- 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/
真实世界Haskell的第8章 globToRegex' (c:cs) = escape c ++ globToRegex' cs 这个函数不是尾递归的,它说答案依赖于 Haskell 非严格(惰性)
documentation for gather/take mentions Binding to a scalar or sigilless container will also force la
Lazy 模块中有两种力量: val force : 'a t -> 'a force x forces the suspension x and returns its result. If x h
在 Lazy.Force 的 MSDN 文档中扩展方法说: Forces the execution of this value and returns its result. Same as Val
我正在编写一个 MVC 5 互联网应用程序,我有一个关于使用 interface 的问题与 Lazy initialization . 这里是有问题的类定义: public class WebAPIT
我对 real world haskell 中的代码有点困惑 import qualified Data.ByteString.Lazy.Char8 as L8 import qualified Da
我从 Hibernate 迁移到 EclipseLink,因为我们需要 EclipseLink 可以很好地处理复合主键,而 Hibernate 则不能(确实不能!)。现在我正在修复我们的 JUnit
我正在观看 Java 内存模型视频演示,作者说与 Lazy Initialization 相比,使用 Static Lazy Initialization 更好,我不清楚他说的是什么想说。 我想接触社
我想使用 Rust 和 once_cell实现一些静态常量结构实例,一个静态常量向量包含这些静态结构实例。 示例代码如下: use once_cell::sync::Lazy; pub struct
首先我必须承认:我对 Haskell 完全陌生。我已经练习了一些,现在在字符串操作方面遇到了一些麻烦: 我需要删除/删除从字符串末尾开始的字符。我期望函数 dropWhileEnd 执行此操作,但是当
我想使用 Rust 和 once_cell实现一些静态常量结构实例,一个静态常量向量包含这些静态结构实例。 示例代码如下: use once_cell::sync::Lazy; pub struct
我有一个 Lazy>其中 T 是一个类,它有一个巨大的字符串和关于文件的元数据。我们称它们为属性 HugeString和属性(property)Metadata 我有这个 U 类,它具有相同的属性 H
下面的代码是使用 str1 替换字符串的三种不同方式( str2 、 str3 和 Data.Text.Lazy.replace ) .他们应该给出相同的输出。 import Data.Text.La
我有一个表 Image 保存图像信息。我还想存储图像本身。我也应该 1.将 Blob 存储在同一个图像表中,然后像下面这样延迟获取它 @Basic(optional = false, fetch =
在这篇快速文章中,我们将通过一个例子来讨论Spring的@Lazy注解。 默认情况下,Spring IoC容器会在应用程序启动时创建并初始化所有单体Bean。我们可以通过使用@Lazy注解来阻止单体B
我有一个 viewController,因为我使用了 Page 控件。每个页面有 4 个 ImageView 。 我已经通过了 Xml 并根据其中的图像数量得到了 pageControl 的页数,即
我使用了一个名为 blazy 的 js,当我向下滚动页面到它时,图像会加载。 图像显示在 pingdom 速度测试中,如果延迟加载适用于图像,它是否应该显示在速度测试树中? 最佳答案 根据我的经验,我
浏览器级别的 Lazyload 是几乎所有浏览器的新功能( https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading
我想尝试惰性表达式评估,但我现在不想深入研究 Haskel。拜托,你能帮忙找出其他语言有这个功能吗? 最佳答案 你可以用多种语言模拟它。 this例如,是 C++ 的通用惰性求值器。正如文章所说,它也
关注,据说foldl'是 foldl 的严格版本. 但是我很难理解,strict 是什么意思?意思是?? foldl f z0 xs0 = lgo z0 xs0 where
我是一名优秀的程序员,十分优秀!