2014年/11月/25日
在公司的一次分享
关于编程冰山,我可能只在某个角落里瞎玩玩而已,我始终在试图寻找编程的本质,如爱因斯坦的质问:我想要知道上帝是如何创造世界的,其他就不重要了。哪天能够顿悟呢?越深入越白痴。如果你也关注计算机的历史 程序的本质结构,可以随便看看.
一、从Intellij IDEA开始
在捷克,一个叫Sergey Dmitriev的人在2000年的时候创立一个软件公司叫JetBrains。这个公司生产了一款Java IDE叫IDEA,Sergey Dmitriev为什么要开发这个软件呢?因为他认为写java代码真TM累,或者写程序也真TM累,所以他要一个智能的IDE。他对程序的理解在如下这篇文章里
1. 我们的编程还是太过于原始,程序员还是太累,解空间和问题空间不好匹配,类,方法,循环,条件,最原始的元素
2. general-purpose语言需要我们把高层的领域概念翻译为低层的编程语言特性,在最终的程序中,很多高度概括的视角、蓝图都丢失了
3. general-purpose语言不能搞定所有问题,任何复杂的系统都会有一个丑陋的lisp解析器,更不可能有通用dsl
4. 程序为什么非得是文本行,不能是其他结构吗?不能是图形吗?不能直接编辑tree吗?于是JetBrains开发了MPS
MPS帮助你实现自己的DSL,很多动态语言的元编程算一个代码自动生成语言级别的利器。
利用元编程可以去掉重复代码:
class Person < ActiveRecord::Base
end
domain = Person.new
domain.name = 'name'
domain.age = 28
domain.email = 'name@gmail.com'
domain.save
web编程:
get '/hi' do
"Hello World!"
end
如果要关注“元”这个字,差不多是事物最本质的东西,比如:
平面几何的5大公理:
1. 过相异两点,能作且只能作一直线(直线公理)。
2. 线段(有限直线)可以任意地延长。
3. 以任一点为圆心、任意长为半径,可作一圆(圆公理)。
4. 凡是直角都相等(角公理)。
5. 两直线被第三条直线所截,如果同侧两内角和小于两个直角, 则两直线作延长时在此侧会相交。
1. 光的三原色:RGB这三种颜色的组合,几乎形成所有的颜色
2. 程序的三种结构:顺序,分支和循环
3. 物理世界的四种力:万有引力,电磁力,强力和弱力
4. 数论中的质数:数论是纯粹数学的分支之一,主要研究整数的性质。而整数的基本元素是素数(也称质数),所以数论的本质是对素数性质的研究。数论被高斯誉为“数学中的皇冠”。
二、如何在IDEA中快速编写Java代码
这里是Oh My IDEA这个插件的演示,敲代码的重点是敲,那么我们如果能够更少碰鼠标,那便是极好的。以最少的移动获取最大的编辑能力,目前我见过的vim是个利器。但是 在IDEA里我其实不需要vim那么全的特性,不遵守vim的规则,只要能快速编辑java即可。如果敢兴趣可以关注我的一个oh my idea的项目,它模拟了部分vim用法但是编写java更迅速。
三、计算机机器的历史
算盘是什么原理?
我们的祖先把四则运算全部表达成了机械操作,你只要需要一个存储器,然后用一个机械的规则不断的修改存储器就可以完成计算了。那么数学还有必要研究吗?
我们从加减乘除到代数运算再到微积分,这些数学定理都是一种符号表示,那么是否可以给定一个规则,然后一个机械过程,自动推导出数学命题呢?
在不知道莱布尼兹的设想下,发现人类的逻辑是可以表示为代数运算
独立布尔,发展了概念文字,发现了编程语言的原型,用概念文字描述数学基础但是被罗素灭了
挑战集合论,发现对角线法则
认为数学是的真理是可以用机器进行机械推导的,但是这个天真的想法被哥德尔否定了
图灵想证明为什么数学是不能机械推到的,发现了图灵计算模型,同时邱奇通过拉姆达函数可定义性也发现了。
冯诺依曼放弃了研究逻辑,制造计算机,存储程序的革命
四、斐波拉契和快速排序
数列用图灵,修改内存
//0、1、1、2、3、5、8、13、21、……
var position = 10; //位置
var fib = []; //存储
fib[0] = 0;fib[1] = 1;
for(i=2; i<=position; i++) {
fib[i] = fib[i-2] + fib[i-1];
}
var result = fib[position]; //得到这个位置的Fibonacci数
声明式描述
//0、1、1、2、3、5、8、13、21、……
function fib(n){
return n<2 ? n: fib(n-1)+fib(n-2);
}
var result = fib(10);
逻辑式描述
//0、1、1、2、3、5、8、13、21、……
rule FebCalculate
when
f1 : Fact( s1 : seq, value != -1 ) //如果有一个事实的值不是-1
f2 : Fact( seq == (s1 + 1 ), value != -1 ) //如果后继事实值也不是-1
f3 : Fact( s3 : seq == (f2.seq + 1 ), value == -1 )//如果再后继的事实的值是-1
then
modify ( f3 ) { value = f1.value + f2.value }; //则进行计算,将两个事实的值求和复制给第三个事实的value属性
end
快速排序,图灵,修改内存
//[4,0,-1,8,9,10,2,11,3]
public int partition(int[] array, int left, int right) {
//假定第一个是基准
int point = left;
int compare = array[left];
//从第二个开始向后看,如果发现比第一个小就要移动指针同时做交换
for (int j = left + 1; j <= right; j++) {
if (array[j] < compare) {
point++;
swap(array, point, j);
}
}
//经过上述循环可能在其他地方找到了基准应该出现的位置,把第一个数交换到指针处
swap(array, point, left);
return point;
}
为什么要修改数据呢?
def quicksort a
(pivot = a.pop) ? quicksort(a.select{|i| i < pivot}) + [pivot] + quicksort(a.select{|i| i > pivot}) : []
end
五、关于编程语言的balabala
scheme
程序设计语言的设计不应该是特征的堆砌,而应消除那些需要依赖于多余特征的弱点和局限。Scheme语言证明,极少的表达式构造规则和不加限制的表达式复合方式可以构造出实用而高效的程序设计语言,
其灵活性足以支持今天的大部分主流编程模型。
Scheme是第一种被广泛使用的,采纳第一级逃逸过程(escape procedure)的程序设计语言,通过第一级逃逸过程可以合成所有已知的顺序控制结构。
数:c,c++,java 纠结在有符号,无符号,各种表示范围,精度问题 java的sb问题
Integer i = 100;
Integer j = 100;
System.out.println(i == j); //true
System.out.println(i == 100);
i = 200;
j = 200;
System.out.println(i == j); //false
System.out.println(i == 200);
ruby无精度自动提升了。 lua只用浮点表示数,Lua没有整型,并且也不需要。有个普遍的误解,使用浮点型会有算术错误,一些人害怕浮点型即使一个简单的“加”运算也会有奇奇怪怪的问题。但事实上,用一个double类型来表示一个integer,不存在任何边界问题(除非这个数大于1.0e14)
boolean 虽然就两个值,其实表达了整个机器的运转,程序语言中如何对待真假的处理很值得研究,强布尔的语言比如java,我们必须用工具StringUtils.isBlank(),StringUtils.isEmpty()
字符
字符串在paul graham眼中不应该存在,存在的应该是字符数组
空:
js就由undefined和null ruby,lua等用nil java的null更是让人诟病,与null程序中断
public ActionResult Index(int? id, int? md){
if (id.HasValue && md.HasValue){
User user=userService.GetUser(id.Value);
return View("Hello");
}
return new RedirectResult(AppConfig.BASE_URL);
}
结构:
c,c++,java严格以来于库,java方便一点把库放在了jdk里,数组是基本结构,其他抽象全部使用类。 ruby,在语言级别支持了range,hash js,关联数组 erlang,元祖,列表 lua的table,php的array
句法:
顺序,分支,循环组成了程序。
if else 是可以被消除的。
if(a >=5){
alert("你好");
}
可以写成:
a >= 5 && alert("你好");
var max = max_width || preferences.max_width || 500
多从分支也就是多个if else,所以也可以用连续表达式来写。
分支是可以另外写的
case n
when 0
puts 'You typed zero'
when 1, 9
puts 'n is a perfect square'
when 2
puts 'n is a prime number'
puts 'n is an even number'
when 3, 5, 7
puts 'n is a prime number'
when 4, 6, 8
puts 'n is an even number'
else
puts 'Only single-digit numbers are allowed'
end
result = case score
when 0..40 then "Fail"
when 41..60 then "Pass"
when 61..70 then "Pass with Merit"
when 71..100 then "Pass with Distinction"
else "Invalid Score"
end
def eval(tree, env) do
case tree do
{:number, n} -> n
{:add, l, r} -> eval(l, env) + eval(r, env)
{:mul, l, r} -> eval(l, env) * eval(r, env)
{:variable, id} -> Dict.get(env, id)
end
end
match ch with
| [] ->
(* make sure we read all *)
if timeout && is_process_running() then
loop ins
else begin
Buffer.add_string berr (IO.read_all (IO.input_channel perr));
Buffer.add_string bout (IO.read_all (IO.input_channel pout));
end
| s :: _ ->
let n = Unix.read s tmp 0 (String.length tmp) in
if s == iout && n > 0 then
ctx.com.print (String.sub tmp 0 n)
else
Buffer.add_substring (if s == iout then bout else berr) tmp 0 n;
loop (if n = 0 then List.filter ((!=) s) ins else ins)
循环是可以被递归取代的。
//循环
var loop = 100;
var i = loop;
do {
//do something
i--;
}while(i>0)
//递归
function foo(i) {
//do something
if(--i > 0) foo(i);
}
foo(loop)
//当然还可以这样写
(function foo(i){
//do something
if(--i >0) foo(i)
})(loop)
数据类型:
具体:不表达任何封装,比如c的struct,java的贫血
抽象:比如Queue,Stack
OO: 具备了继承和多台的抽象数据类型(ADT)
继承:继承接口和继承实现,单继承和多继承,多继承引发菱形问题,单继承又失去了灵活性,extjs的集成体系,java的集成体系,最后发展出了ruby的单继承+混入
多态:依赖于继承接口,但是鸭子类型更加灵活
require 'observer'
class PObservable
include Observable
end
class AObserver
def update(arg)
puts "AObserver 被通知了 " + arg
end
end
class BObserver
def update(arg)
puts "BObserver 被通知了 " + arg
end
end
observer_a = AObserver.new
observer_b = BObserver.new
obj = PObservable.new
obj.add_observer(observer_a)
obj.add_observer(observer_b)
obj.changed
obj.notify_observers("Test")
六、程序员眼中的物理学
-
有丑陋的方程吗?
-
关于维度(解释数据结构)
-
奥卡姆剃刀原则,让事情保持简单,自然界选择最短路径
-
发现和发明
七、相关书籍
- 计算机程序构造与解释
- Concepts, Techniques, and Models of Computer Programming
- 冒号课堂
- 逻辑的引擎
- 哥德尔,巴赫,埃舍尔
- 超越时空