动态语言——披着彩衣飞舞的脚本语言

 

故凡天下之理,欲向动上求静,静上求动            ——《蔡牧堂·发微论》
关键词:      动态语言,静态语言,脚本语言
摘要:   动态语言简谈
 !预览
·           程序是为终端用户服务的,而脚本是为程序员服务的
·           动态语言秉承的一个理念是:优化人的时间而不是机器的时间
·           待静态语言披盔戴甲、备马抬枪之际,动态语言已衣袂飘飘,长剑出手了
·           当脚本语言披上动态语言的彩衣,昔日不起眼的毛毛虫便羽化成碟,开始飘舞在众人追逐的目光之中
  ?提问
·           脚本与程序的区别是什么?
·           脚本语言有什么特点?为什么适合作粘合语言?
·           动态语言有什么特点?它与脚本语言究竟有什么分别?
·           动态语言也能用于大型应用开发吗?
·           动态语言会最终取代静态语言吗?
:讲解
叹号急不可耐地问:“现在可以谈动态语言了吧?”
冒号感言:“曾几何时,动态语言还只是陪太子读书的角色,那时候它们的名字是‘脚本语言’。近来却迅速崛起,俨然有与静态语言分庭抗礼之势。”
问号忍不住问道:“动态语言与脚本语言是一回事吗?”
“相比动态语言定义上的模糊,脚本语言的概念还是比较明确的。”冒号回避直接给出答案,“脚本(script)的提法,是为了区别于一般的程序(program)。Perl的发明者Larry Wall不愧为语言学家,对此有一个精彩的说法:‘A script is what you give the actors,a program is what you give the audience’。直译为:脚本是给演员看的,节目是给观众看的。此言妙在一语双关——program兼有‘节目’和‘程序’的意思。”
句号领会其意:“这里的演员指的是程序员,观众指的是用户。换言之,程序是为终端用户服务的,而脚本是为程序员服务的。”
“正解!”冒号肯定道,“脚本最常见的形式是壳脚本(shell script),在非Unix类的操作系统中也称为批处理文件(batch file)。”
“批处理文件倒是很熟悉,壳脚本听起来就怪怪的。”逗号嘀咕着。
“那是因为你在Windows的世界里长大,听不惯Unix的方言。”冒号一语道破缘由,“操作系统的内核称为核(kernel),出于安全考虑不便直接与用户交互,因此裹上一层壳(shell),即人们常说的命令行解释器(command line interpreter)。壳脚本是在壳上运行的脚本,扩展了命令行下可执行的命令。它最初主要是内建(built-in)命令的组合,用于系统程序的调度,是系统管理员的必备武器。其后,壳脚本也发展到用于应用程序的调度、连接、调试等,成为粘合(glue)语言。”
逗号不禁有些疑问:“难道一般的程序语言如C之类的不能作此用吗?”
引号回应道:“这些语言通常需要‘编写-编译-链接-运行’的循环过程,十分繁琐。脚本语言编写后即可运行,快捷方便得多。”
冒号点点头:“不错,既然脚本主要用于整合其他程序,本身并不占用太多的资源,同时逻辑也不太复杂,因此脚本语言注重简洁、实用,语法要求不那么严格,性能上的要求也不高。除壳脚本外,还有一些专用于文本处理(text processing)的语言或工具如AWK、sed和grep等,多用于读写配置文件和日志文件、过滤处理各种程序的输入和输出,对于整合各种程序也非常实用。随着对脚本语言需求的增长,其局限性日益突出,以Perl为代表的高级脚本语言便应运而生了。Perl在壳脚本、AWK、sed的基础上,融合了命令式的C与函数式的Lisp的特征,渐渐成为最流行的脚本语言之一。”
问号注意到:“JavaScript是浏览器端的脚本,来路似乎有些不同。”
冒号解释道:“除了命令行程序外,脚本语言在其他的应用程序中也身影频现,如图形界面应用、多媒体应用、网络应用等。尤其是网络应用,成为滋生和繁荣脚本语言最肥沃的土壤。例如:Perl非常广泛地用于网络服务器端的CGI编程;PHP更是专为动态网页而设计的语言;Ruby虽与Java同岁,但真正开始风行得益于网络应用框架Ruby on Rails的成功;至于JavaScript,长期被边缘化为网页设计人员的语言,是web2.0的新宠AJAX真正将其带入程序员的视线。”
逗号有些好奇:“什么时候脚本语言变成了动态语言呢?”
“尽管动态语言并无确切的定义,但不是所有的脚本语言都能称作动态语言的——比如Bash之类的壳脚本语言(shell script language);另一方面,也不是所有的动态语言天生就是为脚本服务的——比如Lisp[1]。不妨这么理解,脚本语言以语言的实际用途为标志,动态语言以语言的语法特征为标志。”冒号回答,“单从用途上看,一个脚本语言如果不再局限于命令行工具和粘合工具,从专用语言发展为通用语言,并能胜任复杂的应用开发,或许更有资格归为动态语言。”
句号发现:“动态语言似乎对字符处理都特别擅长。”
冒号道:“脚本语言与一般程序一个不同之处是,它一般是面向字符而非数值的,因为字符是最通用的接口,正好发挥其粘合作用,而数值运算对性能要求较高,多由核心程序来完成。动态语言继承了这个特点,并且除了正则表达式(regular expression)外,为字符串、数组、列表、集合、映射等常用结构提供了丰富简洁的运算,远比静态语言依赖于库(library)的方便自然得多。”
叹号问:“我们清楚了脚本语言中‘脚本’的来历,那动态语言中‘动态’又体现在何处呢?”
“问得好!”冒号闻言,正中下怀,“再从用法上看,动态语言能在运行中增加或改变数据结构、函数定义、对象行为或指令流程等。如果说动态类型语言的动态体现在类型上,动态语言的动态则体现在结构和功能上。相比而言,静态语言虽然也可能实现同样的效果,但既不方便也不自然[2]。另外不容忽视的一点是,动态语言大多是开源的,其本身的发展也更具动态性。”
引号非常注重理论:“动态语言的语法特征有那些?”
“动态语言秉承的一个理念是:优化人的时间而不是机器的时间。为提高人的生产率,宁肯牺牲部分的程序性能或者购买更高配置的硬件。由于硬件相对于人件一直在贬值,该理念便有了合理的现实基础。”冒号讲述着,“从语法上看,动态语言为了更好地粘合来自不同系统、不同语言的程序,对类型的要求一般不如静态语言那么严格,代码更加简洁自由,故而多为动态类型的和弱类型的,天然支持泛型式编程。当然这不是绝对的,比如Groovy也支持静态类型,Scala完全是静态类型的,Python一般认为是强类型的。大多数动态语言支持eval函数,能动态执行任意字符串形式的代码,并有丰富的反射(reflection)机制,天然支持元编程。动态语言很多还支持包括高阶函数(high-order function)和闭包(closure)等在内的函数式编程。此外,大多动态语言也支持对象式编程,如Python、Ruby、Perl 5、PHP 3等。”
句号补充道:“许多动态语言还支持过程式编程和并发式编程,简直把主要的编程范式一网打尽了!”
“其实Python、Ruby和Groovy等还可以进行切面式编程,这对于支持元编程的动态语言来说非常自然,因为切面式编程一般都是通过元编程来实现的。”冒号进一步指出,“而逻辑式编程语言的代表Prolog,同样有动态语言的特征。至于事件驱动式编程嘛,对支持callback的语言来说都不是难事。”
引号高兴地看到:“九大编程范式无一漏网啊!”
叹号较为感性:“静态语言给人的感觉是沉稳持重,而动态语言则活泼轻快。如果同时用静态语言和动态语言编程,岂不培养出双重人格?”
“程序员本就是双重人格的。”冒号淡淡地说,“你总结得没错,两类语言的风格的确大相异趣:待静态语言披盔戴甲、备马抬枪之际,动态语言已衣袂飘飘,长剑出手了。不过,如果是应付强敌的长期大规模作战,静态语言还是有优势的。”
引号听声辨音:“这意味着动态语言不适用大型应用开发吗?“
“这么说未免有些武断。”冒号并不同意,“诚然,动态语言的语法比较宽松,相对容易出错。但也有人辩称,动态语言的代码量少于相应的静态语言,bug应该更少。有人认为动态语言调试不如静态语言方便,有人却说随着IDE的日益强大,出错几率和找错成本也在减少。谈到运行效率,动态语言虽然多为解释型语言(interpreted language),但许多也提供了与Java类似的字节码编译(bytecode compilation)甚至JIT编译(just-in-time compilation)。动态语言在某方面甚至还更胜一筹:譬如一个类的接口如果发生变动,在静态语言中所有该类的子类和一些相关类都可能需要重新编译、连接,这在大型应用中是非常耗时的,而动态语言则大可不必,这当然不足为奇——在它眼里类结构本来就是能动态改变的。除此之外,越是大型的程序,越耗费人力和时间成本,客户需求的变化也越大,因而对程序的灵活性、适应性和开发周期提出了更高的要求。动态语言在这些方面比静态语言更有优势,并且还能作为快速原型(rapid prototyping)开发的工具。”
“快速原型开发?”问号一脸的疑惑。
冒号简作介绍:“这是一种软件开发的方式。举例来说,为了快速搭建一个系统,以适应不断变化的客户需要,可以先采用开发效率更高的动态语言。在交付时再将其转化为编译型的静态语言。如果系统对性能的要求不高,这种转化至多是局部的。有的干脆一字不易,不仅省了当下的时间,以后维护起来也更方便。”
逗号耍起了贫嘴:“这就叫:替补变成了主力,配角变成了主角,媳妇熬成了婆婆。”
叹号开始担忧起来:“听您这意思,动态语言优点突出而弱点并不突出,这样下去静态语言还有市场吗?”
冒号坦然道:“动态语言小快灵的风格的确吸引了越来越多人的注意,也渐渐走入静态语言的世界。Java平台和.Net平台不仅为Ruby和Python等动态语言铺设了跑道,而且为培植诸如Groovy等动态语言提供了土壤。同时,Java和C#本身也融进了越来越多的动态特征。”
句号断言:“静态语言这种融合性结合内在的安全性、稳定性,以及较高的性能、成熟度和接受度,都决定了它不可能被动态语言完全取代。”
“对!”冒号坚定地表示赞同,“当脚本语言披上动态语言的彩衣,昔日不起眼的毛毛虫便羽化成碟,开始飘舞在众人追逐的目光之中。但静态语言也绝不会淡出人们的视线,它如矫健的苍鹰,依然有搏击长空的雄力。程序员只要保持严谨的作风和开放的心态,既有稳如泰山的马步,又有一跃凌空的飞腿,静如处子,动如脱兔,如履平地般游走于高高的梅花桩上,绝无跌落之虞。”
一股豪情在众人心中荡漾开来。
冒号看了看时间,敛起眼中精光,同时收起话匣:“关于动态语言,今天还是先简单谈到这里吧。”
 
,插语
[1] Lisp本身以及一些变种如Emacs Lisp、AutoLISP等也能作为脚本语言,但那毕竟不是Lisp语言的初衷。
[2] 一些设计模式(如装饰模式、访问者模式等)就是为了赋予静态语言一定的动态特征。
。总结 
程序是为终端用户服务的,脚本是为程序员服务的。 脚本语言一般是解释型语言,不需要通过“编写-编译-链接-运行”的循环圈,便利快捷,加之简洁宽松的语法、面向字符的特性以及较强的文本处理能力,尤其适合作为粘合语言,多用于系统管理和集成。 脚本语言与动态语言尽管并不完全重合,但更多地还是提法上的区别。前者强调作为命令行工具和粘合工具的语言用途,后者强调动态的语言特征。当脚本语言不再局限于粘合语言,从专用语言发展为通用语言,并且胜任复杂的应用开发的时候,动态语言的提法显然更加合理。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


背景:    8月29日,凌晨4点左右,某服务告警,其中一个节点直接down掉,收到告警的同事让运维重启。    9点左右,内存监控上发现内存异常,堆内存涨速很快,即便GC也没有什么效果,频繁GC。    9点38,服务各种超时,影响整个app使用。处理方式:    当时由于很想要
https://support.smartbear.comeadyapi/docs/soapui/steps/groovy.htmlGettestcaseobjectToobtaintheobjectwhichreferstothecontainingtestcase,usethefollowingcodesnippet:Groovy def case=testRunner.testCase; Byusingthe tes
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能。查看最流行的扩展机制,比较性能并分析哪一个是最好的。  这是乐队之战,JMeter风格。 BeanshellV.JSR223V.JavaRequestSampler 在我们之前的帖子中,  JMeterPerformance和TuningTips  ( 由fantastik
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,同时支持面向对象Groovy:jvm上的脚本,较好兼容java语法,Groovy加强了Java集成。 可配置化的优势,可以将一些简单的逻辑公开给外部编辑和使用,增强了互操作性,复杂逻辑来说,可配置化代码的调试则会比较麻烦 Scala和Java
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部元件的访问testRunner.testCase开头1、向下访问testRunner.testCase.testSteps[testStepName]testRunner.testCase.getTestStepByName("新增一个空间")2、向上访问,用于访问同一项目中的其他testSuites和testCase下
在运行groovy的junit方法时,报了这个错误:java.lang.ExceptionInInitializerError atorg.codehaus.groovy.reflection.ClassInfo.isValidWeakMetaClass(ClassInfo.java:271) atorg.codehaus.groovy.reflection.ClassInfo.getMetaClassForClass(ClassInfo.java:241) atorg.codeha
基本语法1.Grovvy的注释分为//和/**/和java的一样.2.Grovvy语法可以不已分号结尾.3.单引号,里面的内容严格的对应java中的String,不对$符号进行转义.defs1='iamastudent$'printlns1iamastudent$4.双引号“”的内容中如果有$号的话,会先对表达式先求值.de
Tiobe发布了最新一期(3月份)编程语言欢迎度榜单,其榜单根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube统计出排名数据。TOP5几乎没有变化,Java和C语言牢牢占据前两名。Python相较去年上升一位进入TOP3,C++下
我有一个Google地图组件,作者可以在其中指定纬度和经度.我正在使用带有正则表达式的常规“输入”类型控件来验证它们是否是数字,但是,当试图解决指定范围的问题时(经度验证该值在[-180,180]内并且纬度[-90,90])但是,通过正则表达式进行验证似乎很麻烦,而且利用inputtype=“numb
我正在为未来的应用程序评估SpringBoot,并希望使用Groovy模板来实现其纯粹的可读性.不幸的是,我在迭代我添加到控制器返回的ModelAndView对象的对象列表时遇到了麻烦.这是我的控制器:@RestController@RequestMapping("/ships")publicclassShipsController{@Autowired
我有一个基于Spring的java应用程序,其中包含一些有用的组件.作为系统的一部分,我有一个groovy脚本,来处理一些报告.我想从groovy脚本中调用spring组件.当我用Java编写时,我需要在@Component中使用@Autowired注释,即@ComponentclassReporter{@AutowiredSearchServicesearchS
在Grailsi18n插件definedthusly中定义了一个messageSourcebean:messageSource(PluginAwareResourceBundleMessageSource){basenames=baseNames.toArray()fallbackToSystemLocale=falsepluginManager=manager....}是否可以覆盖我的resources.groovy中的fa
我正在寻找一种方法来反向工程RDBMS表(MSSQLServer)并生成JPA@EntityGroovy类.我们目前没有选择使用Grails和/或GORM,因此Grailsdb-reverse-engineer插件似乎很接近但不太正确.它生成符合GORM的类而不是JPA实体类.我们目前有一个gradle构建,它利用org.hibernate.tool.ant.Hibe
https://blog.csdn.net/Gdeer/article/details/83062523一、直接运行groovy程序因为groovy插件和android插件不兼容,所以不能在原始项目上使用groovy。 新建module,创一个JavaLibrary,取名lib。  修改lib/build.gradleapplyplugin:'java-library'depe
一、自动生成GET请求脚本1、配置Createascript在ngrinder管理台主页,点击script–>Createascript,并填写脚本名称和请求的url,如下所示:点击Create按钮,nGrinder会自动生成对应的脚本结构,如果没有参数需要设置的话,可以直接运行了。二、详细解析GET请求脚本ngrinder自动生成的脚本
我正在关注使用列表和地图作为构造函数的this博文.为什么以下列表无法强制反对?classTest{staticclassTestObject{privateinta=1;protectedintb=2;publicintc=3;intd=4;Strings="s";}stati
Information:java:Errorsoccurredwhilecompilingmodule'security'Information:javac1.8.0_131wasusedtocompilejavasourcesInformation:2019/6/98:31-Buildcompletedwith1errorand0warningsin3s116msError:java:读取E:\repository\org
ngrinder中的groovy脚本结构类似junit,同时在junit的基础之上封装了自己的注解,用来控制脚本的运行。一、运行逻辑图如下:此处只列出了groovy脚本的逻辑,jython脚本是类似的,在此不再单独介绍。二、各注解的使用比较三、关注点在ngrinder中,通常使用单进程多线程就足够大部分测试了,所以:
我有一个switch语句来处理javaenumfoo,并使用spock编写一些groovy单元测试.我已经添加了一个测试,它验证当前是否处理了每种类型的foo而没有抛出异常.现在我想测试一个无法识别的foo类型会导致抛出异常.要做到这一点,我将不得不嘲笑枚举,并已经看到这里概述的解决方案:MockingJ
我有一个groovy实体ClientInvoiceAttachmentExt,它扩展了java实体ClientInvoiceAttachment.ClientInvoiceAttachment具有@Id注释,但仍然看到“没有为实体指定的标识符”错误这是我的堆栈跟踪[Mar0317:11:54]ERROR|org.springframework.web.context.ContextLoader|Contex