LISP和C#在函数式编程方面有哪些主要区别?具体而言,如果LISP程序员转而使用C#,他们最有可能错过的功能是什么?
从来没有成为一个lisp用户,所以在阅读时不要让我太密集.然而;
我知道这种语言有几种变体,至少有一种可以让它在商业上保持一段时间(AutoLisp,VisualLisp - 来自Autodesk的相当大的支持)......但我不会遇到每天使用它的人.所以如果你能解释一下这个问题:
你认为它的未来会是什么样的?它会成为少数应用程序中的另一种支持语言,还是会在某个地方?
另外,除了"不得说出名字的编辑"外;
我听说Lisp的宏系统非常强大.但是,我发现很难找到一些可用于它们的实际例子; 没有它们很难实现的事情.
谁能举一些例子?
最近几个月我一直在广泛使用Emacs作为我的主要开发环境,现在我已经到了一个点,我想学习它自己的Emacs Lisp为Emacs写我自己的小东西并将它扩展到我的个人需求.
话虽如此,我还想学习Common Lisp一段时间,一起玩,探索一种新语言.我的问题是,我应该从哪里开始?请问Emacs Lisp能否为我提供必要的知识,以便以后更轻松地获取Common Lisp,反之亦然?我基本上对每条路径的效率感兴趣,以便在我最终决定从一种方言转移到另一种方言时最小化学习曲线.
Scheme为所有变量使用单个名称空间,无论它们是绑定到函数还是其他类型的值.Common Lisp将两者分开,这样标识符"hello"可以引用一个上下文中的函数,而另一个中引用一个字符串.
(注1:此问题需要上述示例;请随意编辑并添加一个,或通过电子邮件发送原作者,我会这样做.)
但是,在某些上下文中,例如将函数作为参数传递给其他函数,程序员必须通过使用明确区分他指定函数变量而不是非函数变量#',如:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
我一直认为这有点像疣,但我最近遇到的一个论点是,这实际上是一个特征:
......重要的区别实际上在于形式的语法,而不在于对象的类型.在不了解所涉及的运行时值的情况下,很明显函数形式的第一个元素必须是函数.CL采用这一事实并使其成为语言的一部分,以及宏观和特殊形式,这些形式也可以(并且必须)静态地确定.所以我的问题是:当函数名称的主要用途出现在很少想要出现变量名的地方时,为什么你希望函数的名称和变量的名称在同一名称空间中?
考虑类名的情况:为什么名为FOO的类会阻止使用名为FOO的变量?我唯一一次通过名称FOO引用该类是在期望类名的上下文中.如果在极少数情况下我需要获取绑定到类名FOO的类对象,则有FIND-CLASS.
这个论点确实从经验中对我有所帮助; Haskell中有一个类似的字段名称,它也是用于访问字段的函数.这有点尴尬:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
Run Code Online (Sandbox Code Playgroud)
这是通过一些额外的语法解决的,NamedFieldPuns扩展特别好:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
Run Code Online (Sandbox Code Playgroud)
那么,对于问题,超越一致性,Common Lisp vs. Scheme以及一般来说,所有值的单个命名空间与函数和非函数值的单独命名空间有哪些优点和缺点?
我已经掌握了一些语言(粗略的专业知识):Python,C,C++,PHP,Javascript,Haskell,Java,MIPS,x86汇编程序.但是,自从我学会了一个新的,已经差不多2年了,我开始痒了.我有几个标准:
我在想Lisp(CL?还有什么?)或OCaml.我已经有了一些使用Haskell的函数式语言的经验(是的,我知道Lisp/OCaml是多范式的).我不是专家 - 例如来自Real World Haskell的部分代码仍然可以扭曲我的大脑,但我理解基本概念和一些高级概念(仿函数,monad).
哪一个选择?我忽略了其他任何语言?另外,您能不能包括一些有用的链接到好书/教程等.
我正在通过SICP工作.目前,在第一章中,我遇到了让Racket重新定义"原语"的问题.例如,我的印象是我应该可以任意做(define + 5),这样就可以了,或重新定义sqrt程序.相反,我明白了:
define-values: cannot change constant variable: +
Run Code Online (Sandbox Code Playgroud)
我的语言目前设置为R5RS,我认为这样可以解决与SICP的兼容性问题.
当前选择: lua-jit.令人印象深刻的基准测试,我已经习惯了语法.编写高性能ABI需要仔细考虑如何构建我的C++.
其他感兴趣的问题
背景
我正在研究一个实时高容量(复杂)事件处理系统.我有一个DSL,代表源的事件结构的模式,存储格式,某些特定于域的构造,触发内部事件(构造和驱动通用处理),以及编码始终发生的某些处理步骤.
DSL看起来非常类似于SQL,事实上我使用berkeley db(通过sqlite3接口)来长期存储事件.这里的重要部分是事件处理是基于集合完成的,就像SQL一样.然而,我得出结论,我不应该在DSL中添加通用处理逻辑,而是嵌入lua或lisp来处理这个问题.
处理核心是arround boost :: asio,它是多线程的,rpc是通过协议缓冲区完成的,事件是使用协议缓冲区IO库编码的 - 事件不是使用协议缓冲区对象构建的,它们只使用相同的编码/解码库.我将创建一个包含行的数据集对象,与数据库引擎在内存集中的存储方式非常相似.首先处理DSL中的处理步骤,然后将其呈现给通用处理逻辑.
无论我使用哪种可嵌入的脚本环境,我的处理核心中的每个线程都可能需要它自己的嵌入式语言环境(这就是lua至少在你做多线程工作时需要它的方式).
问题
目前的选择是在lisp ECL和lua之间.请记住,性能和吞吐量是一个强烈要求,这意味着非常需要最小化内存分配:
如果你在我的位置,你会选择哪种语言?
有没有我应该考虑的替代方案(不建议没有可嵌入实现的语言).Javascript v8也许吧?
lisp更适合这个领域吗?我不认为lua和lisp在它们提供的方面有所不同.叫我出去:D
我应该考虑其他任何属性(如下所示)吗?
我断言任何形式的嵌入式数据库IO(请参阅下面的示例DSL以获取上下文)使脚本语言调用在数量级上相形见绌,并且选择这两者不会给总体吞吐量增加太多开销.我是在正确的轨道上吗?:d
期望的属性
我想将我的数据集映射到lisp列表或lua表,我想最小化冗余数据副本.例如,如果两个表具有相同的形状,则从一个数据集向另一个数据集添加行应尝试使用引用语义.
我可以保证在我进行lua/lisp调用时,作为输入传递的数据集不会改变.我希望lua和lisp在可能的情况下强制不改变数据集.
在嵌入式调用结束后,应该销毁数据集,创建的任何引用都需要用副本替换(我猜).
DSL示例
我附上了一个DSL供您观看,这样您就可以了解我想要实现的目标.注意:DSL不显示通用处理.
// Derived Events : NewSession EndSession
NAMESPACE WebEvents
{
SYMBOLTABLE DomainName(TEXT) AS INT4;
SYMBOLTABLE STPageHitId(GUID) AS INT8;
SYMBOLTABLE UrlPair(TEXT hostname ,TEXT scriptname) AS INT4;
SYMBOLTABLE UserAgent(TEXT UserAgent) AS INT4;
EVENT 3:PageInput
{
//------------------------------------------------------------//
REQUIRED 1:PagehitId GUID
REQUIRED 2:Attribute TEXT;
REQUIRED 3:Value TEXT;
FABRRICATED 4:PagehitIdSymbol INT8;
//------------------------------------------------------------// …Run Code Online (Sandbox Code Playgroud) 我被搞糊涂了所有内置在声称为防止评价在某种程度上数学函数:Unevaluated,Defer,Hold,以及超过一半的形式的打Hold*.Mathematica文档只是单独解释了每个函数,但没有解释为什么要选择其中一个函数.任何人都可以对所有这些功能提供一致的解释吗?整件事对我来说似乎是一个令人费解的混乱.将它全部与Lisp宏相关可能是一个很好的起点.
大多数Mathematica语言都设计得非常好,但看起来Wolfram真的把自己描绘成了这方面的一个角落.或者我可能会遗漏一些东西.
我将继续承认我对Lisp的了解非常少.但是我对这门语言非常感兴趣,并计划在不久的将来开始认真学习它.我对这些问题的理解无疑是有缺陷的,所以如果我说出任何错误的内容,请评论并纠正我而不是贬低.
真正的同性恋和自我修改的语言
我正在寻找支持Homoiconicity(代码与数据表示相同)和不受限制的自我修改的编程语言示例(Unrestricted意味着您可以更改正在运行的代码的每个方面,而不仅仅是发出新代码或更改函数指针/代表).
到目前为止我发现的三个例子符合这个标准:
为什么Lisp不在此列表中
Lisp不在那个列表中,因为在我看来,Lisp 几乎只是Homoiconic,并且只支持受限制的自我修改.你可以做点什么
(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)
这将做同样的事情
(eval '(+ 1 2 3))
Run Code Online (Sandbox Code Playgroud)
第一个版本(+ 1 2 3)是原始代码,而第二个版本是数据.通过假设这个陈述的真实性,可以说Lisp甚至不是杀人的.代码与数据具有相同的表示形式,即它们都是列表/树/ S表达式.但事实上你必须明确地标记这些列表/树/ S表达式中的哪些是代码以及哪些是我的数据似乎说Lisp毕竟不是杀人的.这些表示非常相似,但它们的细节不同,您必须实际说明您是在处理代码还是数据.这绝不是一件坏事(实际上其他任何东西都会是疯狂的),但它强调了Lisp和机器代码之间的区别.在机器代码中,您不必明确标记哪些数字是指令,哪些是指针,哪些是数据.在实际需要解释之前,一切都只是一个数字,此时它可以是任何一个.
对于不受限制的自我修改,这是一个更强大的案例.当然,您可以获取代表某些代码并对其进行操作的列表.例如改变
'(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)
至
'(+ 1 4 3)
Run Code Online (Sandbox Code Playgroud)
然后你运行它eval.但是当你这样做时,你只是编译一些代码并运行它.您没有修改现有代码,只是发出并运行新代码.C#可以使用表达式树完全相同的事情,即使是一种不太方便的格式(由于C#代码对其AST具有不同的表示而产生,而不是Lisp,这是它自己的AST).您是否可以实际获取整个源文件并在运行时开始修改整个源文件,对源文件所做的更改会对程序行为产生实时影响?
除非有某种方法可以做到这一点,否则Lisp既不是讽刺也不是自我修改.(为了推断定义的争论,Lisp不是同源的,也不是自我修改到与机器代码相同的程度.)
如何制作Lisp Homoiconic/Unrestrictedly self-modifiable
我可以看到3种可能的方法使Lisp像机器代码一样可以单调/自我修改.
点1.结合2.将产生一个完全自我修改的Lisp.前提是可以生产所描述的神奇的Lisp机器.2.单独可以产生自我修改的Lisp,但是在冯·诺依曼架构上的实现可能非常低效.
问题
附录
语言具有不受限制的自我修改但不具有杀戮性
其他概念和语言可能在某种程度上相关/有趣:Lisp,Ruby,Snobol,Forth和它的编译时元编程,Smalltalk和它的反射,无类型的lambda演算,它的属性是一切都是函数(哪种意味着假设我们可以发明一台直接执行lambda演算的机器,lambda演算将是homoiconic而Von Neumann机器代码在所述机器上运行时不会.[并且Godels定理将是可执行的.哈哈,可怕的想法:P])