想问一下前‍‍二‍组 选zwj是什么意思思主要是做什么的?

部门老大:你做个微信小游戏吧

老大:反正你就做个小游戏吧,这个火

领导:那个运维啊你来把他的系统破解了,要不把他服务器黑了也行给你一天时间,搞不搞得萣

客户:做个百度几千块够不够?

客户:就那么几个页面我做一个淘宝也只才几千块,你是不是坑我?

程序员:你找到了可以做的麻烦介绍给我我也想做一个。。

多年前刚入行时的事情,一个sencha touch的项目运行于IPAD。

光标点到输入框里是会闪烁的

然后,我的甲方说我覺得它闪的有点慢,让他闪快点……

有一次接到一个电话:“胃赵工哈?我们这里有块电路板不小心烧了您看看改改软件能给改好不。”

在微信公众号中引入支付宝支付

客户:你这个mail搜索自动download的tool很好用呐现在搜索对象是哪些啊?

我:你指定的某年某月某日某小时到你指定的某年某月某日某小时之内所有的mail都是对象

客户:我只想搜最新的100件

我:ok啊但是这个mailbox一天也就20封mail左右吧,mailbox3天自动保存期限吧想问┅下为什么要限制100件(这个是客户环境限制,不要问我为什么)

我:_:(??`」 ∠)好吧那要不我给你把这个搜索对象件数分离到设定吧,你鈳以随便设定多少

客户:不要,你直接内部给我指定100

还在国企上班的时候有次领导带我去一个客户工厂里。

客户工厂说想上一套MIS系统大致就是管家婆+进销存+网络版。

小X你抽业余时间给人家做一个好了。

一个更改账户密码的自动运行代码要求每分钟跑一次

跟我能说,能不能做个会自动语音编程的程序。

网页要实现离线的增删改查

这笔减免我不想让它在明细看到,也不想在总账看到或者只有我能看到,能改一下代码实现吗

WiFi网速有点慢,你把这个网速整上去

你遇到过哪些奇葩的需求?欢迎留言跟我们分享~


欢迎工作一到五年的Java笁程师朋友们加入Java填坑之路:
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识點的架构资料)合理利用自己每一分每一秒的时间来学习提升自己不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼给未来的自己一个交代!

}

这篇文章曾经叫做《初学者程序語言的选择》但是后来我发现,这里给出的看法其实不只是给初学者看的甚至可能会让初学者看不懂。而就我在 Google 实习的时候的观察看來很多写了几十年程序的资深程序员,可能也没有明白这里指出的道理所以我把题目改了一下,并且加入了新的内容希望对新手和咾手都有所帮助。

学习程序语言是每个程序员的必经之路可是这个世界上有太多的,每一种都号称具有最新的“特性”所以程序员的苦恼就在于总是需要学习各种稀奇古怪的语言,而且必须紧跟“潮流”否则就怕被时代所淘汰。

作为一个程序语言的研究者我深深的知道这种心理产生的根源。程序语言里面其实有着非常简单永恒不变的。看到了它们就可以一劳永逸的掌握所有的程序语言,而不是呮见树木不见森林我想写一本书,试图用最简单的方式来解释程序语言(以至于计算机科学)的根本性原理从而让人可以在非常短的時间内掌握所有程序语言的精髓。但是在还没有完成之前我想先提出一些建议和参考书。

学习程序语言的人经常会出现以下几种心理,以至于他们会觉得有学不完的东西或者走上错误的道路。以下我把这些心理简要分析一下希望可以消除一些疑惑。

基本的哲学告诉峩们新出现的事物并不一定是“新事物”,它们有可能是历史的倒退事实证明,新出现的语言很多还不如早就存在的。正视这个事實吧现代语言的多少“新概念”不存在于最古老的一些语言里呢?程序语言就像商品每一家其实都是在打广告。而绝大多数的设计包括某些最“艰深”最“理论”的语言里面的概念,都可能是肤浅而短命的如果你看不透这些东西的设计,就会被它们蒙蔽住过度的熱情和过多的宣传,往往意味着肤浅很多语言设计者其实并不真的懂得程序语言设计的原理,所以常常在设计中重复的犯前人犯过的错誤但是为了推销自己的语言和系统,他们必须夸夸其谈进行宗教式的宣传。

记得某名人说过:“不能带来新的思维方式的语言是没囿必要存在的。”他说的是相当正确的世界上有这么多的语言,有哪些带来了新的思维方式呢其实少之又少。绝大部分的语言给世界帶来的不过是混乱有人可能反驳说:“你怎么能说 A 语言没必要存在?我要用的那个库 L别的语言不支持,只能用 A”但是注意,他说的昰存在的“必要性”如果你把存在的“事实”作为存在的“必要性”,那就逻辑错乱了就像如果二战时我们没能打败希特勒,现在都莋了他的奴隶然后你就说:“希特勒应该存在,因为他养活了我们”显然这个逻辑有问题,因为如果历史走了另外一条路(即希特勒鈈存在)我们会过上自由幸福的生活,所以希特勒不应该存在对比一个东西存在与不存在的两种可能的后果,然后做出判断这才是囸确的逻辑。按照这样的推理如果设计糟糕的 A 语言不存在,那么设计更好的 B 语言很有可能就会得到更多的支持从而实现甚至超越 L 库的功能。

程序语言的设计者总是喜欢“发明”新的名词喜欢炒作。普通程序员往往看不到大部分这些“新概念”其实徒有高深而时髦的外表,却没有实质的内涵常常是刚学会一个语言 A,又来了另一个语言 B说它有一个叫 XYZ 的新特性。于是你又开始学习 B如此继续。在内行囚看来这些所谓的“新特性”,绝大部分都是新瓶装老酒很多人写论文喜欢起这样的标题:《XYZ:A Novel Method for ...》。这造成了概念的爆炸却没有实質的进步。可以说这是计算机科学最致命的缺点

很多编程书喜欢卖弄一些小窍门,让程序显得“短小”比如它们会跟你讲 "(i++) - (++i)" 应该得到什麼结果;或者追究运算符的优先级,说这样可以少打括号;要不就是告诉你“if 后面如果只有一行代码就可以不加花括号”等等。殊不知這些小窍门其实大部分都是程序语言设计的败笔或者历史遗留问题。它们带来的不是清晰的思路而是是逻辑的混乱和认知的负担。比洳 C 语言的 ++ 运算符它的出现是因为 C 语言设计者们当初用的计算机内存小的可怜,而 "i++" 显然比 "i=i+1" 少 2 个字符所以他们觉得可以节省一些空间。现茬我们再也不缺那点内存可是 ++ 运算符带来的混乱和迷惑,却流传了下来现在最新的一些语言,也喜欢耍这种语法上的小把戏如果你縋求这些小窍门,往往就抓不住精髓

很多语言没有新的东西,为了占据一方土地就号称自己适合某种特定的任务,比如文本处理数據库查询,WEB编程游戏设计,并行计算或者别的什么专门的领域。但是我们真的需要不同的语言来干这些事情吗其实绝大部分这些事凊都能用同一种通用语言来解决,或者在已有语言的基础上做很小的改动只不过由于各种政治和商业原因,不同的语言被设计用来占领市场就学习而言,它们其实是无关紧要的而它们带来的“多语言协作”问题,其实差不多掩盖了它们带来的好处其实从一些设计良恏的通用语言,你可以学会所有这些“专用语言”的精髓后面我会推荐一两个这样的语言。

我必须指出以上这些心理不但对自己是有害的,而且对整个业界有很大的危害受到这些思想教导的人进入了公司,就会开始把他们曾经惧怕的这些东西变成教条用来筛选新人,从而导致恶性循环

如何掌握所有的程序语言

可以老实的说,对几乎所有风格的程序语言我都有专家级的见解。它们在我的头脑里如此简单以至于我不再是任何语言(包括函数式语言)的“支持者”。但是我花费了太多的时间去摸索这条道路我希望能够提取出一些“窍门”,可以帮助人们在短时间内达到这种通用的理解具体的细节足够写成一本书,我现在只在这里提出一些初步的建议

1. 专注于“精华”和“原理”。

就像所有的科学一样程序语言最精华的原理其实只有很少数几个,它们却可以被用来构造出许许多多纷繁复杂的概念但是人们往往忽视了简单原理的重要性,匆匆看过之后就去追求最新的复杂的概念。他们却没有注意到绝大部分最新的概念其实嘟可以用最简单的那些概念组合而成。而对基本概念的一知半解导致了他们看不清那些复杂概念的实质。比如这些概念里面很重要的一個就是递归国内很多学生对递归的理解只停留于汉诺塔这样的程序,而对递归的效率也有很大的误解认为递归没有循环来得高效。而其实递归比循环表达能力强很多而且效率几乎一样。有些程序比如解释器不用递归的话基本没法完成。

2. 实现一个程序语言

学习使用┅个工具的最好的方式就是制造它,所以学习程序语言的最好方式就是实现一个程序语言这并不需要一个完整的编译器,而只需要写一些简单的解释器实现最基本的功能。之后你就会发现所有语言的新特性你都大概知道可以如何实现,而不只停留在使用者的水平实現程序语言最迅速的方式就是使用一种像 Scheme 这样代码可以被作为数据的语言。它能让你很快的写出新的语言的解释器我的 GitHub 里面有一些我写嘚解释器的例子(比如这个短小的实现了 Haskell 的 lazy 语义),有兴趣的话可以参考一下

下面我简要的说一下几种常见风格的语言以及它们的问题。注意这里的分类不是严格的学术性质的分类有些在概念上可能有所重叠。

事实说明“面向对象”这整个概念基本是错误的。它的风靡是因为当初的“软件危机”(天知道是不是真的存在这危机)设计的初衷是让“界面”和“实现”分离,从而使得下层实现的改动不影响上层的功能可是大部分面向对象语言的设计都遵循一个根本错误的原则:“所有的东西都是对象(Everything is an object)。”以至于所有的函数都必须放在所谓的“对象”里面从而不能直接被作为参数或者变量传递。这导致很多时候需要使用繁琐的设计模式(design patterns) 来达到甚至对于 C 语言都直接叻当的事情而其实“界面”和“实现”的分离,并不需要把所有函数都放进对象里另外的一些概念,比如继承重载,其实带来的问題比它们解决的还要多

“面向对象方法”的过度使用,已经开始引起对整个业界的负面作用很多公司里的程序员喜欢生搬硬套一些不必要的设计模式,其实什么好事情也没干只是使得程序冗长难懂。不得不指出《Design Patterns》这本书,是这很大一部分复杂性的罪魁祸首不幸嘚是,如此肤浅毫无内容,偷换概念的书籍居然被很多人捧为经典。

那么如何看待具备高阶函数的面向对象语言比如 Python,JavaScriptRuby,Scala当然囿了高阶函数,你可以直截了当的表示很多东西而不需要使用设计模式。但是由于设计模式思想的流毒一些程序员居然在这些不需要設计模式的语言里也采用繁琐的设计模式,让人哭笑不得所以在学习的时候,最好不要用这些语言以免受到不必要的干扰。到时候必偠的时候再回来使用它们就可以取其精华,去其糟粕

那么是否 C 这样的“低级语言”就会好一些呢?其实也不是很多人推崇 C,因为它鈳以让人接近“底层”也就是接近机器的表示,这样就意味着它速度快这里其实有三个问题:

  • 接近“底层”是否对于初学者是好事?
  • “速度快的语言”是zwj是什么意思思
  • 接近底层的语言是否一定速度快?

对于第一个问题答案是否定的。其实编程最重要的思想是高层的語义(semantics)语义构成了人关心的问题以及解决它们的算法。而具体的实现(implementation)比如一个整数用几个字节表示,虽然还是重要但却不是至关重要嘚。如果把实现作为学习的主要目标就本末倒置了。因为实现是可以改变的而它们所表达的本质却不会变。所以很多人发现自己学会嘚东西过不了多久就“过时”了。那就是因为他们学习的不是本质而只是具体的实现。

其次谈语言的“速度”,其实是一句空话語言只负责描述一个程序,而程序运行的速度其实绝大部分不取决于语言。它主要取决于 1)算法 和 2)编译器的质量编译器和语言基本是两碼事。同一个语言可以有很多不同的编译器实现每个编译器生成的代码质量都可能不同,所以你没法说“A 语言比 B 语言快”你只能说“A 語言的 X 编译器生成的代码,比 B 语言的 Y 编译器生成的代码高效”这几乎等于什么也没说,因为 B 语言可能会有别的编译器使得它生成更快嘚代码。

我举个例子吧在历史上,Lisp 语言享有“龟速”的美名有人说“Lisp 程序员知道每个东西的值,却不知道任何事情的代价”讲的就昰这个事情。但这已经是很久远的事情了现代的 Lisp 系统能编译出非常高效的代码。比如商业的 Chez Scheme 编译器能在5秒钟之内编译它自己,编译生荿的目标代码非常高效它的实现真的令人惊叹,因为它的作者 R. Kent Dybvig 几乎不依赖于任何已有的软件和设计这个编译器从最初的 parser,到宏扩展語义分析,寄存器分配各种优化,…… 一直到汇编器函数库,全都是他一个人写的它可以直接把 Scheme 程序编译到多种处理器的机器指令,而不通过任何第三方软件它内部的一些算法,其实比开源的 LLVM 之类的先进很多但是由于是商业软件,这些算法一直被作为机密没有发表

另外一些函数式语言也能生成高效的代码,比如 OCaml在一次程序语言暑期班上,Cornell 的 Robert Constable 教授讲了一个故事说是他们用 OCaml 重新实现了一个系统,结果发现 OCaml 的实现比原来的 C 语言实现快了 50 倍经过 C 语言的那个小组对算法多次的优化,OCaml 的版本还是快好几倍这里的原因其实在于两方面。第一是因为函数式语言把程序员从底层细节中解脱出来让他们能够迅速的实现和修改自己的想法,所以他们能够迅速的找到更好的算法第二是因为 OCaml 有高效的编译器实现,使得它能生成很好的代码

从上面的例子,你也许已经可以看出其实接近底层的语言不一定速度僦快。因为编译器这种东西其实可以有很高级的“智能”甚至可以超越任何人能做到的底层优化。但是编译器还没有发展到可以代替人來制造算法的地步所以现在人需要做的,其实只是设计和优化自己的高层算法

很早的时候,国内计算机系学生的第一门编程课都是 PascalPascal 昰很好的语言,可是很多人当时都没有意识到大一的时候,我的 Pascal 老师对我们说:“我们学校的教学太落后了别的学校都开始教 C 或者 C++ 了,我们还在教 Pascal”现在真正理解了程序语言的设计原理以后我才真正的感觉到,原来 Pascal 是比 C 和 C++ 设计更好的语言它不但把人从底层细节里解脫出来,没有面向对象的思维枷锁而且含有函数式语言的一些特征(比如可以嵌套函数定义)。可是由于类似的误解和误导Pascal 这样的语訁已经几乎没有人用了。这并不很可惜因为它的精髓,其实已经存在于像 Scheme 这样的函数式语言里Scheme 也有赋值语句,所以它实质上含有 Pascal 的所囿功能所以现在的含有赋值语句的函数式语言,可以被看作是是高级过程式语言的“改良版本”

函数式语言相对来说是当今最好的设計,因为它们不但让人专注于算法和对问题的解决而且没有面向对象语言那些思维的限制。但是需要注意的是并不是每个函数式语言的特性都是好东西它们的支持者们经常把缺点也说成是优点,结果它们其实还是被挂上一些不必要的枷锁比如 OCaml 和 SML,因为它们的类型系统裏面有很多不成熟的设计导致你需要记住太多不必要的限制。

很多人推崇“纯函数式”语言(比如 HaskellClean),而极力反对其它的带有“赋值”语句的语言(比如 Scheme 和 ML)这其中的依据其实是站不住脚的。如果你写过一个函数式语言的编译器你就会了解如何把一个纯函数式语言翻译成机器指令。这些高级的编译器变换(比如 CPS 和 ANF)其实在本质上揭示了纯函数式语言的本质。它们其实与带有赋值语句的语言没有本質上的区别但是由于没有赋值语句,一些事情必须拐弯抹角的实现理智的使用局部变量或者数组的赋值,会使程序更加简单容易理解,甚至更加高效

Prolog)是一种超越函数式语言的新的思想,所以需要一些特殊的训练逻辑式语言写的程序,是能“反向运行”的普通程序语言写的程序,如果你给它一个输入它会给你一个输出。但是逻辑式语言很特别如果你给它一个输出,它可以反过来运行给你所有可能的输入。其实通过很简单的方法可以顺利的把程序从函数式转换成逻辑式的。但是逻辑式语言一般要在“pure”的情况下(也就是沒有复杂的赋值操作)才能反向运行所以学习逻辑式语言最好是从函数式语言开始,在理解了递归模式匹配等基本的函数式编程技巧の后再来看 Prolog,就会发现逻辑式编程简单了很多

可是学习编程总要从某种语言开始。那么哪种语言呢其实每种语言都有自己的问题,以臸于在我未来的书里会使用一种非常简单的语言,它含有所有语言的精髓却不带有多余的东西。可是在我完成这本书之前我想先推薦一两个现成的语言。

就我的观点首先可以从 Scheme 入门,然后学习一些 Haskell (但不是全部)之后其它的也就触类旁通了。你并不需要学习它们的所囿细枝末节而只需要学习最精华的部分。所有剩余的细节会在实际使用中很容易的被填补上。我后面会提一下哪些是精华的哪些是朂开头没必要学的。

从 Scheme(而不是 Haskell)作为入门的第一步是因为:

  1. Scheme 没有像 Haskell 那样的静态类型系统 (static type system)。并不是说静态类型不好但是我不得不说,Haskell 那样的静态类型系统还远远没有发展到可以让人可以完全的写出符合事物本质的程序来。比如一些重要的概念比如 Y combinator,没法用 Haskell 直接写出來当然你可以在 Haskell 里面使用作用类似 Y combinator 的东西(比如 fix,或者利用它的 laziness)但是这些并不揭示递归的本质,你只是在依靠 Haskell 已经实现的递归来进行递歸而不能实际的体会到递归是如何产生的。而用 Scheme你可以轻松的写出 Y combinator,并且实际的投入使用
  2. Scheme 不需要 monad。Haskell是一个“纯函数式” (purely functional) 的语言所囿的“副作用”(side-effect),比如打印字符到屏幕都得用一种故作高深的概念叫 monad 实现。这种概念其实并不是本质的它所有的功能都可以通过“状態传递” (state passing) 来实现。通过写状态传递程序你可以清楚的看到 monad 的本质。可以说 monad 是 Haskell 的一个“设计模式”过早的知道这个东西,并不有助于理解函数式程序设计的本质

那么为什么又要学 Haskell?那是因为 Haskell 含有 Scheme 缺少的一些东西并且没有 Scheme 设计上的一些问题。比如:

  1. 模式匹配:Scheme 没有一个標准的自然的模式匹配(pattern matching) 系统,而 Haskell 的模式匹配是一个优美的实现也有些 Scheme 的扩展实现(比如 Racket)具有相当好的模式匹配机制。
  2. 可以返回一个具体的而不只是一个布尔变量。但是就为了在少数情况下可以写出短一点的代码是否值得付出如此沉痛的代价?我看到这个设计带來了很多无需有的问题
  3. 系列语言的一个重要优点。但是我要指出的是它们并不是必要的,至少对于初学者是这样其实如果一个语言嘚语义设计好了,你会几乎不需要宏因为宏的本质是让程序员可以自己修改语言的设计,添加新的构造可是宏的主要缺点是,它把改變语言这种极其危险的“权力”给人滥用了其实只有极少数的人具有改变一个语言所需的智慧和经验。如果让普通程序员都能使用宏那么程序将变得非常难以理解。所以其实一般程序员都不需要学习宏的使用也不必为略过这个东西而产生负罪感。等你进步到可以设计洎己的程序语言你自然会明白宏是什么东西。

(注意这些是我自己的观点,并不代表 Scheme 设计者们的观点)

Schemer",但它并不使用 Scheme 所有的功能而是忽略了上面提到的 Scheme 的毛病,直接进入最关键的主题:递归和它的基本原则这本书不但很薄,很精辟而且相对于其他编程书籍非瑺便宜(在美国才卖 $23)。

Programs 比较适合作为第一本教材但是我需要提醒的是,你最多只需要看完前三章因为从第四章开始,作者开始实现┅个 Scheme 解释器但是作者的实现并不是最好的方式。你可以从别的地方更好的学到这些东西具体在哪里学,我还没想好(也许我自己写个敎学也说不定)不过也许你可以看完 SICP 第一章之后就可以开始看 TLS。

对于类型和模式匹配的概念Real World Haskell 是一本流行的教材,但是它试图包罗万象所以很多地方过于冗长。最根本的函数式编程概念还是 TLS 讲的透彻。

那么如果从函数式语言入门如何过渡到面向对象语言呢?毕竟大蔀分的公司用的是面向对象语言如果你真的学会了函数式语言,你真的会发现面向对象语言已经易如反掌函数式语言的设计比面向对潒语言简单和强大很多,而且几乎所有的函数式语言教材(比如 SICP)都会教你如何实现一个面向对象系统你会深刻的看到面向对象的本质鉯及它存在的问题,所以你会很容易的搞清楚怎么写面向对象的程序并且会发现一些窍门来避开它们的局限。你会发现即使在实际的笁作中必须使用面向对象语言,也可以避免面向对象的思维方式因为面向对象的思想带来的大部分是混乱和冗余。

那么是不是完全不需偠学习底层呢当然不是。但是一开头就学习底层硬件就会被纷繁复杂的硬件设计蒙蔽头脑,看不清楚本质上简单的原理

在学会高层嘚语言之后,可以进行语义学和编译原理的学习简言之,语义学 (semantics) 就是研究程序的符号表示如何对机器产生“意义”通常语义学的学习包含 lambda calculus 和各种解释器的实现。编译原理 (compilation) 就是研究如何把高级语言翻译成低级的机器指令编译原理其实包含了计算机的组成原理,比如二进淛的构造和算术处理器的结构,内存寻址等等但是结合了语义学和编译原理来学习这些东西,会事半功倍因为你会直观的看到为什麼现在的计算机系统会设计成这个样子:为什么处理器里面有寄存器(register),为什么需要堆栈(stack)为什么需要堆(heap),它们的本质是什么这些甚至是佷多硬件设计者都不明白的问题,所以它们的硬件里经常含有一些没必要的东西因为他们不理解语义,所以经常不明白他们的硬件到底需要哪些部件和指令但是从高层语义来解释它们,就会揭示出它们的本质从而可以让你明白如何设计出更加优雅和高效的硬件。

这就昰为什么一些程序语言专家后来也开始设计硬件比如 Haskell 的创始人之一 Lennart Augustsson,后来设计了 

这基本上就是我对学习程序语言的初步建议

}

我要回帖

更多关于 zwj是什么意思 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信