<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>frankking (王涛)</title>
    <link>https://ruby-china.org/frankking</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Vuejs 初试</title>
      <description>&lt;p&gt;Vuejs 以极其简单且友好的方式解决了前端开发中 ViewModel 层面的问题，加上原来越完善的生态环境，让越来越的同学开始接触和学习这个框架。&lt;/p&gt;

&lt;p&gt;之前我在学习的过程中曾经尝试以 Vuejs 为基础用最简洁的代码实现一个 Todo 应用，然后把心得体会写成了一片文章，在这里跟大家分享，希望对准备学习 Vuejs 的同学提供一个感官上的认识，欢迎 Vuejs 大牛们指正文中的错误 :- ) &lt;/p&gt;

&lt;p&gt;正文：&lt;/p&gt;

&lt;p&gt;看到 Vuejs 的第一眼，觉得就算是前端开发经验不多的我，也能轻松地倒腾倒腾。为什么？&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;轻量，核心包很小&lt;/li&gt;
&lt;li&gt;无依赖&lt;/li&gt;
&lt;li&gt;学习成本低，Dom-based，双向数据绑定，动态组件&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;于是乎，我琢磨着搞一个 Todos 应用，功能如下：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/17174-7aa020df640156f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt="Todos.png"&gt;&lt;/p&gt;

&lt;p&gt;当然，css 样式和本地数据持久化就不做了。&lt;/p&gt;

&lt;p&gt;什么 MVC 啊，MVVM 都不需要考虑那么多，先写个能通过输入框添加 Todo 的列表：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://cdn.jsdelivr.net/vue/1.0.16/vue.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"todos"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h4&amp;gt;&lt;/span&gt;Todos&lt;span class="nt"&gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"newTodo"&lt;/span&gt; &lt;span class="na"&gt;v-on:keyup.enter=&lt;/span&gt;&lt;span class="s"&gt;"addTodo"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"new to do"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"todo in todos"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ todo.content }}
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;简单的几行代码就搞定了，Vuejs 确实挺简洁的：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;#todos&lt;/code&gt; 对应一个 Vue 对象&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;#todos&lt;/code&gt; 中可以双向绑定 Vue 对象中的数据&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;#todos&lt;/code&gt; 中可以绑定事件响应函数&lt;/li&gt;
&lt;li&gt;v- 开头的属性中，可以使用 Vue 的 DSL&lt;/li&gt;
&lt;li&gt;在非 vue 定义的属性中，使用 {{ }} 包裹 Vue 的 DSL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;好了，有了这个基础版本，虽然有点太简陋了，但我们可以在此基础上添加新的功能：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;显示当前剩余未完成的 Todo 的数量&lt;/li&gt;
&lt;li&gt;显示所有 未完成的 Todo/已完成的 Todo&lt;/li&gt;
&lt;li&gt;完成一个 Todo&lt;/li&gt;
&lt;li&gt;删除一个 Todo&lt;/li&gt;
&lt;li&gt;删除所有 已完成的 Todo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这些不就是对 todos 这个数组的 查询，添加，删除 的操作嘛？于是乎，当 todos 的业务逻辑变得复杂的时候，单单用 Array 这个基本数据类型就不行了，然后就有了所谓的 Model 这一层的抽象。&lt;/p&gt;

&lt;p&gt;做好 Model 这一层后，我们响应一些 View 上的用户事件如，点击 Todo 完成按钮/Todo 删除按钮/清除已完成 Todo 的按钮，变换 Todo 列表的类型，响应其实就是在当事件发生时执行相应的 Model 操作。将 View 显示逻辑 和 View 相关的 Model 联系起来所抽象的一层，就是所谓的 ViewModel.&lt;/p&gt;

&lt;p&gt;而 Vuejs 所提供的功能之一就是简化 ViewModel 这一层的开发复杂度，或者说提出了一种开发思路及其相应的 api. &lt;/p&gt;

&lt;p&gt;最终效果：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload-images.jianshu.io/upload_images/17174-7ee3840ef0a7487f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt="my_todos.png"&gt;
&lt;a href="https://jsfiddle.net/Focinfi/g0g7mver/10/" rel="nofollow" target="_blank" title=""&gt;Todos 完整项目演示&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;所以在 Vuejs 的帮助下，我们可以轻松地以 Model 层的数据为基础，构建相应的 ViewModel.&lt;/p&gt;

&lt;p&gt;更多资料：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://vuejs.org/" rel="nofollow" target="_blank" title=""&gt;vuejs.org&lt;/a&gt;
&lt;a href="http://teahour.fm/2015/08/16/vuejs-creator-evan-you.html" rel="nofollow" target="_blank" title=""&gt;Vue.js 框架的作者做客 Teahour&lt;/a&gt;&lt;/p&gt;</description>
      <author>frankking</author>
      <pubDate>Wed, 25 May 2016 09:20:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/30116</link>
      <guid>https://ruby-china.org/topics/30116</guid>
    </item>
    <item>
      <title>以 Huffman coding 为例看函数式编程</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;不同编程即为不同解决问题的思路&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;解决一个问题有很多思路，比如：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;过程式 (C 语言)：将解决问题的方式分解成若干步骤来控制数据。&lt;/li&gt;
&lt;li&gt;面向对象式 (Java/Ruby)：以对象为基本单位，定义其行为控制其内部状态，通过不同对象之间的协作解决问题。&lt;/li&gt;
&lt;li&gt;函数式 (Lisp)：一切皆为函数，用连贯的思维方式定义过程，常用递归。&lt;/li&gt;
&lt;li&gt;组合式：将不同的解决方式组合起来，golang 经常会将面向对象与过程式组合起来。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="示例： Huffman编码"&gt;示例：Huffman 编码&lt;/h3&gt;
&lt;p&gt;用 Lisp 的一个方言 Scheme 来实现：&lt;/p&gt;

&lt;p&gt;输入 &lt;code&gt;'((A 1) (B 3) (C 2))&lt;/code&gt;, A B C 为带编码字符，1 2 3 为出现次数。
输出 &lt;code&gt;'((b 0) (a 0 1) c 1 1)&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="定义叶子节点"&gt;定义叶子节点&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(define (make-leaf symbol weight)
  (list 'leaf symbol weight))

(define (leaf? object)
  (eq? (car object) 'leaf))

(define (symbol-leaf object)
  (cadr object))

(define (weight-leaf object)
  (caddr object))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有接触过 lisp 的同学可能对上面的表示方式有点陌生，其实就是用括号代表方法调用，括号里的第一个位置是方法名称，后面的是调用该方法的参数。&lt;/p&gt;

&lt;p&gt;上面的几行代码定义了叶子节点 leaf 及相关函数。&lt;/p&gt;
&lt;h5 id="定义树节点"&gt;定义树节点&lt;/h5&gt;&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-code-tree&lt;/span&gt; &lt;span class="nv"&gt;left&lt;/span&gt; &lt;span class="nv"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; 
    &lt;span class="nv"&gt;left&lt;/span&gt;
    &lt;span class="nv"&gt;right&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;symbols&lt;/span&gt; &lt;span class="nv"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;symbols&lt;/span&gt; &lt;span class="nv"&gt;right&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight&lt;/span&gt; &lt;span class="nv"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight&lt;/span&gt; &lt;span class="nv"&gt;right&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;left-branch&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;right-branch&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadr&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;symbols&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;leaf?&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;symbol-leaf&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;caddr&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;leaf?&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight-leaf&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadddr&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同样的道理，定义了用于在构造 Huffman 树中非叶子的节点 tree 及其相关取值函数。&lt;/p&gt;
&lt;h5 id="有序 list 构造方法"&gt;有序 list 构造方法&lt;/h5&gt;&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;;如果 set 为空，则返回以 x 作为唯一元素的 list&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cond&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;null?&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="c1"&gt;;如果 set 的第一个元素的 weight 大于 x 的 weight，则将 x 和 set 组合成一个新的 list 返回&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;weight&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="c1"&gt;; 否则将 set 的以第一个只取出，让后递归调用 `adjoin-set`&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;adjoin-set&lt;/code&gt; 的功能就是 x 插入到有序 list set 中，保证插入后的 list 仍然有序。lisp 中的 &lt;code&gt;cond&lt;/code&gt; 可理解为 其他语言中的 &lt;code&gt;switch&lt;/code&gt;，而 &lt;code&gt;cons&lt;/code&gt; 可理解为将两个元素结合成一个 list。乍一看这个所谓“插入”元素的方法有点奇怪，而且没有用任何&lt;strong&gt;临时变量&lt;/strong&gt;。其思路将整个插入的过程用递归调用的方式表示：用过程（函数）代替了临时变量。举了例子：&lt;code&gt;(adjoin-set 3 '(1 2))&lt;/code&gt;，执行顺序是：&lt;/p&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到在执行序列中，推迟 &lt;code&gt;cons&lt;/code&gt; 的执行，用参数求值压栈从而省去了临时变量。在  &lt;code&gt;make-leaf-set&lt;/code&gt; 中思路也一样：不断地从 paris 中取元素，交给 &lt;code&gt;adjoin-set&lt;/code&gt; 插入到 list 中。整个编写过程中基本上用程序流畅地表达了我们的解题思路，代码如下：&lt;/p&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-leaf-set&lt;/span&gt; &lt;span class="nv"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;null?&lt;/span&gt; &lt;span class="nv"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;pair&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-leaf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadr&lt;/span&gt; &lt;span class="nv"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-leaf-set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr&lt;/span&gt; &lt;span class="nv"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="Huffman树构造方法"&gt;Huffman 树构造方法&lt;/h5&gt;
&lt;p&gt;在插入元素这种简单的问题中函数式威力还远远没有体现出来，请看下面构造 Huffman 树 的函数实现：&lt;/p&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-tree&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cond&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;null?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;null?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadr&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;error&lt;/span&gt; &lt;span class="s"&gt;"leaves is not enough"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;null?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cddr&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-code-tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadr&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;adjoin-set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-code-tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cadr&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cddr&lt;/span&gt; &lt;span class="nv"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;几行代码就将构造 Huffman 树 的核心逻辑表达清楚了：将按 weight 升序 leaves 的前两个拿出来做成一个 tree node，&lt;code&gt;adjoin-set&lt;/code&gt; 到剩下的 leaves 中，然后不断重复这个操作，直到 leaves 中只剩下两个元素，将这两个元素最为 最终 Huffman 树 的左右子树，然后返回。怎么样？一气呵成。&lt;/p&gt;
&lt;h5 id="编码"&gt;编码&lt;/h5&gt;
&lt;p&gt;对 Huffman 树 遍历编码的实现也是精炼得有种思维的美感：
先进行左子树遍历，直到找到叶子节点，构造成结果 list 中一个元素，然后回到上一层递归，进入右子树，不断重复直到遍历完所有节点。&lt;/p&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;encode&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;visit&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;leaf?&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;; 找到了一个叶子节点&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;symbol-leaf&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;; 用 cons 对 visit 的递归调用&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;visit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;left-branch&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;visit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;right-branch&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cons&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;visit&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;

&lt;span class="c1"&gt;;测试&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;leaf-set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-leaf-set&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;make-tree&lt;/span&gt; &lt;span class="nv"&gt;leaf-set&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;encode&lt;/span&gt; &lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;; outputs: ((b 0) (a 0 1) c 1 1)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;详细代码请进 &lt;a href="https://github.com/Focinfi/scheme-practices/blob/master/haffman.scm" rel="nofollow" target="_blank" title=""&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ps: 本篇用到部分《计算机程序的构造与解析》代码。强烈建议大家学习 MIT 的这门公开课。&lt;/p&gt;</description>
      <author>frankking</author>
      <pubDate>Mon, 02 May 2016 22:19:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/29896</link>
      <guid>https://ruby-china.org/topics/29896</guid>
    </item>
    <item>
      <title>各位同学是如何解决另一半问题的？</title>
      <description>&lt;p&gt;想了解一下论坛里的各位前辈是如何解决 女朋友/男朋友 问题？学校里面谈的恋爱就不算了，主要是工作以后的。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;通过何种方式认识合适的异性朋友？（朋友介绍，豆瓣，相亲，婚恋网......）&lt;/li&gt;
&lt;li&gt;作为程序员，大家对异性朋友有哪些基本要求？&lt;/li&gt;
&lt;li&gt;交往后，自己在工作和生活中有哪些变化？&lt;/li&gt;
&lt;li&gt;交往多长时间会考虑结婚的问题？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;大家也给像我这样刚进入社会的年轻程序员支支招呗。&lt;/p&gt;</description>
      <author>frankking</author>
      <pubDate>Wed, 06 Apr 2016 08:33:44 +0800</pubDate>
      <link>https://ruby-china.org/topics/29554</link>
      <guid>https://ruby-china.org/topics/29554</guid>
    </item>
    <item>
      <title>Ruby 搭建本地 Golang 文档服务器</title>
      <description>&lt;p&gt;平时我们看 golang 文档的方式通常有：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;go doc &amp;lt;package&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;golang.org/pkg 或者国内的 godoc.golangtc.com/pkg/&lt;/li&gt;
&lt;li&gt;看源码，当然这是最好的方式，只是需要更多的时间和耐心。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果没有网络，我一般会选择 方式 1 + 方式 3，但缺点是可读性差。&lt;/p&gt;

&lt;p&gt;后来了解到，&lt;code&gt;godoc -html &amp;lt;package&amp;gt;&lt;/code&gt; 可以生成 HTML 文档，所以就思考如何搭建本地的 localhost:3000/pkg&lt;/p&gt;

&lt;p&gt;先取个名字，godocserver&lt;/p&gt;

&lt;p&gt;步骤如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;获取所有 golang built-in packages 名称&lt;/li&gt;
&lt;li&gt;遍历所有 packages 运行 &lt;code&gt;godoc -html &amp;lt;package&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;保存所有文件，启动一个静态文件服务器&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;利用 Ruby 实现 步骤 1、2，要注意遍历 &lt;code&gt;$GOPATH/src/&lt;/code&gt; 时要过滤一些不需要的目录，创建文件时，要先创建对应的目录。&lt;/p&gt;

&lt;p&gt;启动静态服务器用 golang 和 ruby 都可以，我用的是 negroni，就三行代码。&lt;/p&gt;

&lt;p&gt;问题是，这样的页面完全没有样式啊，所以我不得不去 golang.org/pkg 上 copy css 和 js 文件。&lt;/p&gt;

&lt;p&gt;然后将 Index 的样式修改成这样：
&lt;img src="http://upload-images.jianshu.io/upload_images/17174-9be96146433722ee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt="show.png"&gt;&lt;/p&gt;

&lt;p&gt;最后实现 package 导航：
&lt;img src="http://upload-images.jianshu.io/upload_images/17174-ed07c5f6aeff98a6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" title="" alt="nav.png"&gt;&lt;/p&gt;

&lt;p&gt;这个功能我们需要知道所有已存文档的名称，所以我们需要维护一个文件 all_documents.json 供前端使用，然后我们需要做一个带有过滤功能的列表。这里用 Vue.js 作双向数据绑定 (好用，好用，好用)。&lt;/p&gt;

&lt;p&gt;至此，我们就可以愉快的在本地看 golang 文档啦。&lt;/p&gt;

&lt;p&gt;更多阅读：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Focinfi/godocserver" rel="nofollow" target="_blank" title=""&gt;godocserver 项目地址&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jianshu.com/p/20bb1a8fe686" rel="nofollow" target="_blank" title=""&gt;Vuejs 初试&lt;/a&gt;&lt;/p&gt;</description>
      <author>frankking</author>
      <pubDate>Sat, 12 Mar 2016 15:59:54 +0800</pubDate>
      <link>https://ruby-china.org/topics/29278</link>
      <guid>https://ruby-china.org/topics/29278</guid>
    </item>
    <item>
      <title>[讨论] 用 Ruby 实现 Ruby 的 inject 方法</title>
      <description>&lt;p&gt;Ruby 新手，自己用 Ruby 实现了 Ruby 的&lt;code&gt;Enumerable#inject&lt;/code&gt;方法：&lt;code&gt;Enumerable#my_inject&lt;/code&gt;
代码如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Enumerable&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_inject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;
    &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; 
    &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# 判断参数个数及类型&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"wrong number of arguments &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; for 0..2"&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
      &lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt; &lt;span class="no"&gt;Symbol&lt;/span&gt;
      &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
      &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="c1"&gt;# 给accumulation赋值&lt;/span&gt;
    &lt;span class="n"&gt;accumulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;

    &lt;span class="c1"&gt;# 如果参数中有Symbol（方法）&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; 
      &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;accumulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accumulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; 
      &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;accumulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;accumulation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;accumulation&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大家有兴趣的可以一起来讨论有没有更优雅的写法？
还有，我是新手，有经验的前辈可否指点一下我的代码？（思路、命名、注释..）&lt;/p&gt;</description>
      <author>frankking</author>
      <pubDate>Tue, 09 Dec 2014 13:04:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/23104</link>
      <guid>https://ruby-china.org/topics/23104</guid>
    </item>
  </channel>
</rss>
