我已经做了几年的面向对象编程,而且我没有做太多的函数式编程.我对飞行模拟器感兴趣,并对Lisp的函数编程方面感到好奇.飞行模拟器或任何其他真实世界的模拟器在面向对象的范例中对我有意义.
这是我的问题:
面向对象是表示真实世界模拟域的最佳方式吗?
我知道Common Lisp有CLOS(OO for lisp),但我的问题是关于用函数式语言编写飞行模拟器.因此,如果您要在Lisp中编写它,您会选择使用CLOS还是以函数方式编写它?
有没有人对使用lisp或任何功能语言编写飞行模拟器进行编码?
更新11/8/12 - 对于那些感兴趣的人来说类似的问题 - > 函数式编程如何应用于模拟?
将"Lisp"视为一种功能语言是一个常见的错误.真的,它最好被认为是一个语言家族,但是现在人们说Lisp它们通常意味着Common Lisp.
Common Lisp允许函数式编程,但它本身不是函数式语言.相反,它是一种通用语言.Scheme是一个小得多的变体,在方向上更具功能性,当然也有其他变体.
至于你的问题,这是一个不错的选择吗?这真的取决于你的计划.Common Lisp尤其对这类事情有一些真正的优势.它在您通常在所谓的脚本语言中看到的级别上具有交互性和内省性,使得开发速度非常快.同时编译并具有高效的编译器,因此您可以期望与其他高效编译器在同一个球场中的性能(c的两倍是典型的ime).虽然它是一种大型语言,但它具有比c ++更加一致的设计,并且元编程功能可以为您的特定应用程序创建非常干净,易于理解的代码.如果你只看这些方面常见的lisp看起来很神奇.
但是,有缺点.社区很小,如果你正在寻找的话,你找不到很多人可以帮忙.虽然内置库很大,但您找不到尽可能多的第三方库,因此您最终可能会从头开始编写更多内容.最后,虽然它绝不是一个有围墙的花园,但CL并没有像python那样与外国图书馆的顺利整合.这并不代表你不能调用c代码,有很好的工具.
按照他们的方式,CLOS是我能想到的最强大的面向对象系统,但如果你来自主流的c ++/java/c#/等,这是一个完全不同的方法.OO背景(是的,它们有所不同,但超出了单个与多个inh.并没有那么多)你可能会发现它有点奇怪,几乎完全由内而外.
如果你走这条路,你将不得不关注实际渲染管道性能的一些问题,如果你自己用CLOS写的话.类系统具有令人难以置信的运行时灵活性(即在运行时更新类定义,而不是通过猴子修补等,但通过实际更改类和更新实例),但是您需要为此支付一些调度成本.
对于它的价值,我过去曾使用过CL作为需要数值效率的研究代码,即不同类型的模拟.这对我来说很有用.在那种情况下,我并不担心使用现有代码 - 它不存在,所以无论如何我几乎从头开始编写所有内容.
总之,它可能是这个项目的一个很好的语言选择,但不是唯一的.如果你不使用具有高级方面和良好性能的语言(如CL,OCaml和其他一些语言),我肯定会看到使用像lua这样的语言进行两级方法的可能性python(很多libs)在一些c或c ++代码之上执行繁重的工作.
如果你看一下游戏或模拟器行业,你会发现很多C++加上一些添加的脚本组件.还可以使用其他语言编写用于风景设计或相关任务的工具.但是在该领域中只使用了很少的Lisp.您需要成为一名优秀的黑客才能从Lisp中获得必要的性能,并能够访问或编写低级代码.你怎么知道这个?尝试,失败,学习,尝试,失败少,学习,......只有编写代码并尝试使用它.Lisp对于优秀的软件工程师或那些有可能成为优秀软件工程师的人来说非常有用.
垃圾收集器的主要障碍之一.要么你有一个非常简单的(然后你有随机暂停的性能问题)或你有一个复杂的(然后你有一个问题,让它正常工作).只有少数垃圾收集器是合适的 - 大多数Lisp实现具有良好的GC实现,但仍然没有针对实时或接近实时的使用进行调整.确实存在例外情况.使用C++,您可以忘记GC,因为通常没有.
使用垃圾收集器进行自动内存管理的另一种方法是不使用GC并"手动"管理内存.一些(甚至是商业的)Lisp应用程序使用它来支持一些实时响应(例如过程控制专家系统).
在该区域开发的最接近的东西是来自Naughty Dog的Playstation I(后来的游戏属于Playstation II)的Crash Bandicoot(以及后来的游戏)游戏.由于他们已经被索尼收购,他们为Playstation III换成了C++.他们的开发环境是用Allegro Common Lisp编写的,它包含一个Scheme(一个Lisp方言)变体的编译器.在开发系统上,代码被编译,然后在开发期间下载到Playstation.他们有自己的3D引擎(非常令人印象深刻,总是得到游戏杂志的优秀评论),增量级别加载,许多不同演员的复杂行为控制等等.所以Playstation真的执行了Scheme代码,但内存管理没有完成通过GC(afaik).他们必须自己开发所有技术 - 没有人提供基于Lisp的工具 - 但他们可以,因为他们是优秀的软件开发人员.从那时起,我还没有听说过类似的项目.请注意,这不仅仅是用于编写脚本的Lisp - 它一直是Lisp.
在Scheme方面,还有一个名为Ypsilon Scheme的新的有趣实现.它是为弹球游戏开发的 - 这也可能是其他游戏的基础.
在Common Lisp方面,已经有Lisp应用程序与飞行模拟器交谈并控制它们的各个方面.有些游戏库基于SDL.有OpenGL的接口.还有类似"开放代理引擎"的东西.还有一些用Common Lisp编写的3d图形应用程序 - 甚至是一些复杂的应用程序.但是在飞行模拟领域,现有技术很少.
关于CLOS与功能编程的主题.可能人们都不会使用.如果您需要从系统中挤出所有可能的性能,那么CLOS已经有一些人们可能想要避免的开销.
看看功能反应式编程.在Haskell中有许多这样的框架(不了解其他语言),其中大多数是基于箭头的.基本思想是表示时变值和事件之间的关系.因此,例如,您将编写(使用没有特定库的Haskell箭头表示法):
velocity <- {some expression of airspeed, heading, gravity etc.} position <- integrate <- velocity
第二行声明了位置和速度之间的关系.< - 箭头操作符是一堆将所有内容组合在一起的库调用的语法糖.
然后你可能会说:
groundLevel <- getGroundLevel <- position altitude <- getAltitude <- position crashed <- liftA2 (<) altitude groundLevel
宣布如果你的海拔高度低于你所在位置的地面水平那么你就已经崩溃了.就像这里的其他变量一样,"崩溃"不仅仅是一个单一的值,它是一个随时间变化的值流.这就是"liftA2"功能用于将比较运算符从简单值"提升"到流的原因.
IO在这个范例中不是问题.输入是时变值,例如操纵杆X和Y,而屏幕上的图像只是另一个时变值.在最顶层,您的整个模拟器是从输入到输出的箭头.然后你调用一个"运行"函数,将箭头转换为运行游戏的IO动作.
如果你在Lisp中写这个,你可能会发现自己创建了一堆基本上重新发明箭头的宏,因此可能只需要找到箭头就可以了.