無標題文檔

改进两个 Vim 插件

再趁手的 Vim 插件都想力求达到自己的要求,有些插件要满意终究还得自己「二次开发」下,这两个插件希望能对您有所帮助:

MRU

MRU(Most Recently Used)插件 简单的说, 就是给 Vim 增加「最近打开的文件」功能。脚本本身已经很满足我的需求,但对放到了 File 菜单的二级子菜单中,让我觉得非常的不方便。看着脚本最后更新是 2008 年, 于是自己动手做了以下的小改进:

  1. 将菜单提到根菜单上,在编辑中按 Alt+R 即可弹出 MRU 菜单
  2. 改进菜单显示样式,使其看起来更整齐,并添加文件选择快捷键(按 1-9)
  3. 增加 MRU_Filter_Not_Exists 选项,用于过滤已经不存在的文件

那么如何调用 MRU 呢?当然你可以从命令行调用

:MRU

https://friable.rocks/_/2009_11_05/19632838eb92.jpg

现在也可以使用 Alt+R 弹出菜单以后,直接按 1-9 选择最近打开的文件,如上图。

脚本下载

fontsize.vim

和现在主流的浏览器一样, fontsize.vim 的功能就是通过快捷键放大和缩小字体。 这款脚本唯一的不足就是无法支持中文(也就是没有考虑 &guifontwide 的情况),所以改 进了下。

调用此脚本的方式,下面的代码已经足可以说明

if ! hasmapto("<Plug>FontsizeInc", "n")
    nmap <silent> <Leader>++  <Plug>FontsizeInc
    nmap <silent> <Leader>==  <Plug>FontsizeInc
endif

if ! hasmapto("<Plug>FontsizeDec", "n")
    nmap <silent> <Leader>--  <Plug>FontsizeDec
endif

if ! hasmapto("<Plug>FontsizeDefault", "n")
    nmap <silent> <Leader>00  <Plug>FontsizeDefault
endif

对于 <Leader> 这个按键,在 Windows 下通常是「\」,用你的右手小指就可以找到 :^D

顺便说句,很多兄弟对 Windows 设置中文字体感到迷惑。特别是如果配置文件(_vimrc) 是 utf-8 编码的话,中文字体始终设置不上。这是因为 Windows 的内码还是使用 gbk 编 码(Windows XP 下),因此要靠 iconv 帮忙。

例如我的 _vimrc 中字体相关配置如下(类似的问题也可以举一反三) :

if has("gui_win32")
    exec 'set guifont='.iconv('Courier_New', &enc, 'gbk').':h11:cANSI'
    exec 'set guifontwide='.iconv('微软雅黑', &enc, 'gbk').':h11'
endif

脚本下载

后记:Vim 插件 FontSize 的作者采纳了我的意见,更新了脚本支持中文等多语言字符。同时从他脚本中看出他考虑得比我多得多,再次向他学习 http://www.vim.org/scripts/script.php?script_id=2809

--EOF--

PHP 的闭包之痒(翻译)

原文链接: http://justafewlines.com/2009/10/whats-wrong-with-php-closures/ , 其中比较惹眼的特性之一就是支持了闭包。那么以后,我们也可以和那帮写 Ruby、Javascript 等等「高科技语言」的家伙们一样,写出非常酷的代码吗?呃,其实大部分情况下是可 以的,而有些方面还是令人非常的困扰,下面慢慢道来。

很多语言的都提供了非常优雅和漂亮的操作数组的方法。在下面的例子中,会使用 PHP5.3 以及其他语言提供的闭包功能,用于展示如何「客观的」操作迭代数组。

译注:原文作者比较火星,我不了解 Groovy 以及 Scala 语言,所以这里我加上 Javascript 的实现。

在开始之前先说明下,本例子仅仅是阐明观点,并没有考虑性能等其他方面的因素。

「货比三家」

用个简单的例子开始,有下面个数组:

$nums = array(10, 20, 30, 40);

需要找出数组中大于 15 的项。那么,不考虑闭包的情况下,我们或许会这样写:

$res = array();
foreach ($nums as $n) {
    if ($n > 15) {
        $res[] = $n;
    }
}

如果语言本身有闭包支持的,那么或许会这样写(Groovy 语言)

def res = nums.findAll { it > 15 }

或者使用 Scala 语言

val res = nums filter (_ > 15)

译注:Javascript 1.6 的话会是如下

var res = nums.filter(function(c){return c > 15});

因为循环操作已被抽象起来,所以可以看到 Groovy 、Scala (以及 Javascript) 都很漂亮得用一行就可以搞定。

当然,如果使用 PHP5.3 的闭包,也可以做到

$res = array_filter($nums, function($v) { return $v > 15; });

PHP 在这方面使用了比 Scala 更多的字符,但对比先前的例子,它更简短并且能更好得阅读。

顺便说下,上面的 PHP 代码实际上是使用了 Lambda 解析式,并不是个真正的闭包,这个 并不是我们目前关注的重点。详细阐述 PHP 闭包以及 Lambda 解析式的资料,可以 参考这里

目前看来感觉都还不错,那么我们再的题目增加点难度:找到所有大于 15 的项, 然后乘以 2 再加上作用域中的的某个变量值以后再返回。

Groovy 的实现:

def x = 1
def res = nums .findAll { it > 15 } .collect { it * 2 + x }

Scala 的实现:

val x = 1
val res = nums filter (_ > 15) map (_ * 2 + x)

译注,Javascript 的实现:

var i = 1;
var res = nums.filter(function(c){return c > 15}).map(function(c){return c * 2 + i});

以及 PHP:

$x = 1;
$res = array_map(
    function($v) use ($x) { return $v * 2 + $x; },
    array_filter(
        $nums,
        function($v) { return $v > 15; })
);

光从代码量方面,现在看起来 PHP 与其他语言有出入了。先抛开代码字面上本身 的审美不谈,上面的 PHP 代码还有个额外的问题。

例如,如果需要使用数组的键而非值作比较,怎么办?是的,上面的代码就办不到 了。同时,从语法角度上说,上面的代码非常难以阅读。

返璞归真,这时还是得返回老土的思路去解决问题:

$x = 1;
$res = array();
foreach ($nums as $n) {
    if ($n > 15) {
        $res[] = $n * 2 + $x;
    }
}

呼,这样看起来又很清楚了。但这个时候你或许又会迷惑了:「那还瞎折腾啥,这不就是个 数组操作吗?」。

是的,好戏还在后头。这个时候该让 PHP 的某些高级特性出场,来搞定这看似有自残倾向 的「无聊问题」。

ArrayObject – 对数组的封装

PHP 有个称作 SPL 的标准库 ,其中包含了个叫做 ArrayObject 的类,它能提供「像数组一 样操作类」的功能,例如

$res = new ArrayObject(array(10, 20, 30, 40));
foreach ($res as $v) {
    echo "$v\n";
}

ArrayObject 是个内置的类,所以你可以像其他类类操作一样封装它。

Arr - 包上糖衣

既然我们已经有了 ArrayObject 以及闭包这些特性,我们就可以开始尝试封装它:

class Arr extends ArrayObject
{
    static function make($array)
    {
        return new self($array);
    }

    function map($func)
    {
        $res = new self();
        foreach ($this as $k => $v) {
            $res[$k] = $func($k, $v);
        }
        return $res;
    }

    function filter($func)
    {
        $res = new self();
        foreach ($this as $k => $v) {
            if ($func($k, $v)) {
                $res[$k] = $v;
            }
        }
        return $res;
    }
}

好了,万事俱备。下面重写的 PHP 代码就可以解决上面提到的问题,并且看起来语法上「差 不多」了:

$res = Arr::make($nums)
    ->filter(function($k, $v) { return $v > 15; })
    ->map(function($k, $v) { return $v * 2; });

上面的代码与传统方式有何不同呢?首先,它们可以递归并形成作用链式的调用,因此可以 添加更多的类似操作。

同时,可以通过回调的两个参数分别操作数组的键以及值其项 - $k 对应键以及 $v 对应值 。这使得我们可以在闭包中使用键值,这在传统的 PHP 函数 array_fliter 中是无法实现的。

另外个带来的额外好处就是更加一致 API 调用。使用传统的 PHP 函数操作,它们有可能第一个参数是个闭包,或者是个数组,抑或是多个数组…总之谁知道呢?

这里是 Arr 类的完整源代码 ,还包含了其他有用的函数(类似 reduce 以及 walk),其实它 们的实现其实方式和代码类似。

博弈

这个问题其实很难回答 - 这需要根据代码的上下文以及程序员自身等众多因素决定。其实 ,当我第一眼看见 PHP 的闭包实现时,我感觉似乎回到了那很久以前的 Java 时期,当时 我在开始使用 匿 名内置类(anonymous inner classes) 来实现闭包。当然,这虽然可以做到, 但看起来实在是些画蛇添足。PHP 闭包本身是没错,只是它的实现以及语法让我感到非常的困惑。

其他具有闭包特性的语言,它们可以非常方便的调用闭包并同时具有优雅的语法。在上面的例子 中,在 Scala 中使用传统的循环也可以工作,但你会这样写吗?而从另个方面,那么有人 说上面这个题目使用 PHP 的闭包也可以实现,但一般情况下你会这样写吗?

可以确定,PHP 闭包在些情况下可以成为锐利的军刀(例如延时执行以及资源调用方面), 但在传统的迭代以及数组操作面前就显得有些为难。不要气馁不管怎么样, 返璞归真编写具有兼容性的、清爽的代码以及 API 是最重要的。

结束语

像所有后来加上的语法特性一样(记得当年 Java 的 Generics 特性不?以及前几年的 PHP OOP 特性),它们都需要时间磨合以及最终稳定下来。随着 PHP5.3 甚至将来的 PHP6 逐渐普及,越来越多的技巧和特性相信在不远的将来逐渐的被聪明的程序员挖掘出来。

回到最初文章开头那个题目,对比

$res = Arr::make($nums)
    ->filter(function($k, $v) { return $v > 15; })
    ->map(function($k, $v) { return $v * 2; });

以及

val res = nums filter (_ > 15) map (_ * 2)

两者之间的区别。归根结底它们仅是语法而已,本质上都是殊途同归解决了同个问题。程序 语言的应用特性不同,自然孰优孰劣也就无从比较。

最后, 这里有此篇文章的代码示例 , 相信可以找到更多如何使用 PHP 进行函数式迭代(当然不仅仅是这些)的心得。

-- Split --

不靠谱之博主心得

坦白讲,虽然在 PHP5.0 之前就了解过提出的新增闭包等功能,但在看到 PHP5.3 提供的闭 包以及 Lambda 功能后,与原本心理期待的还是有些出入。

甚至相对于熟悉的 JavaScript,PHP 的闭包在我看来,像是「别的语言都有了,所以我也要有」 的这种心态下的产物。

但正如上文中所言,相比 JavaScript 等其他动态语言,PHP 出于自身的应用以及实现的哲学 出发,与其他开发语言不尽相同。

因此在某些特性的调用方式、实现方法也会不一样,这难免会让熟悉另外具有类似功能的语言 的人感到的不适应。

从 PHP5.3 推出至今,还不到半年的时间,相比 JavaScript 等这些早已具有闭包等特性的 动态语言相比,自然是显得非常稚嫩。

同时,广大的开发者对于 PHP5.3 提供的包括闭包在内的新特性还在持观望态度。PHP 的闭包特性目前还是存在于实验室中,其应用于实际开发如要突破的不仅仅是语言特性 ,还要经过效率、安全性等方面的考验。

但相信,如原文作者所言,随着 PHP 版本的推进,PHP 的闭包应用场合会越来越频繁。像 当年 PHP4 转换到 PHP5 一样,对语言新特性的适应,其实是种痛并快乐着的过程。

家乡的孔明灯

国庆并没无外出,只是呆在老家。虽然在这土生土长,但在外很多年的我,现在看来似乎更像是位睡客。吃完晚饭,穿着拖鞋短裤即可上街散步,逛着熟悉的店铺、听着熟悉的乡音,也倒是显得格外的惬意。

https://friable.rocks/_/2009_11_05/9918883019a6.jpg

不经意抬头望了下天,有几只红艳艳的孔明灯飘过。县城不大,于是就着往孔明灯飘过来的方向走去。稍顷,就发现了源头,孩子们围绕着买孔明灯的小贩,在欢笑声中又个孔明灯升上了天。

不知道从什么时候开始,这里开始流行放孔明灯。其实孔明灯的制作也简单,几根竹签糊上纸,然后下面安放半截的蜡烛,点上加热后就可以放飞。孔明灯可以飞很远,红色灯升空后随风远去,地面上的孩子们慢慢得看它飘远、消失。

这个情景使我想起来童年过年的时候。县城的风俗是正月过十四,点花灯、放炮仗那天会很热闹。最开心的也是孩子们,除了压岁钱以外,这时候家长们会给孩子们扎毛兔灯。

通体白色的毛兔灯,加上它眼睛上的两点红色,甚是可爱。在毛兔灯上再牵出根绳子,孩子就拖着灯满街的欢跑。每家每户的手艺不同,所以毛兔灯的样式也各不一样。有时候孩子们的争吵就是比谁家的灯漂亮,天真的话语往往会引得在旁大人的哄笑。

https://friable.rocks/_/2009_11_05/38584830197c.jpg

在旁卖孔明灯的小贩正在劝说家长多买几个孔明灯,否则「看着天上孤零零的一盏多寂寞」,这个时家长多半不会拒绝。于是可以再等一会,就能看见又一批孔明灯从头顶上飘过,耳畔同时也再次响起孩子们欢畅的笑声。

孔明灯,这曾几何时作为战争通信用的工具,现在已转变成了承载希望和寄托的信物。虽然现在的生活节奏日益的变快,但对美好生活的向往不会变。或许现在那些面对孔明灯欢笑的孩子们,在将来这也会变成他们童年美好的回忆。

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 要知道作为码农取名是件很难的事情,所以不想在取名这事情上太费心思。

作为八零后,自认为还仅存点点可能不怎么被理解的幽默感,以及对平淡生活的追求和向往。 为了避免不必要的麻烦,声明本站所输出的内容以及观点仅代表个人,不代表自己所服务公司或组织的任何立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章