似乎每个人最近都在跳跃着充满活力,没有编辑的潮流。我大多只使用编译的静态类型语言(C,Java,.Net)。我对动态语言的体验是ASP(Vb Script),JavaScript和PHP。在考虑动态语言时,使用这些技术在我的嘴里留下了不好的味道。通常会被编译器捕获的事情(例如拼写错误的变量名称以及将错误类型的值分配给变量)直到运行时才会发生。即便如此,您可能也不会注意到错误,因为它只是创建一个新变量,并分配一些默认值。我也从未见过intellisense在动态语言中运行良好,因为变量没有任何明确的类型。
我想知道的是,人们对动态语言有何吸引力?动态语言允许您执行的操作无法完成或在编译语言中难以完成的主要优点是什么。在我看来,我们很久以前就决定,像未编译的asp页面抛出运行时异常这样的事情是个坏主意。为什么这类代码会重新出现?为什么至少在我看来,Ruby on Rails看起来并不像10年前你用ASP做过的任何东西?
答案 0 :(得分:102)
我认为原因是人们习惯于静态类型化的语言,这些语言具有非常有限且无法表达的类型系统。这些是Java,C ++,Pascal等语言。而不是朝着更具表现力的类型系统和更好的类型推断的方向发展(例如在Haskell中,甚至在某种程度上甚至是SQL),有些人喜欢只保留所有“类型”信息都在他们的头脑中(以及他们的测试中),并完全取消静态类型检查。
这到底是什么让你不清楚。关于类型检查存在许多误解的概念,我最常见的是这两种概念。
谬误:动态语言不那么冗长。误解是类型信息等于类型注释。这完全是不真实的。我们都知道类型注释很烦人。机器应该能够找出那些东西。事实上,它在现代编译器中确实存在。这是一个静态类型的QuickSort,分为两行Haskell(来自haskell.org):
qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
这是LISP中的动态类型QuickSort(来自swisspig.net):
(defun quicksort (lis) (if (null lis) nil
(let* ((x (car lis)) (r (cdr lis)) (fn (lambda (a) (< a x))))
(append (quicksort (remove-if-not fn r)) (list x)
(quicksort (remove-if fn r))))))
Haskell示例伪造了静态类型的假设,因此详细。 LISP示例伪造了详细的假设,因此静态类型。在打字和冗长之间的任何一个方向都没有任何暗示。你可以放心地把它放在心上。
谬误:静态类型语言必须编译,而不是解释。再次,不是真的。许多静态类型的语言都有解释器。有一个Scala解释器,Haskell的GHCi和Hugs解释器,当然SQL的静态类型和解释时间比我活着的时间更长。
你知道,也许充满活力的人群只想要自由而不必仔细思考他们正在做什么。该软件可能不正确或不健壮,但可能不一定。
就我个人而言,我认为那些放弃类型安全以购买一点暂时自由的人,既不应该获得自由,也不应该打字安全。
答案 1 :(得分:70)
不要忘记您需要在单元测试中编写10x代码覆盖率来替换编译器所做的事情:D
我去过那里,用动态语言做到了,我看到绝对没有优势。
答案 2 :(得分:40)
在阅读其他人的回答时,似乎动态语言或多或少有三个参数:
1)代码不那么冗长。 我觉得这没有效果。一些动态语言比一些静态语言更简洁。但是F#是静态类型的,但是那里的静态类型并没有添加太多(如果有的话)代码。但它是隐式输入的,但这是另一回事。
2)“我最喜欢的动态语言X有我最喜欢的功能特性Y,因此动态更好”。不要混淆功能和动态(我不明白为什么要这样说)。
3)在动态语言中,您可以立即看到结果。新闻:您也可以在Visual Studio中使用C#(自2005年起)。只需设置一个断点,在调试器中运行程序并在重新编译时修改程序。我一直这样做,而且效果很好。
我自己,我是静态打字的坚定拥护者,主要原因之一是:可维护性。我有一个系统,里面有几行10k的JavaScript,而任何重构我想要做半天,因为(不存在的)编译器不会告诉我那个变量重命名弄乱。这就是我自己编写的代码,IMO结构合理。我不想要负责其他人写的等效动态系统。
我想我会因此大肆投票,但我会抓住机会。
答案 3 :(得分:19)
我从未使用过不允许运行时错误的语言。恕我直言,这主要是一个红鲱鱼:编译器没有捕获所有拼写错误,也没有验证意图。当您需要显式类型时,显式键入很棒,但大多数情况下,您不需要。在generics
上搜索问题或关于使用无符号类型是否是索引变量的一个好选择的问题 - 大多数时候,这些东西只是妨碍了,并且让人们在旋转时旋转有时间在他们手上。
但是,我还没有真正回答你的问题。为什么动态语言很吸引人?因为过了一段时间,编写代码变得迟钝,你只想实现算法。你已经坐下来用笔,图解的潜在问题场景进行了全部工作并证明它们是可解决的,剩下要做的唯一事情就是编写二十行实现代码......以及两百行样板文件来编译。然后你意识到你使用的类型系统并没有反映你实际在做什么,而是其他人对你可能做什么的超抽象概念,而你很久以前就放弃了编程对于一个如此强迫性的knicknack调整生活,即使是虚构的侦探Adrian Monk也会感到羞耻。
当你去涂抹开始认真看待动态语言时。
答案 4 :(得分:19)
我是一名全职的.Net程序员,完全陷入了静态类型C#的阵痛中。但是,我喜欢现代JavaScript。
一般来说,我认为动态语言允许您比静态类型语言更简洁地表达 intent ,因为您花费更少的时间和空间来定义构建块在您尝试表达时所表达的内容在许多情况下,他们是不言而喻的。
我认为还有多种动态语言。我不想再回到VBScript中编写经典的ASP页面了。为了有用,我认为动态语言需要在其核心支持某种类型的集合,列表或关联构造,以便可以表达对象(或对象的传递),并允许您构建更复杂的构造。 (也许我们都应该在LISP中编码......这是一个笑话......)
我认为在.Net圈子中,动态语言会因为与VBScript和/或JavaScript相关而变得糟糕。由于Kibbee声明的许多原因,VBScript只是一个被召回的噩梦 - 任何人都记得使用CLng在VBScript中强制执行类型以确保你有足够的位用于32位整数。此外,我认为JavaScript仍然被视为下拉菜单的浏览器语言,它以不同的方式为所有浏览器编写。在这种情况下,问题不是语言,而是各种浏览器对象模型。有趣的是,C#越成熟,它开始看起来越动态。我喜欢Lambda表达式,匿名对象和类型推断。每天感觉更像是JavaScript。
答案 5 :(得分:18)
这是一个静态类型的QuickSort,分为两行Haskell(来自haskell.org):
qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
这是LISP中的动态类型QuickSort(来自swisspig.net):
(defun quicksort (lis) (if (null lis) nil (let* ((x (car lis)) (r (cdr lis)) (fn (lambda (a) (< a x)))) (append (quicksort (remove-if-not fn r)) (list x) (quicksort (remove-if fn r))))))
我认为你在这里用你选择的语言来偏见。众所周知,Lisp非常沉重。与Haskell更接近的是Python。
if len(L) <= 1: return L
return qsort([lt for lt in L[1:] if lt < L[0]]) + [L[0]] + qsort([ge for ge in L[1:] if ge >= L[0]])
来自here
的Python代码答案 6 :(得分:15)
对我来说,动态语言的优势在于,由于更少的代码以及Ruby的块和Python的列表理解等功能技术,代码变得更强可读。
但是我有点想念编译时检查(错字确实发生)和IDE自动完成。总的来说,较少的代码和可读性为我带来了回报。
另一个优点是语言的解释/非编译特性。更改一些代码并立即查看结果。在开发过程中真的节省了时间。
最后但并非最不重要的是,我喜欢这样一个事实:你可以启动一个控制台并尝试一些你不确定的东西,就像你之前从未使用的类或方法一样看看它的表现如何。控制台有很多用途,我只想留下让你弄清楚。
答案 7 :(得分:12)
您对动态语言的论证完全有效。但是,请考虑以下事项:
我也发现一开始就远离静态打字的安全世界有点可怕,但对我而言,优势远远超过了劣势,而且我从未回头。
答案 8 :(得分:8)
我认为动态类型语言的“新发现的爱”与静态类型的语言在绝对意义上是更好还是更差的关系不如某些动态语言。 Ruby on Rails显然是一个引起动态语言复兴的重要现象。让rails如此受欢迎并且从静态阵营中创建了如此多的转换器的主要原因是:非常简洁和干燥的代码和配置。与需要大量XML配置的Java Web框架相比,尤其如此。许多Java程序员 - 也是聪明的程序员 - 进行了转换,有些甚至传播了ruby和其他动态语言。对我来说,三个不同的功能允许像Ruby或Python这样的动态语言更简洁:
这三个功能并非动态语言所独有,但它们当然不存在于当今流行的静态语言中:Java和C#。您可能认为C#在代理中有#2,但我认为它根本没有被广泛使用 - 例如列表操作。
对于更高级的静态语言... Haskell是一种很棒的语言,它有#1和#2,虽然它没有#3,但它的类型系统非常灵活,你可能找不到缺点元的限制。我相信你可以在编译时使用语言扩展在OCaml中进行元编程。 Scala是最近添加的,非常有前景。 .NET阵营的F#。但是,这些语言的用户占少数,因此他们并没有真正为编程语言领域的这种变化做出贡献。事实上,除了其他动态语言之外,我非常相信Ruby的受欢迎程度会以积极的方式影响Haskell,OCaml,Scala和F#等语言的流行。
答案 9 :(得分:7)
就我个人而言,我认为你所使用的大多数“动态”语言恰好都是一般语言的不良例子。
我方式在Python中比在C或Java中更高效,而不仅仅是因为你必须进行edit-compile-link-run舞蹈。我在Objective-C中的效率越来越高,但这可能更多是由于框架。
毋庸置疑,除了PHP之外,我在这些语言中的效率更高。好吧,我宁愿在Scheme或Prolog中编写代码而不是PHP代码。 (但是最近我实际上做了更多的Prolog而不是其他任何东西,所以拿着那些盐!)
答案 10 :(得分:6)
我喜欢动态(键入,因为这似乎是线程的焦点)语言的主要原因是我使用的(在工作环境中)远远优于我的非动态语言用过的。 C,C ++,Java等......它们都是用于完成实际工作的可怕语言。我希望看到一种隐式类型的语言,这种语言在很多动态类型语言中编程是很自然的。
话虽这么说,但某些结构在动态类型语言中才是惊人的。例如,在Tcl
中 lindex $mylist end-2
您传入“end-2”以表示您想要的索引这一事实对读者来说非常简洁明了。我还没有看到一种完成这种语言的静态类型语言。
答案 11 :(得分:6)
我对动态语言的欣赏与功能性的关系非常紧密。 Python的列表推导,Ruby的闭包和JavaScript的原型对象都是这些语言非常吸引人的方面。所有这些都具有一流的功能 - 我再也看不到它的生活。
我不会以同样的方式对PHP和VB(脚本)进行分类。对我来说,这些主要是命令式语言,具有你建议的所有动态类型缺陷。
当然,您没有获得相同级别的编译时检查(因为没有编译时间),但我希望静态语法检查工具能够随着时间的推移而发展,以至少部分地解决该问题。
答案 12 :(得分:6)
动态语言的一个优点是能够更改代码并继续运行。无需重新编译。在VS.Net 2008中,在调试时,您实际上可以更改代码并继续运行,而无需重新编译。随着编译器和IDE的进步,使用动态语言的这种优势和其他优势可能会消失。
答案 13 :(得分:6)
啊,当我发布similar question
时,我没有看到这个主题除了这里提到的关于动态语言的其他人的好功能之外,我想每个人都会忘记一个,最基本的东西:元编程。
编程程序。
在编译语言中很难做到,一般来说,例如.Net。为了使它工作,你必须制作所有类型的mambo jumbo,它通常以运行速度大约100倍的代码结束。
大多数动态语言都有一种方法可以进行元编程,这使我无法在内存中创建任何类型的代码,并将其完美地集成到我的应用程序中。
例如,要在Lua中创建计算器,我所要做的就是:
print( loadstring( "return " .. io.read() )() )
现在,尝试在.Net中执行此操作。
答案 14 :(得分:5)
我认为这种论点有点愚蠢:“通常会被编译器捕获的东西,例如拼写错误的变量名称,并将错误类型的值分配给变量,直到运行时才出现”是的作为一个PHP开发人员我直到运行时才看到输入错误的变量,BUT运行时是我的第2步,在C ++中(这是我有经验的唯一编译语言)它是链接和编译后的第3步。
更不用说在我点击保存到我的代码准备好运行之后需要几秒钟,而不像编译语言那样需要几个小时。我很抱歉,如果这听起来有点生气,但我有点厌倦了让我成为二流程序员的人,因为我不需要编译我的代码。
答案 15 :(得分:3)
参数比这更复杂(阅读Yegge's article "Is Weak Typing Strong Enough"以获得有趣的概述)。
动态语言也不一定缺少错误检查 - C#的类型推断可能就是一个例子。同样,C和C ++有可怕的编译检查,并且它们是静态类型的。
动态语言的主要优点是a)能力(不一定必须一直使用)和b)Boyd's Law of Iteration。
后一个原因是巨大的。
答案 16 :(得分:2)
我认为我们需要不同类型的语言,这取决于我们想要实现的目标,或者用它们来解决。如果我们想要一个通过互联网从数据库创建,检索,更新和删除记录的应用程序,我们最好使用一行ROR代码(使用脚手架),而不是使用静态类型语言从头开始编写。使用动态语言可以让人们想起
更接近业务需求的问题,如
无论如何,松散类型语言的一个优点是我们真的不关心它是什么类型,如果它的行为像它应该的那样。这就是我们在动态类型语言中使用duck-typing的原因。这是一个很棒的功能,我可以根据需要使用相同的变量名来存储不同类型的数据。另外,静态类型语言迫使你像机器一样思考(编译器如何与代码交互等),而动态类型语言,特别是ruby / ror,迫使机器像人一样思考。
这些是我用来证明我在动态语言方面的工作和经验的一些论据!
答案 17 :(得分:2)
虽然我不是Ruby的忠实粉丝,但我发现动态语言非常精彩且功能强大。
没有类型检查和变量声明的想法实际上并不是太大的问题。不可否认,你不能在运行时才能发现这些错误,但对于有经验的开发人员来说,这不是一个真正的问题,当你确实犯错时,它们通常很容易修复。
它还迫使新手更仔细地阅读他们正在写的内容。我知道学习PHP教会我更加关注我实际输入的内容,这甚至在编译语言中也改进了我的编程。
好的IDE将为您提供足够的智能感知,以便了解变量是否已被“声明”,并且他们还会尝试为您做一些类型推断,以便您可以知道变量是什么。
使用动态语言可以做的事情的力量真正使我们在他看来如此有趣。当然,你可以用编译语言做同样的事情,但需要更多的代码。像Python和PHP这样的语言可以让您在更短的时间内开发,并在大多数时间内更快地获得功能性代码库。
为了记录,我是一名全职.NET开发人员,我喜欢编译语言。我只在空闲时间使用动态语言来了解更多关于它们的信息,并且作为开发人员更好地自我...
答案 18 :(得分:1)
我对动态语言一般没有多少经验,但我知道的一种动态语言,JavaScript(又名ECMAScript),我非常喜欢。
嗯,等等,这里的讨论是什么?动态编译?还是动态打字? JavaScript涵盖了两个基础,所以我想我会谈论两个:动态编辑:
首先,动态语言被编译,编译只是推迟到以后。 Java和.NET确实编译了两次。一次到他们各自的中间语言,再一次,动态地,到机器代码。
但是当推迟编译时,您可以更快地看到结果。这是一个优点。我喜欢简单地保存文件并快速查看我的程序。
另一个优点是您可以在运行时编写和编译代码 。在静态编译的代码中这是否可行,我不知道。我想它一定是,因为无论编译JavaScript是最终的机器代码和静态编译。但在动态语言中,这是一件微不足道的事情。代码可以自行编写和运行。 (而且我很确定.NET可以做到这一点,但.NET编译的CIL无论如何都是动态编译的,而且它在C#中并不是那么简单)
动态类型:
我认为动态类型比静态类型更具表现力。请注意,我正在非正式地使用术语表达动态类型可以用更少的东西说更多。这是一些JavaScript代码:
var Person = {};
你知道现在是什么人吗?这是一本通用字典。我可以这样做:
Person["First_Name"] = "John"; Person["Last_Name"] = "Smith";
但它也是一个对象。我可以参考这样的“键”中的任何一个:
Person.First_Name
并添加我认为必要的任何方法:
Person.changeFirstName = function(newName) { this.First_Name = newName; };
当然,如果newName不是字符串,可能会出现问题。如果有的话,它不会马上被抓住,但你可以检查自己。这是交易表达能力和安全灵活性的问题。我不介意添加代码来检查类型等,我自己,而且我还没遇到一个给我带来很多悲伤的类型错误(我知道这并不是很多。这可能只是时间问题: ))。然而,我非常喜欢能够随时适应的能力。
答案 19 :(得分:1)
我喜欢静态和动态语言。自2002年以来我参与的每个项目都是一个带有嵌入式Python解释的C / C ++应用程序。这给了我两全其美:
我发现构建系统的静态类型语言和配置它的动态类型语言的混合为我提供了灵活性,稳定性和生产力。
回答“动态语言的热爱是什么?”对我而言,它能够以任何可想象的方式在运行时完全重新连接系统。我将脚本语言视为“运行show”,因此正在执行的应用程序可以执行您想要的任何操作。
答案 20 :(得分:1)
这一切都归结为部分适合特定目标以及什么是共同的个人偏好。 (E.G.这将是一个庞大的代码库,由更多的人维护,而不是一起进行合理的会议吗?你想要进行类型检查。)
个人部分是关于交易一些检查和其他开发和测试速度的步骤(同时可能放弃一些cpu性能)。有一些人正在为这种解放和性能提升而且有一些人正是相反的,是的,它确实取决于你语言的特殊风格。我的意思是,这里没有人说Java可以用于快速,简洁的开发,或者PHP是一种可靠的语言,在这种语言中你很难发现拼写错误。
答案 21 :(得分:1)
因为我认为必须声明盒子的类型是愚蠢的。 类型保留在实体中,而不是容器。当盒子的类型直接影响内存中的位被解释时,静态类型就有意义。
如果你看一下GoF中的设计模式,你就会发现它们中很大一部分只是为了与语言的静态性质作斗争,它们没有任何理由以动态语言存在
另外,我已经厌倦了写MyFancyObjectInterface f = new MyFancyObject()之类的东西。干的原则是谁?
答案 22 :(得分:1)
关于同一主题的好博文:Python Makes Me Nervous
方法签名实际上是 在Python中没用。在Java中,静态 键入使方法签名成为 食谱:这就是你需要的所有东西 使这个方法工作。不是这样的 蟒蛇。这里,方法签名会 只告诉你一件事:多少 你需要让它运作的论据。 有时,如果是,它甚至不会这样做 你开始他妈的 ** kwargs。
答案 23 :(得分:1)
让自己选择一个全新的程序员选择一种语言开始,谁不关心动态与staic对比lambdas与此对比等等。你会选择哪种语言?
C#
using System;
class MyProgram
{
public static void Main(string[] args)
{
foreach (string s in args)
{
Console.WriteLine(s);
}
}
}
的Lua:
function printStuff(args)
for key,value in pairs(args) do
print value .. " "
end
end
strings = {
"hello",
"world",
"from lua"
}
printStuff(strings)
答案 24 :(得分:1)
答案 25 :(得分:1)
特定背景下的生产力。但这只是我所知道的一个环境,与我所知道或曾经使用过的其他环境相比。
对于复杂的应用程序,在Squeak / Pharo with Seaside上的Smalltalk是一个比ASP.Net(/ MVC),RoR或Wicket更有效和高效的Web平台。直到你需要与其中一个库中的库有联系但不是小代码的东西。在IDE中,拼写错误的变量名称为红色,IntelliSense可以正常工作但不具体。网页上的运行时错误不是问题,而是一个功能,只需单击一下即可打开调试器,单击一下IDE,修复调试器中的错误,保存,继续。对于简单的错误,此循环的往返时间少于20秒。
答案 26 :(得分:1)
FWIW,对大多数应用程序进行编译不应该花费数小时。我使用过200-500k行的应用程序,需要几分钟才能编译。当然不是几个小时。
我自己更喜欢编译语言。我觉得好像调试工具(根据我的经验,可能不适合所有事情)更好,IDE工具更好。
我希望能够将Visual Studio附加到正在运行的进程中。其他IDE可以这样做吗?也许,但我不知道他们。我最近一直在做一些PHP开发工作,说实话,它并不是那么糟糕。但是,我更喜欢C#和VS IDE。我觉得我工作得更快,并且可以更快地调试问题。
所以对于我来说,它可能比动态/静态语言问题更重要吗?
最后一条评论......如果您使用本地服务器进行开发保存比编译更快,但通常我无法访问本地计算机上的所有内容。数据库和文件共享在其他地方。 FTP到Web服务器更容易,然后运行我的PHP代码只是为了找到错误,必须修复并重新ftp。
答案 27 :(得分:1)
我认为这两种风格都有其优点。在我看来,这种或/或思考都会对我们的社区造成严重影响。我曾经在从上到下静态打造的架构中工作,这很好。我最喜欢的架构是在UI级别动态输入,在功能级别静态输入。这也鼓励了一种语言障碍,迫使UI和功能分离。
要成为一个愤世嫉俗的人,可能只是动态语言允许开发人员更懒惰,并且更少了解计算的基础知识。这是好事还是坏事取决于读者:)
答案 28 :(得分:0)
弱类型语言可以灵活地管理数据。
我在去年春天使用VHDL用于几个类,我喜欢他们表示位/字节的方法,以及如果你尝试将6位总线分配给9位总线,编译器如何捕获错误。我试图用C ++重新创建它,并且我正在努力整齐地让打字与现有类型一起顺利运行。我认为Steve Yegge在描述强类型系统所涉及的问题方面做得非常好。
关于详细程度:我发现Java和C#在大型中非常冗长(让我们不要挑选小算法来“证明”一点)。而且,是的,我写过两者。 C ++在同一领域也在挣扎; VHDL在这里屈服了。
Parsimony似乎是动态语言的优点(我以Perl和F#为例)。
答案 29 :(得分:0)
理论上,静态类型语言可以获得动态语言的好处,理论上,动态语言也有可能吸引并引起更多头痛而非快乐。
然而,实际上,动态语言允许您快速编写代码,而无需过多的样板,而不必担心低级别的细节。
是的,从理论上讲,c风格的语言可以提供类似的功能(D尝试,使用auto
类型发现和dmdr
编译模块并在运行时运行它们,就好像它们是脚本一样),
所以是的,反对者是正确的,因为动态不是必然意味着更容易/更清洁的代码。
但,实际上是Python > Java
在C中尝试w = "my string here".split()[1]
,甚至是Java。
答案 30 :(得分:0)
对我来说这是一个情况问题。我花了很多时间为网站编写Perl代码,为图形引擎编写C ++代码。两种完全不同的编程领域,有两种截然不同的语言。
动态语言对我来说无论如何都要更快,因为我花更少的时间来确保框架到位,而更多的是关于手头的实际问题。
然而,静态语言提供了更精细的控制,这在某些应用程序(如实时图形渲染)中是必需的。我可以用C ++做的事情比我为Perl写的更有效,更快,但对于大多数Perl脚本的大小,效率的损失可以忽略不计。
最后,它真正归结为问题陈述以及您的目标目标。如果您有很多简单的事情要做,速度和内存效率不是很大,请使用动态语言。如果你有一个需要从系统中挤出最后一个周期的巨型项目,那就去静态。
答案 31 :(得分:0)
因为这很有趣,很有趣。一个人不用担心内存分配很有趣。不等待编译很有趣。等等等