很早就开始VBF的设计,在经历开发和调整了两个月的时间后,VBF的第一个BETA版终于和大家见面了!我是从前一阶段博客园上较为流行的动态语言讨论上获得灵感。我主要不是想写一个动态语言,而是发现很多动态语言共有的特征——不同程度地支持函数式编程(Functional Programming,FP)。这是一种显著不同于命令式编程(目前的VB,和C#均为命令式编程语言,面向过程和面向对象也是命令式编程范式的扩展)的编程范式。它讲究组合、高阶函数和延迟计算。在纯粹的FP语言(Lisp, SML)可以不使用变量,函数执行没有副作用,表达式的意义更接近数学式的意义而不是计算机的执行方式。函数式语言具有比命令式语言更高的数学抽象力,因此在描述某些算法的时候比命令式语言更佳。现在人们发现,在命令式语言中引入局部的函数式编程思想,能将两种范式的好处合二为一。VB9和C#3都将不同程度地引入函数式编程的特性。
我开发VBF主要就是希望利用Visual Basic 2005和C# 2.0自身所具有的语言抽象力将函数式编程的思想引入。我不对编译器进行改造,也不编写任何插件,只要引用我的类库,就可以实现一些非常精妙的语法。
[VB]
Dim list As List(Of Integer) = GetList() '假设用一些数填充list
Dim result As List(Of Integer)
'找到所有大于25或者小于等于17的数,存入result
result = list.FindAll(IdInt > 25 Or IdInt <=17)
[C#]
// using I = VBF.Functional.Identities
List<int> list = GetList(); //假设用一些数填充list
//找到所有大于25或者小于等于17的数,存入result
List<int> result = list.FindAll(I.IdInt > 25 | I.IdInt <= 17);
如你所见,“IdInt”就如同表达式中变量的占位符,由它生成的表达式并不求值,而是将表达式的运算规则保存下来传递给FindAll,而FindAll作为一个高阶函数将表达式作用于列表中的每一项上。这就是延迟计算。这里IdInt为“恒等组合子(Identity Combinator),是VBF初期所支持的几个组合子之一。通过组合子之间的组合就可以重用函数的功能,比如IdInt和+(对结果进行加法的组合子)和7(常函数)三者组合,就生成了对一个数加7的函数。这就是我VBF BETA1的最基本功能。我在VBF 1.0 BETA1中支持了以下特性:
Functor 函数体基类,支持大量组合运算符和延迟求值
Combinator 组合子基类
Identity和Constant组合子
Predicate 谓词
ComparisonPredicate 比较谓词(大于、小于等)
进行通用四则运算的组合子
进行字符串处理的组合子
我的VBF代码中非常频繁地使用泛型和运算符重载,大量手法均为主流类库所见不到的。我也因此获得了非常丰富的在.NET中使用泛型的经验。大家均可下载我的代码参考。项目主页:http://www.sf.net/projects/vbf
希望大家对我的VBF提出建议,同时敬请关注VBF的后续版本,有更多精彩的内容。

posted on 2005-11-11 08:55
装配脑袋 阅读(1273)
评论(16) 编辑 收藏
评论
| 2005-11-11 09:08
好!学习...
| 2005-11-11 09:10
非常抱歉的告诉大家——因为这次时间仓促,所以几乎没有文档和例子。请大家多多包涵!
| 2005-11-11 09:17
先收藏。前段时间看了点 python 的 fp 知识,还没来得及了解 VB 的。楼主是否可以提供多点学习资料的链接。谢谢了~
| 2005-11-11 09:51
VB大牛!
| 2005-11-11 09:57
感觉你上面的例子在模仿dotnet3.0
:)
| 2005-11-11 10:04
@Lion
你注意到了,已开始我的确是想做Lambda的。不过后来发现VB和C#的抽象力量还不够强大,做起Lambda来不得心应手。所以就转向组合子逻辑的实现了。
不过VBF绝不仅仅是C# 3.0语法模仿版,这是一个真正的函数式编程类库。可以用来写AI程序和词法解析等。
| 2005-11-11 10:41
3.0的 lambda现在能不能填一块语句了?
| 2005-11-11 11:07
关注,希望丰富文档
| 2005-11-11 11:15
@脑袋
看出来了,已经在sf下载收藏起来了,有空学习一下,不懂的地方还要向你请教
| 2005-11-11 11:59
Good, 等了好久了~~
| 2005-11-11 12:49
极度佩服中。学习啊学习……
| 2005-11-11 13:25
我实在是笨,不能理解如此高深之函数,我写了一个试验代码,显示名字为"Steve“的人员。:
using System;
using System.Collections.Generic;
using System.Text;
using Ident = ConsoleApplication1.Identities2;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
// using I = VBF.Functional.Identities
List<Employee> list = GetList(); //假设用一些数填充list
//找到所有名字是Steve的,存入result
List<Employee> result = list.FindAll(Ident.IdEmployee.Name == "Steve");
foreach (Employee a in result) {
Console.WriteLine(a.Name);
}
}
private static List<Employee> GetList() {
List<Employee> ret = new List<Employee>();
ret.Add(new Employee("A"));
ret.Add(new Employee("B"));
ret.Add(new Employee("Steve"));
return ret;
}
}
class Employee {
public Employee(string pName) {
Name = pName;
}
public string Name;
}
sealed class Identities2 {
public static VBF.Functional.Identity<Employee> IdEmployee {
get {
return VBF.Functional.Identity<Employee>.Default;
}
}
}
}
编译不能通过,说没有Name属性,我该怎么办?
| 2005-11-11 13:44
@tansm
默认的Functor是不支持自动到属性的转换的,因为.(圆点)运算符无法重载。我正在想办法。
你可以自己写一个Functor来实现此功能
public class EmployeeName : Functor<Employee, string>
{
public override string Invoke(Employee obj){ return obj.Name; }
}
然后这样写
//找到所有名字是Steve的,存入result
List<Employee> result = list.FindAll((new EmployeeName()) == "Steve");
如果你需要从IdEmployee开始,那么必须写一个Combinator。就会显得复杂一些。
我无法支持属性,就是因为没有合适的语法来做这件事,如果你能想到,希望马上告诉我:)
| 2005-11-11 13:47
PS.我重载的==一般用于实现有IComparable接口对象的比较。如果你做字符串比较,我建议你用Equals代替==(Equals也被我重写过已经面目全非,呵呵)
| 2005-11-11 15:54
dotnot3.0是什么?
| 2005-11-11 16:12
能否转换成C#来学习学习呀??