本文由大漠根据Micah Godbolt的《Exploring Maps In Sass 3.3(Part 2): Sass Maps & Memoization》一文所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.phase2technology.com/blog/sass-maps-memoization/,以及作者相关信息。
——作者:Micah Godbolt
——译者:大漠
在介绍Sass Maps的博客系列中,第一篇文章主要介绍了Sass3.3 引入了Sass Maps,而在第二部分(这篇文章),我将向大家阐述Sass Maps更强大用途之一:memoization。Memoization技术已经常期用于其他语言当中,以来提高性能。它涉及到一个函数结果的缓存,是这样的,如果一个函数使用相同的的参数调用两次,那么缓存的副本可以用来替代需要再次计算的值。
话说,我们有现个简单的函数的调用是这样的:
$length1: length(cat, dog, fish);
$length2: length(cat, dog, fish);
在这种情况之下,Sass的length()
函数会对列表list(cat,dog,fish)
调用两次,可每次计算的长度都是3。
如果你对Sass提供的函数不太了解,建议你先阅读一下《Sass函数》。——@大漠
这种计算的开销显然是相当小的,但我们考虑一个不同的功能:
// Fibonacci Function
@function fibonacci($n) {
$fib: 0 1;
@for $i from 1 through nth($n,1) {
$new: nth($fib, length($fib)) + nth($fib, length($fib) - 1);
$fib: append($fib, $new);
}
@return $fib;
}
这就是著名的斐波那契(Fibonacci)函数,他创建了一串数字,每个数字是两个预览数的总和。这个函数可以接受多秒钟编译每次使用的功能,想像一下这样的情况:
$fib1: fibonacci(1000);
$fib2: fibonacci(1000);
你让Sass执行完全是相同的,耗费的时间,计算两次。我怀疑你会需要一个斐波那契数列,很多时候,你的网格系统使用了一个函数来制作,它可能会在单个的项目中调用上百次。
Maps允许我们使用Memoization技术,这样当我们调用fibonacci(1000)
第二次时,我们也不需再计算该值。相反,我们将这些值存储在Maps中,我们需要的时候就可以调用。
如何在项目中创建Memoization
你可以通过此链接打开一个示例,接下来的内容,我们根据这个示例内容进行阐述。
我们先创建一个全局的变量$memo
,并且赋予其一个空的map:
$memo:();
第一件事情是就是创建一个辅助函数memo-update()
:
@function memo-update($function, $params, $value) {
$result:();
@if map-has-key($memo, $function) {
$sub-map-new: map-merge(map-get($memo,$function),($params: $value));
$result: map-merge($memo, ($function: ($sub-map-new) ));
}
@else {
$result: map-merge($memo, ($function: ($params: $value)));
}
@return $result;
}
这个函数的功能就是检查函数中是否有条目@if map-has-key($memo,$function)
。如果有则更新sub-map
,并且创建新的条目;如果没有则创建一个新的sub-map
。然后返回新的$memo
,并且更新了$memo
Maps。
我们来创建第二个辅助函数memo-get()
:
@function memo-get($function, $params) {
$result: map-get(map-get($memo,$function),$params);
@return $result;
}
这个函数实现通过$function
的Key在$memo
的Map中得到自己的需,然后通过参数$params
的Key在map-get($memo,$function)
新产生的Map中得到自己的值。看起来蛮复杂的一样。
最后是我们系统的心脏:call-function()
。这个函数调用了前面定义的两个函数。
@function call-function($function, $params...) {
@if map-has-key($memo, $function) {
$result: memo-get($function, $params);
@if $result != null {
@return $result;
}
}
$result: call($function, $params...);
$memo: memo-update($function, $params, $result) !global;
@return $result;
}
当给函数传递参数之后,call-function()
会检查以前是否有调用过。如果有,将会通过memo-get()
函数检索值。如果之前没用,则使用call()
函数,返回结果,并通过memo-update()
来重组$memo
map。
有了这些功能,我们可能通过call-function()
或其他函数名以及参数列表。他会从$memo
的map中索引出值,就算没有,也可以计算出值,并更新到$memo
的map中。
还有很多我们可以做的,而且应该做的,用这些东西可以使其更加强大。
在下周我将会结束Map的这个系列教程。通过这个系列教程,我们可以改善Sass的Maps和如何调用我们的变量,使用变量。在此期间,我阅读了Mike Crittenden的系列教程。
这篇文章个人理解起来蛮复杂的。似懂非懂。希望没有带来太多的误导。——@大漠
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载,烦请注明出处:
英文出处:http://www.phase2technology.com/blog/sass-maps-memoization/
中文译文:http://www.w3cplus.com/preprocessor/sass-maps-memoization.html