<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>jakit (jakitto)</title>
    <link>https://ruby-china.org/jakit</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>有没有人试过绕开依赖来 rvm install ruby</title>
      <description>&lt;p&gt;如果在一台没有 root / sudo 权限的 Linux server，是没有 yum install / apt install 能力的。&lt;/p&gt;

&lt;p&gt;这时候，rvm install 默认指向调用 yum install / apt install【各种依赖】(libffi-dev openssl-dev)&lt;/p&gt;

&lt;p&gt;这会给人造成很大的困扰，有没有人有解决办法？在线等&lt;/p&gt;

&lt;p&gt;请允许 me 把老人们艾特出来
&lt;a href="/jasl" class="user-mention" title="@jasl"&gt;&lt;i&gt;@&lt;/i&gt;jasl&lt;/a&gt; &lt;a href="/Rei" class="user-mention" title="@Rei"&gt;&lt;i&gt;@&lt;/i&gt;Rei&lt;/a&gt; &lt;a href="/huacnlee" class="user-mention" title="@huacnlee"&gt;&lt;i&gt;@&lt;/i&gt;huacnlee&lt;/a&gt; &lt;/p&gt;</description>
      <author>jakit</author>
      <pubDate>Thu, 21 Feb 2019 14:25:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/38132</link>
      <guid>https://ruby-china.org/topics/38132</guid>
    </item>
    <item>
      <title>谈谈我对 Python 的看法</title>
      <description>&lt;p&gt;原文：
&lt;a href="https://zhuanlan.zhihu.com/p/36210899" rel="nofollow" target="_blank"&gt;https://zhuanlan.zhihu.com/p/36210899&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="引言"&gt;引言&lt;/h2&gt;
&lt;p&gt;首先，我在 14 年开始接触 Py，当时还在学校学习数据结构和算法，它是我最好的伙伴，因为我当时买了一本 Py 宝典，我就算上课没听，我看书上的 sample 代码就看懂了老师上课说的内容，然后转换成老师要的 C 程序代码，就算课没听，但是我知道怎么抽象数据结构。&lt;/p&gt;

&lt;p&gt;但是，我最近特别讨厌他，因为我工作中用到它，因为我工作中每天都在写不等长的 占位符，我且把 tab 的长度的 space 数和 space (1 byte char) 长度的 space 混为一谈，我真不知道是谁发明这么变态的语言。正如有一天我去吃麻辣烫，我点的“咪咪辣”，然后见一妹子跟她闺蜜指着招牌上写的辣度——“变态辣”说：你别要变态辣，我跟你没完，你要是点变态辣你就是变态所以你怎么吃都不觉得辣。&lt;/p&gt;

&lt;p&gt;嗯，就这么变态，我也是这么 think (about Python) 的。
あー、すごく変態だ、俺もそう思った
Yes, it is so hentai, I think so.&lt;/p&gt;
&lt;h2 id="Python 的好处在哪里"&gt;Python 的好处在哪里&lt;/h2&gt;
&lt;p&gt;吾辈认为，Python 不亚于就是让你不需要学复杂的数据抽象，就算你没有系统设计能力（尤其没接触过编程刚学的大学生），初学者一般教学入门计算机的认知就是输入输出，然后他们作为初学就真的只需要会用几个变量、一些条件语句、一些基础数据结构（数组、字典）来完成任务或应用程序开发。&lt;/p&gt;

&lt;p&gt;你要是跟他们谈物件导向编程（OOP），他们是一脸懵逼的，而且，OOP 的思想是“世界的粒度就是对象，然后每个对象都是一个可复用可继承的数据结构，可派生甚至可有后天行为”，这些东西其实新手真的用不到或者对他们来说，他们不去实施稍微有规模的程序，应该说，他们也没有项目可做，尤其在学校的环境里，不可能给他们一个人去搞一个什么项目烧时间旷课来完成。&lt;/p&gt;

&lt;p&gt;所以 Python 对他们来说也是很好的，入门者需要的就是简单的工具，过程化逐步深入学习。而不是一下子来个 Java，泛型、类型擦除、反射都糊他们一脸。&lt;/p&gt;
&lt;h2 id="我为什么不喜欢它"&gt;我为什么不喜欢它&lt;/h2&gt;&lt;h3 id="你为什么要以缩进来作为代码块的基准"&gt;你为什么要以缩进来作为代码块的基准&lt;/h3&gt;
&lt;p&gt;自从我历经多门语言，修炼多门技术甚至自己对词法有了解后。至今我在商业项目上终于又拿 Python 来做项目的时候，我反应过来，是谁告诉你拿占位符形成的缩进来作为一个代码块的基准的？&lt;/p&gt;

&lt;p&gt;吾辈认为，虽然这个风格的语言，你不推广，自己用可以，但你别跑出来祸害大众让大众跟你一起这样呀。&lt;/p&gt;
&lt;h4 id="内嵌问题"&gt;内嵌问题&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if condition:
    if condition:
        if condition:
            if condition:
    // code
        if condition:
            // code
            // code
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            ... 很长一段
            if condition:
                ... 很长一段
                ... 很长一段
                ... 很长一段
                ... 很长一段
        if condition:
    // 啊咧？这是哪一个 if 的子块里面呀？
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="匿名函数问题"&gt;匿名函数问题&lt;/h4&gt;
&lt;p&gt;我不得不吐槽 Python 不能创建正常的匿名函数，Lambda 只能短写：
lambda x: //code&lt;/p&gt;

&lt;p&gt;对于这个问题，Guido 说暂时没办法解决，因为缩进已经限制了语法的结构，如果 lambda 这么做，换行看起来怪怪的，而且如果加上的话 Python 解析器语法解析也不方便，他说如果有黑客能做到的话也欢迎建议。
（然而我看他是自己给自己挖了坑，自己跳进去之后发现早知道不设计缩进语法，现在好了，还跟大家说，有哪位黑客能解决告诉他吧）&lt;/p&gt;
&lt;h3 id="所谓的 Zen of Python"&gt;所谓的 Zen of Python&lt;/h3&gt;
&lt;p&gt;我彻底无法理解 Python 的“禅”：&lt;/p&gt;

&lt;p&gt;首先，我写代码的时候开了 pylint，然后，我有一行代码这样的：  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def method(param={}):
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时候 Pylint 给我警告，告诉我 {} 作为代码风格中间需要有个空格，好，我改成这样的：  &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def method(param={ }):
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时候 Pylint 给我警告，告诉我 { } 作为参数不能有空格&lt;/p&gt;

&lt;p&gt;请问，你想让我怎样？反正怎么写里外不是人。&lt;/p&gt;

&lt;p&gt;还有一堆我真不想说，比如每个类、方法都要我去写 doc string，否则红点点（警告信息）跟你没完。&lt;/p&gt;

&lt;p&gt;而且还有类跟类定义之间换行两行&lt;/p&gt;

&lt;p&gt;包空间中方法与方法之间换行两行&lt;/p&gt;

&lt;p&gt;噢，这些强迫症，就是 Python 之禅！&lt;/p&gt;

&lt;p&gt;我后来换成了 flake8，终于强迫症少了一些，但是我还是没法容忍：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_data = ["Name 1", "Name 2" ...]
true_names = [ ... ]
if condition:
    if condition:
        if condition:
            my_data = [v for v in my_data if true_names] # 警告
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;警告行会有提示：代码长度超过 80 charactors，噢呀，我忘了空格占位符缩进也算在 charactors 里面呀，这样的话，如果缩进到 6 层，是不是根本没法写语句了。（示例只是 if，但是有可能是类定义完了里面有方法，方法里面有 while 还有 if 的常见案例，并不算过分）&lt;/p&gt;
&lt;h4 id="写作很痛苦"&gt;写作很痛苦&lt;/h4&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def method(user_name, id_type, address, local_ip, host_name)
# Too long
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样写会太长而告警，换行了一下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def method(user_name,
    id_type,
    address,
    local_ip,
    host_name)
# Warning
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样还是告警，提示是换行的话，第二个参数要跟第一个参数的首字母对齐，得这么写：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def method(user_name,
           id_type,
           address,
           local_ip,
           host_name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;警告终于消失，但是，我知道我空了几个空格吗？不知道，有时候我真的得祭出 Python 最佳编程实践专用神器—— &lt;strong&gt;游标卡尺&lt;/strong&gt; 来量一下我需要空几个格，然后下一行别急着继续空格，最好把上面的空格复制粘贴到下面，或者最好是把第三行开始删掉空格回到上一行右边，然后回车，编辑器、IDE 自动换行，然后应该会自动 对齐到上一行开始。&lt;/p&gt;

&lt;p&gt;另外，&lt;strong&gt;Python 不支持 switch 语句&lt;/strong&gt;，很多场景没办法，只能多写几个 if，然后，如果具体值在一个集合里面，你可以用 dict 存一些值，然后 if in，但是，如果具体 case 不在一个集合里面，而是别的场合，那么你只能这么写：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if condition:

if condition:

if condition:

&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Python 不尊重高级开发者"&gt;Python 不尊重高级开发者&lt;/h2&gt;&lt;h3 id="继承没有 protected"&gt;继承没有 protected&lt;/h3&gt;
&lt;p&gt;C++ 的继承方式多种，是为了能在没有运行时、虚拟机的环境下依然能组合出多元化的对象继承结构（数据复用结构）。&lt;/p&gt;

&lt;p&gt;但是 Python 刚好相反，它让你要么什么都暴露，要么什么都隐藏，不要跟我谈 &lt;strong&gt;getattr&lt;/strong&gt; 和 &lt;strong&gt;setattr&lt;/strong&gt; 之类的元类特性，你觉得我为了 protected 我每次用都做这些好玩吗？&lt;/p&gt;
&lt;h3 id="使用已经公认差评的多重继承"&gt;使用已经公认差评的多重继承&lt;/h3&gt;
&lt;p&gt;多重继承本身就是个 deprecated 的做法，它会有钻石继承的问题，而且 Python 绝大多数书上都让新手去绕开这个坑，而不是语言级别去解决这个问题。就是语言不去解决问题而是把问题交给用户自行解决。&lt;/p&gt;
&lt;h3 id="还是刚才说的 lambda 问题"&gt;还是刚才说的 lambda 问题&lt;/h3&gt;
&lt;p&gt;Java 支持匿名类，C++ 既支持匿名函数也支持匿名类。&lt;/p&gt;

&lt;p&gt;就连我黑了上万遍的 PHP 都支持匿名函数（closure）和匿名类。&lt;/p&gt;

&lt;p&gt;但是，我还是包容的，因为 Python 对象允许后天行为的学习（为实例增加方法和属性）。但是写起来不成体统也不直观。lambda 发明就变成残废，你以为每个人都是数学家吗写个短公式不能换行做递归计算？递归？我记得 Guido 在讨论递归的时候是听厌恶的，他说他的 Python 是杜绝递归，不做尾递归优化，虽然网上有人提出 tail_call_optimized 修饰器的解决方法。&lt;/p&gt;

&lt;p&gt;无论怎么说，网友的想法是好的，用户能去这么容忍 Py 不去怎么样而自行解决问题，说明用户都是好心人。&lt;/p&gt;
&lt;h2 id="我要开始怼喽"&gt;我要开始怼喽&lt;/h2&gt;
&lt;p&gt;Guido van Rossum 估计是一个患有天才病（阿斯伯格综合征）的病人。&lt;/p&gt;

&lt;p&gt;这样的人人际交往困难。患者有与人交往的强烈意愿，却缺乏相应的技巧，所采取的交往方式刻板、生硬、程式化，更无法理解表情、眼色、肢体动作等非语言表达的信息。所以患者往往不受欢迎，也不能灵活地应对场景变化，难以融入群体，建立并维持良好的人际关系。&lt;/p&gt;

&lt;p&gt;去反观一下 Zen of Python，去看看 pep8，无处不体现这些特征。&lt;/p&gt;
&lt;h2 id="The Zend of Python"&gt;The Zend of Python&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Python 自以为自己用着很优雅的，自认为优美，实际上在强迫用户去把代码辛苦地浪费时间格式化来显得很标致。&lt;/li&gt;
&lt;li&gt;Python 自以为自己用着很明了的表达，实际上逼迫着用户有且只能用有限的表达方式和实现来完成任务。&lt;/li&gt;
&lt;li&gt;Python 自以为的简洁去面对 Java 的复杂 PHP / Perl 的杂乱，实际上实现真正能模拟接近复杂业务的时候 if if if if 都不如 - Java 一个 reflection / annotation 来得紧要，不如比 PHP / Perl 的 $obj-&amp;gt;{$requestmethod} 来的及时。&lt;/li&gt;
&lt;li&gt;Python 自认为的扁平不如 JS Promise / JxJava / Ruby Fiber 也有而且还可以带上长的、真正能发挥作用的匿名函数的非嵌套。&lt;/li&gt;
&lt;li&gt;Python 自认为的间隔是在按捺代码编写者的耐心。&lt;/li&gt;
&lt;li&gt;Python 自以为的可读性是牺牲编写容易性，甚至代码编写效率，影响开发者耐心，影响项目质量和进度。&lt;/li&gt;
&lt;li&gt;所谓的“规则至高无上”，是建立在里外不是人的变态苛刻编写制度之上。&lt;/li&gt;
&lt;li&gt;不要包容所有错误，为何你不像 TypeScript 静态化？做事有头有尾，没必要文人面前扮演武人。&lt;/li&gt;
&lt;li&gt;存在多种可能，不是尝试去猜的机会都没有，为了所谓的简化去用所谓唯一一种明显的万金油方案，然而，万金油程序往往是被有经验的开发者忌讳的。&lt;/li&gt;
&lt;li&gt;Python 之父不是神，是个听不懂人话只会 ABC 的智障（当初就是为了开发 ABC 顺便发明 Python 的）&lt;/li&gt;
&lt;li&gt;不假思索就动手还不如不做说明你没听说过热闹驱动开发，不过吾辈认为 Python 就是现在热闹驱动开发炒出来的火，都没验证这门语言是不是 SB 就已经开始火了&lt;/li&gt;
&lt;li&gt;无法向人描述你的方案是不是好方案不是谁说了算的，请不要过于自我强调&lt;/li&gt;
&lt;li&gt;命名空间是一种绝妙的理念，我们应当多加利用，嗯，是的，但是相信 Python 开发者会把它 import somepkg.vara 来用，尤其 Python 大名鼎鼎的框架 flask，是这么用的：from flask import Flask，但是 app = Flask(name) 之后，app 就形成了耦合，app.db app.logger 等，我的意思是如果外部 from app import app.db 之后，如果其它模块需要引用或者那些模块再反向引用回 app 会出现惊喜（比如 controller 引用 db db 引用 app app 引用 controller），这跟 C extern var 一样的，全局变量、外部变量这种东西，你觉得这是好的编程方式？你就不怕被 OOP style 那群人黑一番？&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这就是我在标题用【掩耳盗铃】的原因，我认为 Guido 一直在做这种事情，他一味地崇拜 ABC，把开发者当傻逼，他以为他从语法上去强制洁癖了代码就把代码变得圣洁。&lt;/p&gt;

&lt;p&gt;稍微熟悉点的开发者，甚至绕开 Python 这种机制去写出非常难调试的场景，比如利用 &lt;strong&gt;setattr&lt;/strong&gt; 和 &lt;strong&gt;getattr&lt;/strong&gt; 等来私藏很多“元”，就算外表调用光鲜，内部还不是一样晦涩，而且这样还非常难调。这样的类让人看起来“正直”，但是实际上是个犯罪系数很高的类，然而你从语法的简洁能看出来吗？根本看不出来。&lt;/p&gt;

&lt;p&gt;正如很多很多销售都穿得很正装，他是魔鬼就要你去被他套圈子套路。你上当了但是你还认为他是个好好先生，好男人。&lt;/p&gt;

&lt;p&gt;从限制语法来限制开发者的单一调用方式万金油式地解决问题就是个坑，你以为你是上帝一行代码解决所有问题，那你这一行代码得为了适应千万场景写多少天？&lt;/p&gt;

&lt;p&gt;搞得像服务员小姐，就是抿个嘴都得先拿个东西挡一下，然后再去擦拭，那勺子吃饭要讲究礼仪抬起哪只手，否则会被老板（语法检查器、解释器编译时）批评（警告）甚至是处分（Error）。&lt;/p&gt;
&lt;h2 id="工具是拿来用的，不是拿来看的"&gt;工具是拿来用的，不是拿来看的&lt;/h2&gt;
&lt;p&gt;你 tab space 那么多，给谁看，耽误了工期，你在字里行间的词汇中写出朵花来都没用。&lt;/p&gt;

&lt;p&gt;函数逻辑没写对，doc string 写得再详细，那也是欺骗。&lt;/p&gt;

&lt;p&gt;就算你 space tab 出了 全宇宙圣经级 pep8 代码，但是跑不起来，设计架构也不完整不成熟，实现效率低出品慢。那又有何用？&lt;/p&gt;

&lt;p&gt;不过我倒是悟出了一个真相，一个道理：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python 是写来装逼的（外观式编程）&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;相信 Python 在礼仪程序（Python 写的不是用来运行而是拿来作为礼物送人给别人看）讨好上司看自己写的代码多么礼仪还是很有价值的。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;第一个观点：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;然而我并不需要这种写了半天都没格式化好还有浪费时间在因为不提倡 if while 嵌套不能多行匿名函数我得绕各种弯子解决问题，浪费时间在代码风格上的语言。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;第二个观点：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;我需要的是，我写得舒服，看着清晰、正确，作为 adult 就应该自觉去格式化代码而不是被代码格式化暴力与强奸，应该是我写代码不是代码写我。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;有时候为了写出符合 pep8 风格又要达到算法优化级又要完成任务，那简直是多烧脑，不如去写 Haskell Ocaml，但是王垠在《我为什么不再做 PL 人》是这么评价的：&lt;/p&gt;

&lt;p&gt;第一段&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;有一些 PL 人喜欢推广他们认为高大上的语言，比如 Haskell，OCaml，Scala 等。这些语言在 PL 学术界很受尊重，所以他们以为这些语言能够奇迹般的解决实际的问题，然而事实却不是这样的。事实是，这些学术界出来的语言，其实缺乏处理现实问题的机制。为了能够在学术上证明程序的所谓“正确性”，而且由于类型系统本身的局限性，这些语言往往被设计得过于简单，具有过度的约束性，以至于表达能力欠缺。&lt;/p&gt;

&lt;p&gt;最后，你发现用这些语言来写代码，总是这也不能做，那也不能做，因为你要是那么做了，编译器就无法发现“类型错误”。到最后你发现，这些语言的约束，其实是无需有的。如果放宽这些约束，其实可以更优雅，更简单的对问题进行建模。对正确性的过分关注，其实导致了 PL 人选择蹩脚的语言，写出绕着弯子，难以理解的代码。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;第二段&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这种天才病的危害在于，它蒙蔽了这些人的眼睛。他们不再能设计出让“普通人”可以容易使用的产品。如果你不会用，他们就会嘲笑你笨，而其实呢，是因为他们的设计不好。他们喜欢用含混晦涩的方式（所谓“函数式”）的写法来构造代码，让其它人阅读和修改都极其困难，……&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr&gt;

&lt;p&gt;关于 lambda 的讨论，我想引出来的是一门语言，要么提供匿名函数，要么提供匿名类：&lt;/p&gt;

&lt;p&gt;C++&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;std::function func = [](type param) {
    // code
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用过 cocos2d-x 的人都知道绑定 event 最常用的方法就是它&lt;/p&gt;

&lt;p&gt;JavaScript&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyIterable { this.arr = [] }
MyIterable.prototype = Object.create(Object.prototype);
MyIterable.prototype.constructor = MyIterable;
MyIterable.prototype.iterWith(func) {
    this.arr.forEach(function(item) {
        func(item);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然，这些东西放到抽象类作为等到子类去实现也是可以的：&lt;/p&gt;

&lt;p&gt;PHP&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class MyIterable {
    $arr = [];
    public function iterWith() {
        foreach($this-&amp;gt;arr as $value) {
            $this-&amp;gt;iterWithImpl($this-&amp;gt;arr);
        }
    }
    abstract public function iterWithImpl($item);
}

$my_iter = new MyIterable {
    public function iterWithImpl($item)
    {
        echo $item;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然 PHP 也可以用 closure 匿名函数解决：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyIterable {
    $arr = [];
    public function iterWith($callback) {
        foreach($this-&amp;gt;arr as $value) {
            $callback($value);
        }
    }
}

$my_iter = new MyIterable {
    public function iterWithImpl($item)
    {
        echo $item;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上说明 PHP 提供两种方案。&lt;/p&gt;

&lt;p&gt;Java 的例子，跟 PHP 基本差不多，而且 Java 还可以用 Lambda 来便捷地创建匿名类（以下摘自安卓 button 监听）：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void myBtnClick() {
       btn.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Toast.makeText(getApplicationContext(),"这是弹窗",Toast.LENGTH_SHORT).show();
           }
       });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What about Python?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python 既没有匿名类，lambda 也是个残废&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这样的语言，你说写起来能不绕？写起来绕就算了，但是宗教教条一样的语法限定又怎么说，那就完成一件事不仅仅要注意它的教条规范，还得去绕着弯来做事，这是多么的困难。&lt;/p&gt;

&lt;p&gt;Python 教条主义符合以下特征：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 为了能够在证明他的程序代码能保证的所谓“Zen 的简洁性”&lt;/li&gt;
&lt;li&gt;这些语句往往被设计得过于简单，具有过度的约束性，以至于表达能力欠缺&lt;/li&gt;
&lt;li&gt;你发现用这些语言来写代码，总是这也不能做，那也不能做，因为你要是那么做了，pep8 warning 和 Python 解释器跟你没完&lt;/li&gt;
&lt;li&gt;到最后你发现，这些语言的约束，其实是无需有的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="/rocLv" class="user-mention" title="@rocLv"&gt;&lt;i&gt;@&lt;/i&gt;rocLv&lt;/a&gt; 的回复跟让我可笑，同时也正好符合&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;如果你不会用，他们就会嘲笑你笨，而其实呢，是因为他们的设计不好。他们喜欢用含混晦涩的方式（所谓“函数式”）的写法来构造代码，让其它人阅读和修改都极其困难&lt;/li&gt;
&lt;li&gt;他们不再能设计出让“普通人”可以容易使用的产品&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>jakit</author>
      <pubDate>Sat, 28 Apr 2018 10:58:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/36087</link>
      <guid>https://ruby-china.org/topics/36087</guid>
    </item>
    <item>
      <title>谈谈我对 Ruby 的看法</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2017/49b6a937-d623-41ee-a1a8-59bb72c88bec.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="引言"&gt;引言&lt;/h2&gt;
&lt;p&gt;我上司给我发一篇 java sonar 啥的文章，他觉得很神奇，我就告诉我上司，2013 年左右 王垠 写了 RubySonar 和 PySonar，我还给上司发了 Rubocop。&lt;/p&gt;

&lt;p&gt;他的第一反应是：卧槽这什么鬼玩意（一脸排斥），我跟他说，我的 amber-kit 是借助它辅助编码的。&lt;/p&gt;

&lt;p&gt;上司对 Ruby 真的比较反感，他说武汉根本招不到人，是根本上的，他跟我说他朋友的公司前几年就是用 Ruby，后来全用别的语言重构了。&lt;/p&gt;

&lt;p&gt;他有一次问我：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;为什么你不是用 Go / C++ 来写 amber-kit，先不讨论别的，关键是你这东西没办法招人啊。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;由于公司一直用 PHP，其实我对 PHP 真的很反感，不是一般的反感，简直是逆天弑神的反感到炸。&lt;/p&gt;
&lt;h2 id="Ruby 是否为一个好工具"&gt;Ruby 是否为一个好工具&lt;/h2&gt;
&lt;p&gt;我认为是的，但只是我自己&lt;/p&gt;
&lt;h2 id="Ruby 的好处之复用思想"&gt;Ruby 的好处之复用思想&lt;/h2&gt;
&lt;p&gt;不需要考虑太多复杂的 Interface、Generic、template 等复杂的东西，用 mixin 就可以解决。&lt;/p&gt;
&lt;h3 id="Interface、Generic、template、mixin"&gt;Interface、Generic、template、mixin&lt;/h3&gt;
&lt;p&gt;实现的目的，不过就是暴露一个接口，让类与类之间更好的契合在一起，好比古代木匠的卯和榫。&lt;/p&gt;
&lt;h3 id="Interface"&gt;Interface&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;接口&lt;/strong&gt;的方式是传统面向对象思想的接口（interface）与实现（implement）方式对接两个对象。&lt;/p&gt;
&lt;h3 id="template"&gt;template&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;模板&lt;/strong&gt;的方式是通过预编译宏一样的处理，就是模板类 typename T、class T 只要做了 T::method 或者 T t.method 的调用，在模板委托目标类一定要实现。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
void method(T t) {
    t.method();
}

class MyClass {
    void method() {}
}

MyClass mc;
method(mc); // 调用 mc.method

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其实这是一种典型的【代理委托】设计模式，编译器会在【编译时】检查 mc 的类，也就是 MyClass，是否实现了 method 方法，如果你放个 int a 到 method(a) 来调用，会报错 int 没有方法 method。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;template 一般是 C++ 这种没有完整元信息的实现语言以预编译形式处理的，也就是说，跟宏接近，模板类不是类型，而是模板&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="Generic"&gt;Generic&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;泛型&lt;/strong&gt;的方式和模板相近，比模板强，区别在于，泛型跟普通类一样，也是类型。&lt;/p&gt;

&lt;p&gt;在 Java 编码的时候，你不能 new T，但是你能反射出当前运行时 T 的类再去 new。&lt;/p&gt;
&lt;h3 id="mixin"&gt;mixin&lt;/h3&gt;
&lt;p&gt;说了这么多废话，我要进入正题，开始卖萌了&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module Comparable
  def &amp;gt;(param)
    self.&amp;lt;=&amp;gt;(param) == 1
  end
  ...
end

class Size
  include Comparable
  attr_accesor :size

  def &amp;lt;=&amp;gt;(param)
    self.size - param.size
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;比起接口、模板、泛型，Ruby 可以更简单、直接的委托一个方法到模块，然后复用。&lt;/p&gt;
&lt;h3 id="mixin 是动态类型、动态注入的"&gt;mixin 是动态类型、动态注入的&lt;/h3&gt;
&lt;p&gt;由于是动态注入的，所以随处都能 include，还可以灵活的 extend，虽然 extend 出来的 single_class_method 的方式有点让人联想 JavaScript 的 bad practice 的 prototype clone style programming。但是 Ruby 并不建议你去主张搞那么多 SCM，而是提供这项功能，发挥其作用。这是真善美的！&lt;/p&gt;

&lt;p&gt;动态类型可以解决开发者不用担心编译时太多类型不匹配导致开发者心烦，你试着拿着玉米一粒粒抠掉就能明白你去一个个解决类型匹配问题其中的道理。&lt;/p&gt;

&lt;p&gt;Java 抽象做大了，类型不匹配的情况很多，而且超级恶心，很棘手。&lt;/p&gt;

&lt;p&gt;Ruby 是强类型的，找不到方法还是会抛出错误，虽然动态会带来错误的可能，但还是比较严谨的。开发者可以先解决问题，后修复 bug，这是自顶向下模型。如果你有强迫症（也不是什么强迫症了啦，只想要严格一点），辣么，每个对象都有 is_a?，提供给你筛选符合的类型并处理不符合的类型。&lt;/p&gt;
&lt;h2 id="Ruby 的好处之强类型动态"&gt;Ruby 的好处之强类型动态&lt;/h2&gt;
&lt;p&gt;Python 被很多人公认是很好的入手第一门语言，因为它在强类型动态的特点，让初学者不需要那么老成持重地声明类型、规范类型，但是懂得遵守类型。&lt;/p&gt;

&lt;p&gt;这让开发者不需要去必须把规范执行得很死板，但是又能遵守约定类型来开发，不至于像某些情况说“完全不顾类型的直接编写代码”。&lt;/p&gt;
&lt;h3 id="我要开挂一样的喷 PHP，谁都别拦我"&gt;我要开挂一样的喷 PHP，谁都别拦我&lt;/h3&gt;
&lt;p&gt;PHP 是世界上最“土得掉渣，还告诉爸妈，回家种田吧”级别的语言。&lt;/p&gt;
&lt;h4 id="喷点1. 几乎都是全局方法"&gt;喷点 1. 几乎都是全局方法&lt;/h4&gt;
&lt;p&gt;PHP 延续了 Perl 的任务式开发思想，把很多东西都不包到模块里面，直接全局方法调用。&lt;/p&gt;
&lt;h4 id="喷点2. 复合类型"&gt;喷点 2. 复合类型&lt;/h4&gt;
&lt;p&gt;PHP 世界的粒度是以 Scalar 作为基本单位的，每一个 PHP 变量（Scalar）都既是 int 也是 double 也是 string 也是 object，这跟 Perl 5 一毛一样（说人话）。&lt;/p&gt;

&lt;p&gt;大家可以用 Devel::Peek 看一下 Perl 每个 Scalar 内存结构就知道了。。。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Devel::Peek;
        $a = 42; $a = "hello";
        Dump $a;

# 输出
SV = PVIV(0xbc288) at 0xbe9a8
          REFCNT = 1
          FLAGS = (POK,pPOK)
          IV = 42
          PV = 0xb2048 "hello"\0
          CUR = 5
          LEN = 8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我来跟大家介绍一下，IV 实际上是 IntValue，PV 就是 PointerValue，其实还有很多，像 &lt;a href="/array" class="user-mention" title="@array"&gt;&lt;i&gt;@&lt;/i&gt;array&lt;/a&gt; 还会有 RV、ARRAY FILL MAX 等。具体自己看 perldoc&lt;/p&gt;

&lt;p&gt;以下引出 PHP 类型结构，跟 Perl 没啥区别&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct _zval_struct {
    /* Variable information */
    zvalue_value value;        /* value */
    unsigned char type;        /* active type */
    unsigned char is_ref;
    short refcount;
};

typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perl PHP 当你第一次赋一个 int 的时候，它在结构体的 int 部分指针 = 被赋值的 int，以此类推。。。&lt;/p&gt;

&lt;p&gt;这种复合类型好处是方便不了解编程的人能够方便在 a = 1; a .= "str"; 的时候隐式处理，不需要你 to_s toString() atoi()。&lt;/p&gt;

&lt;p&gt;然而，这样已经从设计的最开始就已经违背了类型系统的初衷，应该说，这样的语言的思想是朝着【无类型】设计的，所有的变量、标量都能连在一起运算运行，无需开发者关心。&lt;/p&gt;
&lt;h4 id="喷点3. 没有包管理（不提 composer 这种名不正言不顺的东西）"&gt;喷点 3. 没有包管理（不提 composer 这种名不正言不顺的东西）&lt;/h4&gt;
&lt;p&gt;PHP 天生几乎都是设计成 SAPI，用 C 扩展的，类似于 JSP 之于 Java 的方式，本来就是作为直接网页嵌入编写式语言，跟包管理更不太融洽，如果你来设计维护 JSP，会辣么无聊让本来作为模板语言嵌入的 DSL 增加包管理吗？显然复杂化了。&lt;/p&gt;

&lt;p&gt;所以 PHP 天生包管理就不强，include 的东西基本上都不是包，而是文件，然后命名空间真的有点脑残，\Namespace 这种前面要带个斜杠才能用全局的 Namespace，否则的话，你前面设定了自己的 NamespaceA 之后继续写代码会引用的是 NamespaceA\Package。
然后我有个 Laravel fans 说就把 \Namespace 看成是目录，我呵呵哒，你见过 java 会 .java.package 写吗？先天残疾不要把这种问题丢给开发者。&lt;/p&gt;

&lt;p&gt;就算有了 namespace，不等于 PHP 就有了包管理，还是有很长的路走的。&lt;/p&gt;
&lt;h4 id="喷点3. 杂七杂八的设计"&gt;喷点 3. 杂七杂八的设计&lt;/h4&gt;
&lt;p&gt;PHP 几乎没有 universal standard coding style，而且每个框架几乎都是独立维护的。像 snews 这种程序，是一个老外写的新闻 cms，一个打包好的 php 脚本就是程序全部了，各种奇葩的东西都有，不过早期也是这么设计的。&lt;/p&gt;
&lt;h4 id="喷点4. 天生是为 CGI 设计的"&gt;喷点 4. 天生是为 CGI 设计的&lt;/h4&gt;
&lt;p&gt;写过 PHP 扩展的人都知道，有 PHP_MINIT_FUNCTION PHP_RINIT_FUNCTION，尤其 PHP_RINIT_FUNCTION 这个东西，是当一个 REQUEST 请求初始化时运行的，说白了就是 CGI 拿到环境之后开始运行调用的。&lt;/p&gt;

&lt;p&gt;这根本就不是一门独立的编程语言，虽然它照样可以使用来进行 low level programming，但是 socket 编程会很有问题，队列操作的时候，如果一个 socket 已经关闭了，那么接下来调用查询状态会出现 FALSE 或者 NULL，但是无论哪种都拿不定，而且 PHP 根本没法判断这个 FD 是个 FD，因为 PHP 对于这种类型根本不是类型，一个比较底层的引用的聚合类型你叫我怎么判断。（这里理解有点难度，如果能读懂我的意思就更好了）&lt;/p&gt;

&lt;p&gt;所以才会出现 Swoole 和 Yaf，但是这样的话，PHP 受制约性也太大了，比 Lua 还差，Lua 好歹可以包装对象，虽然不是完整的面向对象，Lua 好歹也有 meta-table 元表，跟 JavaScript prototype 类似的实现。&lt;/p&gt;

&lt;p&gt;总之 PHP 就是&lt;strong&gt;垃圾中的战斗机&lt;/strong&gt;，根本不足挂齿，说自己是做 PHP 的都觉得脸红耳赤羞得没法下台了（没事，找个地方羞去，没人看的）……（此处省略一亿字）&lt;/p&gt;
&lt;h2 id="Ruby 其它的好处"&gt;Ruby 其它的好处&lt;/h2&gt;&lt;h2 id="运算符重载"&gt;运算符重载&lt;/h2&gt;
&lt;p&gt;这将允许你代码上能快速编码，不需要那么多 number.add().div()，更加灵活&lt;/p&gt;
&lt;h2 id="单例类"&gt;单例类&lt;/h2&gt;
&lt;p&gt;这将允许你进行对象的后天编程，让喜欢抽象的程序员留了一大片自由幻想的天空&lt;/p&gt;
&lt;h2 id="极易扩展"&gt;极易扩展&lt;/h2&gt;
&lt;p&gt;无论自己写模块，包装 gem，跟 C 交互，一切都是干净的、卫生的、便利的，因为它的思维粒度是基于 struct class 和 struct object。C++ 的开发者们把它当作 Lua 使用作为你的辅助工具也无可厚非。JRuby 和 Java 也有很棒的交互能力。&lt;/p&gt;
&lt;h2 id="约定"&gt;约定&lt;/h2&gt;
&lt;p&gt;约定是 Ruby 最核心的东西，它体现在 Rubyist 手写的每一句表达式、每一个控制语句，以及完成的每一种设计上，它不仅仅让你的编码写作变得相互认可（不强求绝对统一），模块、对象之间交互也变得宽松简约。&lt;/p&gt;

&lt;p&gt;另外，这些还是需要一个开发者有良好的编码素养才能达成的，但是也并不难。&lt;/p&gt;

&lt;p&gt;看着 Ruby 的开发者越来越受两边排挤，我也看不下去了，希望更多人支持它！&lt;/p&gt;

&lt;p&gt;知乎链接：&lt;a href="https://zhuanlan.zhihu.com/p/32428688" rel="nofollow" target="_blank"&gt;https://zhuanlan.zhihu.com/p/32428688&lt;/a&gt;&lt;/p&gt;</description>
      <author>jakit</author>
      <pubDate>Thu, 28 Dec 2017 14:51:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/34785</link>
      <guid>https://ruby-china.org/topics/34785</guid>
    </item>
    <item>
      <title>交作业，安道翻译的《Ruby on Rails 教程》</title>
      <description>&lt;p&gt;之前买了 Agile Web Development with Rails 啃得好烧脑，花的时间会太长了，工作忙，划不来。&lt;/p&gt;

&lt;p&gt;本人目前已经有别的领域多了去了的同样的工具使用经验，只是借此参考 The Ruby Way for Web。&lt;/p&gt;

&lt;p&gt;实际能不能用上还真不好说（自己都能 DIY 的东西，怎么说呢，不妨学习了解一下，看看人家怎么设计怎么实现的），用不上就当作藏书吧 &lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt; 。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2017/988eebe4-ee50-4a59-837e-cf80c2264d6c.jpg!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;衷心感谢 &lt;a href="/andor_chen" class="user-mention" title="@andor_chen"&gt;&lt;i&gt;@&lt;/i&gt;andor_chen&lt;/a&gt; 的翻译工作，终于可以减少我的脑力去进行阅读了，谢谢 &lt;img title=":smiley:" alt="😃" src="https://twemoji.ruby-china.com/2/svg/1f603.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>jakit</author>
      <pubDate>Wed, 01 Nov 2017 14:48:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/34484</link>
      <guid>https://ruby-china.org/topics/34484</guid>
    </item>
    <item>
      <title>TextMate 是不是淘汰了？</title>
      <description>&lt;p&gt;我发现 Textmate 更新到 2.0rc7，但是下载的却是 rc4，感觉 Textmate 比 ST 某些地方直观一些，比如 git 的使用，其它吧，代码提示、自动补全我感觉 Textmate 用 ESC 一个个试没有 ST 直接弹出一个列表那样直观。&lt;/p&gt;</description>
      <author>jakit</author>
      <pubDate>Tue, 27 Jun 2017 14:50:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/33322</link>
      <guid>https://ruby-china.org/topics/33322</guid>
    </item>
  </channel>
</rss>
