需要lazy evaluation的一个例子

why functional programming matters里看来的例子,改成了Scheme版本。

占个位子。等SICP做到第四章,搞出LE,这个就可以解决了。

(define (within eps lst)
  (let ((a (car lst))
        (b (cadr lst)))
    (if (<= (abs (- a b)) eps)
        b
        (within eps (cdr lst)))))

(define (repeat f a)
  (cons a (repeat f (f a))))

(define (square-root guess eps n)
  (within esp (repeat
               (lambda (x) (/ (+ x (/ n x)) 2))
               guess)))

Gears of War


Gears of war这个游戏是n个月以前爱辉推荐给我的。当时我看总共7个多G吓了一跳,不过还是拖进了电驴。经历了几个月的下载,就在我快把这回事儿忘了的时候,下载完成了。。。

玩起来竟是欲罢不能。游戏可操作性极好,画面也非常有真实感。配乐更是地道,打起来非常紧张刺激。主角是个老兵而且无疑是个战斗英雄,但这个游戏不像英雄萨姆那样,可以让你一人单挑一万个怪物。主角的身体和敌人士兵一样脆弱,在高难度下,甚至比对方脆弱很多。所以如果不加思考的一味猛冲,你一定会死的很惨。身处硝烟弥漫的战场上,稍不留神就会失去性命。必须时刻观察敌我位置和距离,计算地形和各种障碍带来的影响,还要把敌我的武器装备考虑进去,才能选择合适的战术,一路杀敌前进。

老潘不敢自称高手,但已经打穿hardcore难度,并且在此难度中一次轻易击败总boss,颇有些心得。

wxPython wrappers

Dabo

PythonCard

Wax

SICP-2.16 solution

前面已经分析过了,之所以有不同的答案,是因为某个计算过程接受的参数之间具有内在的逻辑依赖关系,也就是说参数不是完全独立的。表现在前面的例子中,就是div-interval接受的参数实际上是x=r1*r2和y=r1+r2。但div-interval并不知道这一点(它也不应该知道这一点)。x和y是互相牵制的两个值,而不是可以单独参与计算的两个值。

sub-interval同样有这个问题。下面两个表达式是不一样的:

(sub-interval (make-interval 1 2) (make-interval 1 2))

(let ((A (make-interval 1 2)))

  (sub-interval (make-interval 1 2) (make-interval 1 2)))

第二个应该为[0, 0] 

如何解决这个问题?

思路:用过程表示数据?让传入参数自己知道自己是怎么构成的。

Python import到底干了些什么

http://effbot.org/zone/import-confusion.htm

虽然这里讲了一些,但是要想完全明白,就得理解Python module也是object:和所有的instance,class/type一样。另外还要明白,当一个Module被import时,其中的statement被执行。

关于虚函数,多重继承,Python中的super

继承和多重继承(http://en.wikipedia.org/wiki/Multiple_inheritance)是language features,是面向对象技术为了使程序向现实贴近的一个手段。不过在面向对象理论中多重继承也不是必须的,基本上所有可以用多重继承实现的,都可以通过单继承来work around。这句话更多来自于实践而不是严格的理论。

从继承的实现角度来说,当子类对象被初始化时,实际上有一个父类对象也被初始化并且组合到子类对象中。这种来自继承的组合和普通的组合的不同之处主要在于,我们是仅仅需要使用父类提供的功能,还是说也需要使用父类提供的接口。

有继承就有多态。C++为了实现多态引入了late/dynamic/runtime binding(Connecting a function call to a function body is called binding):编译时,编译器不知道通过一个基类引用调用的某函数,具体调用的到底是那段代码。所以传统的非OOP编译器的early/static binding机制就行不通了。C++中实现late binding的手段是虚函数。Python和Java中所有的函数/方法实际上都是虚的。所以说虚函数只是实现多态的一个(并不唯一的)技术手段。

具体的实现机制是,编译器为每一个包含虚函数的类(包括通过继承得来虚函数的类)都生成一段分配空间并初始化VTABLE(就是所谓的虚函数表)的代码。于是在运行的时候内存中就会有这样的VTABLE,它们包含了该类中所有虚函数的实现代码的地址。这是非常合乎逻辑的,因为同一个具体类的所有对象,其虚函数实现都是一样的,所以一个类只需要一个虚函数表。

接下来,每当编译器在源代码中看到new一个对象的时候,都会做一些小偷小摸的事:它会生成一些额外的代码,在对象中在分配空间给一个指针成员变量VPTR(对程序员是不可见的!!!),通常被放在对象内存布局最开始的地方,也就是this指针指向的地址。这个VPTR指向本对象的类所属的VTABLE。这部分代码被十分自然的放在构造器中,所以运行时new一个对象出来,对象被初始化后,这个VPTR就已经ready好了。明白了吧!这就是为什么如果程序员不写构造器,编译器会搞个默认构造器出来。Java中也是这样。

但是VTABLE的地址是在运行时才available的。初始化VPTR这段代码必须在运行时获得本对象的类型信息才能知道正确的VTABLE是哪个!所以编译器确实是插入了类型信息到对象中的。在运行时的时候可以获得。题外话:这也是RTTI的本质。

前面的说法有一个hole,就是如果一个对象多重继承怎么办?这样对于同一个对象就会有多个VTABLE。最直觉也是最家常的做法,就是搞多个VPTR出来,也是都放在对象头部。但这时就需要pointer fixups即thunks(http://en.wikipedia.org/wiki/Virtual_table),即当用不同的类型去引用该对象时,使用不同的VTABLE。

接下来的事情就简单了:当通过一个基类指针调用虚函数时,不管对象的具体类型是啥,总能找到正确的VTABLE,通过其找到被调用函数的正确地址,并调用之。

从语言使用者的角度来看,virtual只是一个关键字。使用者实际上不需要知道虚函数是怎么实现的。但由于虚函数调用会有额外的开销,有心的程序员会去研究它的实现并且在适当的时候才使用。

所谓纯虚函数,就是只有声明没有实现的函数。包含至少一个纯虚函数的类就是抽象类。

多重继承引入了二义性问题。最典型的菱形问题http://en.wikipedia.org/wiki/Diamond_problem。

C++使用虚函数来解决多态调用,使用了虚基类来解决菱形问题。

Python则规定了一个特别的method resolution order来摒除二义性:http://en.wikipedia.org/wiki/Diamond_problem。

Python中的super http://fuhm.net/super-harmful/ 

GUI framework基础原理(占位)

用户直接触发的事件(点击按钮是最经典的例子),用户间接触发的事件(例如resize引起的paint事件),系统事件(某个窗口自动弹出?)

多线程

事件队列,事件分派、传播规则

程序语言的类型系统

类型系统的本质是,赋予计算机中那些莫名二进制数据一些意义。它定义了这些东西代表了啥,并且规定了在特定类型上能做哪些操作。编译器/解释器可以检查对象的类型,也可以不检查;可以在编译时检查,也可以在运行时检查。

  1. object/value 对象/值
    • a. 程序员在程序空间中可操纵的东西
    • b. 对应一些内存空间
    • c. 下文中的“对象”和“值”可互换。一般我会用“对象”
  2. class 类
    • a. 类只不过是用户定义类型罢了
    • b. 实例的类型就是对应的类
    • c. OO中的继承经常基于类。但Self和JavaScript则是基于prototype,比较另类
    • d. 用户定义类型是一个语言feature。要提供这个feature,不一定非得提供类机制。比如JavaScript就是用函数定义不同的对象,用prototype实现继承(代码重用)。
  3. type 类型
    • a. 每一个对象都有一个或多个类型(面向对象语言一般都支持一个对象有多个类型,尤其是用户定义类型即class)
    • b. 类型这个东西在某些语言中,程序员可以操纵,即它们也是对象。在另一些语言中则不是
    • c. 前一种情况的例子包括Python, Java。不过Java只为操纵类型提供了很弱的支持,并且primitive类型无法操纵(虽然有wrapper class)。我勉强把Java归为这一类。Python中的类型则是第一级(first-class)公民。你可以写return int这样的语句
    • d. C属于后一种情况。你可以传递一个类型为某struct的值,而不是这个struct本身。
    • e. 当类型也是对象的时候,会引发一个新的问题:由于对象必有类型,所以类型对象(包括类)也有类型,对吧?(Java里的类不是对象,但可以用对象表示)
    • f. 那么类型的类型是什么呢???Python里有个type类,可谓是元类型。事实上Python允许你通过创建type类的instance创建新类型。哦my god。使用这种方式创建出的类型和用户定义类型class应该是没啥区别。所有类型对象,包括class,都是type class的实例。实例的类型当然就是对应的class了,所以Python中,类型的类型就是这个type class。
    • g. 接着说Python。type class也是个class啊,class在Python里也是第一级公民,也是对象。(咱就说new-style class吧,不要讨论old-style的了。)那type class的类型是什么呢?所有的class的类型都是type class,所以它自己也不例外。。。我们会在Java中看到类似的情况。
    • h. Java里面的类不是对象,本质上是不可操纵的。Java使用java.lang.Class的实例来表示class。你可以通过这些实例获得一些类型信息,还可以用它们创建出对应它们所表示class的实例。对应每一个类,都可以获得对应的java.lang.Class实例。当然对于java.lang.Class这个类本身,也可以获得其对应的java.lang.Class实例。

Oracle相关

Oracle Database Concepts绝对是最佳入门,不得不看。

Windows服务中的那个OracleDBConsoleXXXX(XXXX是SID名)明显是Enterprise Manger的进程。我今天重装10g,装到一个不同的目录下,发现这个服务的可执行命令还是在原来的目录下。真弱。。。于是:

emca -deconfig dbcontrol db

emca -config dbcontrol db

就行了。

expdp要先创建directory object:

SQL> create directory mydump as 'D:\oracle\product\10.2.0\admin\prox2\mydump';

然后

D:\oracle\product\10.2.0\db_1\BIN>expdp user/pwd DIRECTORY=mydump DUMPFILE=xxx

关于JavaScript,肆 (vs Python and Scheme)

JS的对象模型无疑是简单而高效的。从某种意义上来看,简直就是以函数为核心。从面向对象的角度来讲,JS是prototype-based,Python是class-based,Scheme这方面我还未学到啦~我就知道Lisp有个CLOS,还没玩过。

1. 值有类型,变量没有(dynamic typing)。JS中的变量只是名字,这和Scheme一样。Python应该也是,我不是百分百确定。

class C():
pass

D = C
c = C()
C = 1
print C # 1
del C
print D # __main__.C, though C was already deleted from context.
print c # <__main__.C instance at 0x00B44940>
print c.__class__ # __main__.C

2. JS数据类型有numbers, strings, booleans, null, undefined, objects(arrays), functions。new运算符后面可以随便跟个函数,这会创建一个新对象。在此函数内部随便干什么都行,只是这时候this引用的是刚创建的这个对象。

function f() { this.a = 2 }
f.a = 1              // f的property
alert(f)
alert(f.a)           // 1
f = new f()          // 创建对象,覆盖名字f
alert(f)             // 新对象
alert(f.a)           // 执行f()时加上的property a, 值为2

被创建的对象(objects/arrays, functions)可以随意在运行时添加properties(其内部实现应该是hashtable)。如果一个property类型为函数,并且从该对象被调用,函数中的this就是此对象:

function f() { alert(this.a) }
o = Object()
o.a = 'a in the new object'
o.method = f
o.method()             // 'a in the new object'
f2 = o.method          // f2 is equal to f, just a plain function
f2()                   // "this" refers to window object now, so "a" is not defined

如果你在全局scope定义一个函数,这个函数可被视为global object的一个方法。所以在JS中function和method真的是没什么本质区别的。 

Python的数据类型见这里:http://docs.python.org/ref/types.html

下面这段代码很能说明Python中function和method还是有区别的:

class C():
""" A dummy boring class. """

C.g = lambda self: 'method'

# unbound method
print C.g
print C.g(C())

# bound method
c = C()
print c.g
print c.g()

# changed method, still bound
c.__class__.g = lambda self: 'changed method'
print c.g
print c.g()

# function
c.g = lambda : 'function'
print c.g
print c.g()

DirCompare in Python?

I've been evaluating PyQt last weekend, and kicked a start on evaluating wxPython. Both of them seem to have native L&F. Very good. Qt is claimed to have a more advanced event model (signal/slot), but to install Qt, PyQt, MinGW together is somewhat a little complex. It also worried me on the deployment of my software. On the contrary, wxPython is much more comfortable.

I've had enough for Tkinter. Many people seem to agree, too. See what Guido van Rossum said:

wxPython is the best and most mature cross-platform GUI toolkit, given a number of constraints. The only reason wxPython isn't the standard Python GUI toolkit is that Tkinter was there first.

So funny! Another (not so friendly but quite with the personal landmark) comment:

"Why the hell hasn't wxPython become the standard GUI for Python yet?"

-- Eric S. Raymond
This reminds me of the time when I first learned Python. I was inspired and encouraged by one of Eric's essays.
Enough of talking. In my mind this software should include the following features:
1. paned window with trees simultaneously expanding/folding in each pane
2. persistent sessions
3. synchronized scrolling 
4. file/folder name filters
5. highlights
6. binary/CRC/timestamp as comparing criteria
7. sorting
8. tabs for multiple sessions of comparison
9. invoking file comparison tools (e.g., PSPad)
10. FTP support (so make your dir interface general!)
 
Note: I made a huge breakthrough just now (2007 Dec 10 1:18am) !

self-printing

((lambda (x) (list x (list 'quote x)))
 '(lambda (x) (list x (list 'quote x))))

我还没有百分之百的搞懂这个。需要对symbol的进一步认识和对Scheme解释器的进一步理解。

 

 

抽象

 

赋值

函数

高阶函数

工作在更高层次(概念)上 and/or generalize and/or 隐藏细节

SICP-1.14 solution

哎,老潘真是不擅计算order of growth,现在也就能看出所需的空间是Θ(n),因为树的最大深度和amount成正比。至于所需时间我真的不知道怎么精确计算。看到有人做的答案似乎比较倾向于Θ(n^2),说是每次调用cc都会导致调用两次cc自身。我也不知道了,先放着吧,改天翻翻算法导论再说。未完。

SICP-1.6 solution

有了之前对1.5的仔细考量,1.6就很简单啦。

(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))

代替if的这个new-if只是个普通的procedure而不是special form,因此,按照combination的eval规则,sqrt-iter会陷入无休止的递归。

等我学到macro以后,我会自己写个和if行为完全一样的new-if的,嗯嗯。。。

分页共2页 1 2 下一页 最后一页