在较大的程序中使用脚本语言什么时候有用?


70

我听说过几种情况,人们在用C#编写的程序中使用JavaScript或Python(或诸如此类)。什么时候使用JavaScript这样的语言在C#程序中做某事比在C#中做某事更好?


1
为什么有人会否决这个问题?恕我直言,这是一个很好的问题。
KK。

28
这对于制作需要昂贵顾问来维护的极其复杂的软件非常有用,尤其是在脚本语言很糟糕的情况下。
whatsisname 2013年

2
我没有一个“答案”,但是说实话程序员对此有一个章节(第12章-领域语言)。可能会为您提供一些见识。
Craige

1
关于游戏开发的类似问题也有一些不错的答案:gamedev.stackexchange.com/questions/2913/…–
celion

6
有时脚本语言中拥有大型系统甚至更好-这被称为“ Unix之道 ”。您可以使用一个很小的脚本层将众多不同的子系统粘合在一起。已知该体系结构非常健壮和可扩展。
SK-logic

Answers:


66

如果您有某些行为,则不必为了进行更改而不必重新编译程序。这就是为什么这么多游戏将Lua用作脚本/修改语言的原因。


42
而且,用户也可以自己添加功能。您有点暗含,但我认为它很重要,值得进一步强调。

2
也沙箱。查看Blender与Python的集成。
meawoppl

@meawoppl ...或为程序添加功能。看看IDA对Python的集成(称为IDAPython)
Cole Johnson

为什么不这样做,以便只需要重新编译一个库(例如,使用特定的游戏逻辑组件)?
2013年

如果您查看其他工具,例如AutoCAD,Sparx Enterprise Architect,MS Word,则无需重新编译它们即可在C#中编写脚本。
Pete Kirkham

28

此技术可用于实现可在不同语言环境之间轻松移植的核心逻辑。例如,我有一个计算器模拟器,其中所有内部计算器逻辑均以100%JavaScript实现。每个平台的用户界面代码当然是不同的:

  • 网页浏览器(JavaScript)
  • iOS(Objective-C)
  • Windows(带有Qt的C ++)
  • Mac OS X(带有Qt的C ++)
  • Java Swing(Java)

通过这种安排,使我的程序版本适合不同的操作环境,尤其是使其保持最新状态,变得更加容易。


18

从广义上讲,您将在两种情况下应用此模式:

  1. 在内部使用它来利用嵌入式语言的某些质量。
  2. 这用于提供外部可编程性。

内部地

  • 通常情况下,将对嵌入式语言进行解释,从而无需重新编译即可快速进行更改和测试。
  • 嵌入式语言可能比您的核心应用程序所编写的语言更具表达力,从而再次加快了开发速度。
  • 与通用语言相比,该语言可能更适合某些特定领域
  • 该语言由需要“简单”编程语言/环境的内部用户使用。短程序是由非软件开发人员使用相对简单的语法/ API编写的。

这里的一个示例是Adobe Lightroom中使用的Lua。

因此,从本质上来说,我们使用Lua所做的就是从运行UI到管理我们在数据库中实际所做的所有应用程序逻辑。在应用程序中几乎所有可被描述为决策或实现功能的代码都在Lua中,直到您进入C ++中的原始处理为止。(马克·汉堡访谈:Adobe Photoshop Lightroom

在外部

  • 允许用户扩展应用程序的行为,而无需特殊的工具和/或库和/或访问您的源代码。
  • 为这些用户提供定义良好的API和沙盒环境。也可以使用应用程序的语言来完成此操作,但是嵌入解释器可以使此操作更容易。

IBM在大型机操作系统VM-CMS中非常成功地使用了脚本语言。 EXECEXEC / 2和更高版本的Rexx在内部和外部整个系统中使用。可以使用相同的语言编写不同的应用程序(例如XEDIT),并以脚本语言编写内部应用程序/实用程序(例如E-mail),并利用与OS和其他工具的紧密集成。客户创建并共享了许多脚本化工具和应用程序。DEC还提供了DCL。后来,Microsoft 在大多数应用程序中以及最近的PowerShell中将VBscript作为脚本语言支持(也是MS / DOS 批处理文件)。Unix shell也具有脚本

当今的趋势似乎是以某种方式公开API,而脚本语言的选择权留给了可以利用不同绑定或其他方式访问API的用户。


9

真实的例子包括:

  • 大多数将支持嵌入式JavaScript的Web浏览器。

  • Microsoft Office Suite-Excel Word等均支持嵌入式VBA脚本。

  • 许多网络路由器都以多种语言包括TCL,Perl和Lua包含脚本API。

许多嵌入式设备使用非常少的一组核心C函数来实现,这些核心C函数使用脚本语言(例如Lua)粘合在一起。因此,您具有一组小的,快速的C函数,这些函数与硬件交互,并且大多数控制逻辑都以灵活,易于修改的脚本语言来实现。


@ antony.trupe。通常用来指ECMAscript的名称-en.wikipedia.org/wiki/ECMAScript
James Anderson

4

有时,脚本嵌入在应用程序中,因为这是其他开发人员扩展主机应用程序的一种方式。为了捕获尽可能广泛的编程语言技能,主机可以支持多种脚本语言。例如,在JVM上,您可以嵌入整个JSR-223兼容语言,包括Python,Ruby,JavaScript等。

尚未提及的另一个原因是,嵌入式语言具有一个或多个出色的功能,宿主语言无法轻松复制这些功能。这样的一个例子是解析功能或轻松创建DSL(特定于域的语言/方言)的方法,可以在像Rebol这样的语言中找到它。


3

有一种有趣的方式可以在应用程序内部使用脚本语言,而其他方法尚未提及。

如果您的宿主语言具有丰富的反射式运行时,通常将REPL嵌入一种简单的语言到您的应用程序中,然后将其挂在套接字上,并使其可以访问整个系统通常会很有用。

它可以用于交互式调试(自然比常规调试器功能强大),热代码修补,各种监视目的甚至后门(如果您不擅长)。


自然比您通常的调试器强大吗?用什么方式?没有宿主语言的惯用法,内存模型,对象模型,基本数据类型等内在知识的“简单外部脚本语言”怎么可能提供调试器无法使用的有用工具?
梅森惠勒

@MasonWheeler,您可以使用常规调试器热交换代码吗?您可以执行有关运行时状态的任意复杂的可编程查询吗?您可以执行复杂的受控实验吗?而且您认为脚本语言没有“宿主语言惯用法的内在知识……”是错误的。如果主机和脚本语言都在同一VM(.NET,JVM,V8等)中运行,则可以从您的脚本语言完全访问所有内脏。
SK-logic

1

在主要应用程序中使用解释性脚本语言时,我的具体情况是:

有一个执行多种功能的外部设备。测量,控制,读数。它本身很“笨拙”,需要逐步进行精确控制,包括许多等待状态和控制机制方面的临时决策。

在主要应用的不同时间,不同时间通常需要按需提供设备的各种功能。主应用程序不允许等待状态,因此必须使用有限状态机完成所有操作。

现在,无论谁写了一个有限状态机,都知道实现一个等待状态实际上是至少两个,通常是三个或四个内部状态。为外部设备的各种功能实现二十个等待状态(并等待它们的响应并做出相应的反应)将是非常非常令人沮丧的体验。

因此,在有限状态机中存在“执行无等待功能”,“执行阻止功能”,“执行分支/条件/跳转”功能的状态,总共可能有六个状态。并且有一些控制脚本要安排执行时间,然后由控制外部设备的解释器执行,并将其结果放在需要的位置。

总结一下应用程序:在RTOS中,使用内部解释的脚本语言可以极大地降低执行等待状态(阻塞功能)中的任务的复杂性。


1

根据我的经验,我们曾经开发过一个大型应用程序,该应用程序确实将“古老”语言的源代码重写为与unicode兼容。是在C#中完成的。我最终只用C#编写了引擎(该引擎创建了数据模型,并提供了执行重写过程所需的步骤的方法)-实际执行操作的“胶水代码”是在IronPython中完成的。

集成IronPython的最大优点是:假设您加载了一个大数据模型(大约一小时的加载时间)。然后,您想-手动-收集信息并查找内容。从交互式控制台使用Python脚本执行此操作远比使用调试器单击数据模型要好得多(此外,它是可重播的)。


-2

有几个原因。

  • 学习曲线。几乎每个人都可以使用javascript学习和写作。
  • 安全。用C#或Java很难控制脚本代码的安全上下文。Javascript是完美的。脚本作者永远无法访问磁盘或任何不允许访问的地方。核心javascript引擎只是一个高级计算器。
  • 质量。您对脚本代码设置了非常严格的限制。对于Javascript或C#/ Java,“意大利面条代码”级别有很大不同。(这会阻止您打开地狱之门)
  • 类型安全。C#/ Java是类型安全的环境,您通常不希望在脚本环境中使用它。像“ 12” + 3这样的表达式在javascript中为“ 123”,但C#/ Java甚至无法编译。脚本编写者甚至根本不了解“类型”
  • 动态。任何对象都可以包含任何属性/方法,并且可以及时更改其类型。例如,我可以为脚本环境提供一个代理C#对象,该对象将XML节点公开为属性。
  • 生产率。通常,编写脚本要比C#/ Java简单得多。无需编译或“插件注册”。您可以直接在应用程序中编辑脚本内容并立即获得结果。
  • 管理。使用C#/ Java要求将SDK链接到将内部类公开的插件上。对于旧版本的SDK,此插件体系结构需要“向后兼容”。这种体系结构迫使您创建“虚拟”域对象,该对象提供域上下文中应用程序的内部机制。比公开API更可管理/灵活。

3
这惦记嵌入脚本的问题点较大的程序。例如,为什么一个开发人员会选择将script-fu添加到gimp?或者使用lua修改Civ V-为什么开发人员会选择向应用程序添加脚本?

-3

什么时候?从1948年到2008年-最初编译的语言花费了大量时间进行编译和链接,因此创建脚本语言以允许用户自定义和配置是司空见惯的。如果您查看AutoLisp的历史,那么答案是AutoCAD最初附带了脚本语言,但是为了支持向VBA和.net公开脚本化的界面,已逐步淘汰了AutoCAD。

使用CLR,在现有系统中启用C#程序或Lua程序调用的开发成本没有显着差异,并且.net运行时附带了可即时生成和编译的工具。

您不再需要大型程序中使用脚本语言,而是将大型程序暴露给运行时的脚本工具。

在不提供动态代码生成和编译功能的环境中,并且希望提供一种通用的自动化语言,而不是提供特定领域的语言,仍然可以使用Lua或Python脚本。对于提供COM接口的工具,该脚本语言将为C#或VB.net(MS Office,Sparx Enterprise Architect)。因此,没有必要使用一种语言编写程序的脚本语言,而该语言本身足够简单即可成为脚本语言。


用Google搜索Lua可编写脚本的XNA游戏不会显示零结果。
user16764

@ user16764和一个Google搜索的蛋白酥皮制成的自行车的搜索量为600万。
Pete Kirkham
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.