2014年/11月/25日

首页回退

在公司的一次分享

关于编程冰山,我可能只在某个角落里瞎玩玩而已,我始终在试图寻找编程的本质,如爱因斯坦的质问:我想要知道上帝是如何创造世界的,其他就不重要了。哪天能够顿悟呢?越深入越白痴。如果你也关注计算机的历史 程序的本质结构,可以随便看看.

一、从Intellij IDEA开始

在捷克,一个叫Sergey Dmitriev的人在2000年的时候创立一个软件公司叫JetBrains。这个公司生产了一款Java IDE叫IDEA,Sergey Dmitriev为什么要开发这个软件呢?因为他认为写java代码真TM累,或者写程序也真TM累,所以他要一个智能的IDE。他对程序的理解在如下这篇文章里

LOP

中文翻译版LOP

1. 我们的编程还是太过于原始程序员还是太累解空间和问题空间不好匹配方法循环条件最原始的元素
2. general-purpose语言需要我们把高层的领域概念翻译为低层的编程语言特性在最终的程序中很多高度概括的视角蓝图都丢失了
3. general-purpose语言不能搞定所有问题任何复杂的系统都会有一个丑陋的lisp解析器更不可能有通用dsl
4. 程序为什么非得是文本行不能是其他结构吗不能是图形吗不能直接编辑tree吗于是JetBrains开发了MPS

JetBrains Product

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)

数据类型:

具体:不表达任何封装,比如cstruct,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")

六、程序员眼中的物理学

  1. 有丑陋的方程吗? 方程

  2. 关于维度(解释数据结构)

  3. 奥卡姆剃刀原则,让事情保持简单,自然界选择最短路径

  4. 发现和发明

七、相关书籍

  1. 计算机程序构造与解释
  2. Concepts, Techniques, and Models of Computer Programming
  3. 冒号课堂
  4. 逻辑的引擎
  5. 哥德尔,巴赫,埃舍尔
  6. 超越时空