Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1534879
  • 博文数量: 114
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 1357
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-19 18:13
文章分类
文章存档

2010年(8)

2009年(9)

2008年(27)

2007年(62)

2006年(8)

我的朋友

分类: C/C++

2009-01-07 22:46:41

北京理工大学 20981 陈罡

Squirrel这个单词是松鼠的意思,初看起来似乎偶迷上了小动物,呵呵,其实不然。

我迷上的是一个叫做Squirrel的脚本引擎。既然打算入手开始研究,那就从最基础
的东西开始,这个Squirrel到底是何方神圣?做什么的?下面偶就用Squirrel手册
里面的一段介绍来开始Squirrel学习之旅。顺便复习复习基本的面向对象的概念。

1、Squirrel简介
以下是Squirrel 2.x文档中的英文原文:
Squirrel is a high level imperative-OO programming language, 
designed to be a powerful scripting tool that fits in the size, 
memory bandwidth, and real-time requirements of applications like games. 
Although Squirrel offers a wide range of features like dynamic typing, 
delegation, higher order functions, generators, tail recursion, 
exception handling, automatic memory management, both compiler and virtual machine
fit together in about 6k lines of C++ code.

我给简单翻译一下:

Squirrel是一种高级的面向对象的编程语言,Squirrel是一个强大的脚本工具,
Squirrel可以用于开发对文件大小、内存占用、带宽以及实时性要求非常严格的

程序(例如游戏,偶很纳闷游戏需要这么高的要求嘛?)。

尽管Squirrel提供了大量的特性(例如支持动态数据类型,

委托,函数对象,迭代器,尾递归,异常处理,自动内存管理),Squirrel包括
编译器和虚拟机的全部代码只有6000行不到的代码。

一步一步慢慢来。。。

奥,Squirrel是一个面向对象的脚本引擎,支持了不少面向对象的特性,这个动态
数据类型嘛,应该是所有脚本引擎都支持的:
a = 3 
这时候a应该整形的变量,Integer类型的;
a = 'hello world'
这个时候这个a就应该是字符串类型的变量了,String类型的,这个特性应该是个脚本
引擎里面就支持的。ok,继续,继续。

这个委托(delegation)可是说来话长了,在面向对象的概念中,如果我没有理解错
的话应该代表两个意思,一个意思是代表一种设计模式(委托模式),另外一个意思
则是代表一种语言的关键字。

首先,先用c++来回顾一下delegation委托模式(如果偶写的不对欢迎拍砖:P):
定义一个类,叫做CA:
class CA {
  public:
  virtual void foo() {
  cout<<"CA::foo()"<  }
 };

然后,定义一个CA类的孩子类CAa:
class CAa : public CA {
  public:
  virtual void foo() {
  cout<<"CAa::foo()"<  }
 };

好了,再定义个类,叫做CB,只是定义的时候稍微做点手脚:
class CB {
  public:
  CB(CA* pa) : m_pa(pa) { }
  CA * m_pa;
  void foo() {
  m_pa->foo();
  }
 };

然后就可以用下面的代码来实现这个委托模式--->同一个类的对象可以具有不同的行为。。。
// 各位这肯定会有内存泄露的,偶知道的,为了说明问题偶就不管那么多了。。。
CB b1(new CA);
CB b2(new CAa);
b1.foo() ; 
b2.foo() ; 

然后我们就会看到如下的输出:
CA::foo()
CAa::foo()
这就是所谓的委托模式了。

再来看那种关键字模式的委托。。。还是用类似java/c#的语法来演示一下吧,
具体的语法细节需要查材料,偶就犯懒了。。。希望做过实验的朋友帮偶补全:
 class CA {
  void foo() {
  this.bar() 
  }
 
  void bar() {
  print("CA::bar()")
  }
 }
 
 class CB {
  delegationlink A a
 
  void foo() {
  a.foo() // call foo() on the a-instance
  }
 
  void bar() {
  print("CB::bar()")
  }
 }
 
 a = new A()
 b = new B(a) // establish delegation between two objects
然后调用a.foo()和b.foo()看看结果。

然后就是函数对象,天知道老外为什么把这东西叫做higher order function,或许我理解的
有问题,不过这个应该也是几乎所有的脚本引擎都支持的,例如:
a = print
a("hello world")
这个时候a就是函数对象,a可以做为其它函数的参数传入其它函数,也可以做为其它函数的
返回值而存在。呵呵,在脚本的世界里,定义一个返回函数对象的函数是合法的(这一点有点
类似于c语言中定义返回值为指向函数的指针的函数一样,比较绕口了,慢慢读就会明白)

这个generator翻译成迭代器,google了一下,这个类似于标准c++里面stl中定义的iterator
一样的,用python来解释一下这个东西,应该是这个样子的:
def countfrom(n):
  while True:
  yield n
  n += 1
 
# Example use: printing out the integers from 10 to 20.
# Note that this iteration terminates normally, despite countfrom() being
# written as an infinite loop.
 
for i in countfrom(10):
  if i <= 20:
  print i
  else:
  break
 
# Another generator, which produces prime numbers indefinitely as needed. 
def primes():
  n = 2
  p = []
  while True:
  if not any( n % f == 0 for f in p ):
  yield n
  p.append( n )
  n += 1
 
>>> f = primes()
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
7

一步一步来,首先。。。什么是尾递归?
尾递归是针对传统的递归算法而言的, 传统的递归算法好像永远和溢出、效率低下联系在一起。
而尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在
调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量。直接让被调用的函数
返回时越过调用者, 返回到调用者的调用者去.

以下是一个具体的实例:
线性递归:
long Rescuvie(long n) {  
  return(n == 1) ? 1 : n * Rescuvie(n - 1);  
}  

尾递归:
long TailRescuvie(long n, long a) {  
  return(n == 1) ? a : TailRescuvie(n - 1, a * n);  
}  

long TailRescuvie(long n) {//封装用的  
  return(n == 0) ? 1 : TailRescuvie(n, 1);  
}  

当n = 5时
对于线性递归, 他的递归过程如下:
Rescuvie(5)  
{5 * Rescuvie(4)}
{5 * {4 * Rescuvie(3)}}
{5 * {4 * {3 * Rescuvie(2)}}}
{5 * {4 * {3 * {2 * Rescuvie(1)}}}}
{5 * {4 * {3 * {2 * 1}}}}
{5 * {4 * {3 * 2}}}
{5 * {4 * 6}}
{5 * 24}
120

对于尾递归, 他的递归过程如下:
TailRescuvie(5)
TailRescuvie(5, 1)
TailRescuvie(4, 5)
TailRescuvie(3, 20)
TailRescuvie(2, 60)
TailRescuvie(1, 120)
120

很容易看出, 普通的线性递归比尾递归更加消耗资源, 在实现上说, 每次重复的过程
调用都使得调用链条不断加长. 系统不得不使用栈进行数据保存和恢复.而尾递归就
不存在这样的问题, 因为他的状态完全由n和a保存。

下一步的异常处理学过c++的基本都很熟悉吧,就是try...catch嘛,内存管理这东西
估计只有脚本引擎以及java这种高级语言才会有的,类似c++中的内存池的概念,没啥可
挖掘的了,都是极为普通的概念了。

费劲啊,弄到现在这么一个简单Squirrel简介就折腾出来了这么多东西。。。
看来这个Squirrel还真是一个“有深度”的东西呢,不早了,有时间再继续写吧。。。

各位晚安

阅读(8267) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~