精华内容
下载资源
问答
  • 5.3.3计算机语言的特点语言处理系统分为解释器和编译器两种。解释器就是对源程序的语句解释一条执行一条,编译器则是先将源程序转换成机器语言,然后由CPU直接运行机器语言。编译型语言比解释型语言快5-20倍,而且...

    5.3.3计算机语言的特点

    语言处理系统分为解释器和编译器两种。解释器就是对源程序的语句解释一条执行一条,编译器则是先将源程序转换成机器语言,然后由CPU直接运行机器语言。编译型语言比解释型语言快5-20倍,而且编译时还进行程序语法检查,所以正式的程序都用编译型语言编写。

    不过,解释型语言属于对话运行方式,不需要编译和连接,且容易调试,故在编写小型程序时显示出很大的优点。特别是Sh, Perl等外壳语言或脚本语言,也称为胶水(用胶水粘在一起)语言,可方便地用于将其他编译型语言编写的组件程序组合起来一起运行。

    下面讲解C/C+ +, Lisp, Java及其他语言的特点,并说明它们与机器人软件所要求的四个功能之间的关系。

    1. C/C++语言[1]

    在编写Unix系统后C语言的可用性得到证实,随后于20世纪70年代作为微型和小型计算机高级语言被普及。既然能够编写操作系统,就应该能够对输人输出设备实现控制和中断处理,因而也就能够满足机器人硬件层面的控制要求,而比特、字节等数据类型的使用,提高了存储器的使用效率。C语言是函数型语言。函数定义属于一级定义,因此难以对变量名和函数名的作用域进行详细的控制。但是,由于作用域规则比较简单,容易掌握,因而很快获得普及。同时,表达式和语法功能较为简单,语句所对应的机器语言容易想象,故也适宜于设备的控制。

    C语言应用于大规模系统时的不足之处在于它只能在一级函数的水平上进行抽象。为了弥补这丫不足,宏的应用逐渐.增多,因而/usr/include作为头文件日益增加,程序开头附上#include语句也越来越多。由于宏的组装非常巧妙,所以维护起来也比较困难。究其原因,主要是C语言的抽象化水平较低所致。为此,20世纪80年代诞生了面向对象的C++语言[2]。由于类定义具有了继承性,且能够分别定义对象内部的名字和对外公开的名字,从而极大地促进了软件的商品化和可重复利用性。后来,C语言还成为了ANSI标准,且通过POSIX实现了库的标准化。

    C++是C语言的主语言,无论是C编写的源程序、C++编写的检查程序、C++编写的多重继承和假想类,都能够在C++环境下正常运行。对于已经熟练掌握C的程序员来说,掌握起来很容易。但也正因如此,使得C++停留在“更加合理的C',的水平,无法充分发挥C十+的功能,机器人用的很多类库都难以得到。

    C++是面向目标的语言,与C一样,它也没有存储器自动管理功能.因此,如果稍加留意,在编写实时程序时可以不作异步无用单元收集的处理。不过,如果此时程序员对存储器实施管理不善,容易出现内存溢出(memory leak)的现象。

    C/C++的编译器可以生成机器语言的效率很高,因而在诸如模式识别、矩阵等数值计算、几何运算等方面能最大限度地发挥功能。它尽管也能够描述几何模型或者比较复杂的结构,不过一般常用的方法是在程序的开头定义连接表处理程序,即定义mini lisp。

    Unix的操作系统中已经嵌人了C/C++的开发环境,故在Unix上进行程序开发的效率最高.GNU的C编译器属于retargettable构造,库的源代码中也提供开放版源代码,因而能较为容易地构筑交叉开发环境,编写出易于嵌人到目标设备中的代码。

    2.Lisp [3]

    Lisp作为面向人工智能语言,于20世纪50年代开始应用。其特点在于将程序和数据均作为连接表来处理,易于进行解释执行。现代Lisp的标准Common Lisp中已经拥有完备的编译器,不仅数据类型可以列表,还具有多精度数值、数组等基本数据类型,以及可由用户定义的扩展数据类型。现在,基于CLOS(Common Lisp Object System)的面向对象扩展功能也成为一种标准。

    Lisp程序都是先编译成机器语言然后再执行的。不过通常程序开发都采用解释器来进行,甚至已经编译完的程序也可以用来作为运行库充当解释器。Lisp处理系统对存储器的管理是完全自动的,但是需要的自由空间至少是最低使用空间的2倍。因此,Lisp的程序执行系统很大(10M以上),无用单元收集大约占用数十毫秒以上的停顿时间,因而不适宜于嵌人到机器设备中执行伺服等实时控制。

    Lisp属于通用语言,可用于Emacs, Web等服务器,但真正能够体现价值之处在于人工智能的识别程序、几何建模,即开发复杂结构和复杂算法的场合。Lisp不仅具有优异的语言表达能力,而且交互编程环境良好,因此开发程序的时间会比C语言缩短很多。它的不足之处在于源代码的表述方式与自然语言差别比较大,学习起来有些困难,而开发出来的程序可读性不强。至于在机器人编程语言方面的应用,可以举EusLisp(电总研和产总研),它具备面向对象的编程功能,以及几何建模、并行编程等功能,因而用于仿真等研究开发[4]。

    3.Java[5]

    Java是随着互联网的普及于20世纪90年代产生的面向对象的编程语言。它追求的是紧凑和简洁,而非C++那样具有丰富的功能。其最大特点在于能够预先对程序的危险动作进行检查(这里的危险动作指对受到禁止的存储器、文件、手续(函数)等的存取操作)。

    为了实现这个功能,Java程序被编译成称为字节代码的中间语言。执行时,首先由检验程序对字节代码的安全性进行检查,然后再进行解释执行。一般来说,危险的程序动作大多由指针所引起,而字节代码中不带指针操作,故保证了高的安全性。

    字节代码是解释执行的,运行效率很低。于是人们开发出T J IT (Just-In-Time)编译器,它可在即将开始执行前将程序编译成机器语言,从而获得了毫不逊色于C/C++的运行性能。由于中间经过了字节代码,结果不但不再需要依赖于硬件平台编写程序,而且具有安全检查的功能,因此特别适宜于编写互联网上发布的程序。在实际使用过程中,人们曾经发现了Java存在着儿个安全漏洞,为此又开发出了能够更加简便地在互联网上发布程序的语言JavaScript等(与Java无关),从而结束了Java在网络编程领域一枝独秀的局面。

    Java是在软件产业快速成熟的过程中诞生的语言。不幸的是,其规范和普及竟然沦为争权夺利的工具。

    尽管Java具有存储器自动管理的功能,但它与Lisp一样,有时也需要暂停运行进行无用单元收集,故无法用于实时性要求较高的场合,例如伺服控制。Java的水平介于C和C++之间,或者说介于C和Lisp的中间。虽然功能不如C++和Lisp那样丰富,但很容易掌握。同时由于JIT编译性能,在模式处理方面也不存在任何问题。

    Java没有连接表功能,不过借助类定义它能非常方便地实现相同功能。有报道说,Java比Lisp更能提高人工智能程序的性能。说到Java在嵌人方式应用的性能,尽管与Lisp的缺点一样,所花费的运行时间比较长,但是实际上目前在手机、PDA等产品中已经获得嵌人式应用的实例。研究表明Java还有一个优点,即适合分散编程,现在已经出现了将多个Java程序嵌人机器设备中实现分散控制的JINI技术。

    4.其他语言

    在用计算机进行数学或数式处理时,有时人们会使用Maple, Matlab, Mathematica等系统。这些系统采用专门语言.,主要用在理论验证或者离线仿真场合,通常人们编写一些小型的专用程序,验证完成后就把这些程序也随之作废。不过,现在人们已经能把数式处理语言嵌人到大型程序中,作为整体的一部分来运行了。例如,用Matlab语言简便地编写矩阵计算和信号处理程序,在完成仿真后以C语言的形式输出,然后再与其他的C语言程序连接起来应用。

    随着互联网的普及,很多应用开始将Web浏览器作为人机接口的界面。如果希望通过互联网对机器人程序进行控制,就需要与其他系统协同工作。在用CGI启动的场合,一般的做法是将Per1, PHP, Ruby等外壳语言作为Serviet(小服务程序)嵌人到Web服务器中,用Java来编写。

    如前所述,全部功能由单独的一种语言来实现并不是一种好方法。应该根据具体情况选择恰当的语言,或者采用分散系统来实现,这样既容易开发和维护,也可以柔性应对技术进步。如果一定要用一种语言来完成所有工作,那么目前最好的是C/ C++,今后的趋势将是Java。

    松井俊浩

    (责任编辑:laugh521521)

    文章分享:

    展开全文
  • 【数据分析R语言系列】R语言基础语法、基本数据结构、控制结构
    展开全文
  • LOGO语言

    2021-07-16 02:13:07
    LOGO语言Flahs版用于在普及小学生计算机知识,激发小学生学习计算机的兴趣,培养和训练他们的思维能力,发展他们的智力及创造力等方面都起了积极的作用。用Flash程序进行LOGO语言的模拟,可以完全模拟小学阶段大多数...

    LOGO语言Flahs版用于在普及小学生计算机知识,激发小学生学习计算机的兴趣,培养和训练他们的思维能力,发展他们的智力及创造力等方面都起了积极的作用。用Flash程序进行LOGO语言的模拟,可以完全模拟小学阶段大多数的LOGO语言命令,同时还增加了趣味性的命令(ZHUAN)转动命令,还有设置透明度的命令,同时又因为swf文件的跨平台通用性,让它更加符合现代网络观念。

    9891c1b784f4ebdb02f5893a76d219cb.png

    一、LOGO语言Flash版具备Pc-Logo语言的常用操作命令:

    1.具备Logo语言的画图命令。

    2.具备Logo语言的数学函数、字表运算等命令。

    3.具备Logo语言的文件加载保存命令。

    4.具备Logo语言的结构化语言特点。

    二、LOGO语言Flash版FLogo语言的独特之处:

    (一)最终版本填加了Logo模块窗口,从这一版也是LOGO模块的1.0版,从此让Logo语言具有了图形模块的编程方式,改变了学生对Logo语言的恐惧心理,变得喜欢Logo语言,甚至于乐此不疲。

    1.原版字符命令方式与模块同时存在,作用相同。

    2.模块方式将命令分成了十大类,由按钮选择。实现了大多数命令的模块化。

    3.程序编写方便快捷,只须拖动模块连成一组,单击鼠标即可执行此组命令,编程效果也立刻显现,即使中低年级的学生也轻松自如。

    4.可以新建模块,也就是自己定义一段子程序。

    5.系统变量可以随时拖动使用,还可以新建变量。

    (二)程序中产生的任何对象都可以用鼠标拖动。

    1.程序界面组件如海龟、命令框、编辑器、帮助窗口都可以拖动。

    2.程序中产生的按钮、变量框、探测器等也都可以随意拖动。

    3.程序中生成的图形对象默认情况下被锁定不能拖动,但可以借助键盘或设置lock的值来解锁。

    (三)只要是程序生成的图形就有编号。

    1.有编号就可以控制这个图形如同海龟一样。

    2.第一个图形(或称图层)编号是1,是最底层,命令行打一次回车,只要是要画图命令,就会新增一个图层,并且重叠在前一个图形的上一层。

    3.在编辑子程序中,可以用new命令来增加新的图层。

    4.每出现一个新图层,PID变量总是记录最新的图层编号。

    5.新图形的旋转中心点就是海龟在这个图层中画图时的出发点,图形旋转时就是以这个心点转动了。

    6.有了PID不管哪个图形都在掌控之中。让它假扮小海龟也没问题。用ASK命令,可以代替小海龟画图了。

    (四)丰富了(PLAY)音乐播放命令。

    1.可以播放本地或网上的MP3文件。

    2.可以播放内部自带的八种音效,让编出的程序动感十足,使用格式是PLAYS0到PLAYS7。

    (五)可以为海龟和图形加装探测器。

    1.系统设有16个端口用来加装探测器,探测器分6种,实现图形,障碍、火焰、水波、颜色、和灰度的探测。

    2.既然图形可以代替海龟,那当然图形也具有了生命,也可以加装探测器了。

    3.知道是图形是海龟画出来的,那障碍、火焰、水波都是造出来的,都是以画好的图形变化成了这些有特殊用途的图形。

    4.其中图形、障碍、火焰、水波的探测器都是漂亮的扇形,可以调节方向和半径,其实真正起探测作用的是扇形中间的角平分线,探测到对象后,会返回两种值:

    5.一个是PIN0~PIN15,PIN3就代表3号探测器的值,以此类推。如果是0,则是未探测到,如果>0,其数值就是探测器心点到探测对象的距离。

    6.另一个是HITID0~HITID15,也是表示16个探测器,返回的值是它所探测到的图形的编号,也就是说,它探测到几号图形了。如果只有一个探测器用这个HITID也可以,如果是多个,它返回的是端口号大的探测器返回的值。

    7.灰度和颜色探测器的形状不是扇形而是一个小圆圈,探测点在圆圈中心点,是颜色就返回颜色值,是灰度就返回灰度值,但灰度探测比较常用,因为颜色值太大不容易掌控,但用在探测到某一指定颜色也很实用。它只有一种返回值就是是PIN0~PIN15,返回的是颜色或灰度的值。灰度值范围是从0到255,黑色是0,白色是255。

    8.设置好的探测器是保存成一段子程序,方便下一次重现探测器,不必更手动设置。

    (六)碰撞命令,可以轻易实现图形间,或海龟与图形的是否出现碰撞。

    1.有了HIT碰撞命令,它有两个参数,分别是两个图形的编号,HIT23命令可以探测出2号和3号是否产生碰撞。如果其中一个编号是0,那就是和海龟碰撞。

    2.示例中的小球碰撞、俄罗斯方块、打字练习等都是利用HIT命令实现的

    (七)建立命令按钮。

    1.有了按钮可以脱离键盘的束缚,一切都在鼠标掌控中,可以为按钮填加执行的命令串,还可以为按钮设置各种样式,如果有程序正在执行,只有命令中的变量类的命令如MAKESETPC等,可立即执行,但碰到其它命令,则必须等待,或是被取消。

    (八)建立了变量框。

    1.可以为系统变量或自建变量建立一个变量框,这个变量框可以在程序中实时反应出其数值的变化,也可以用鼠标或键盘改变变量的值。

    2.命令按钮和变量框都可以保存成一段程序,供下次直接重现设置好的样式。

    (九)独特的文件加载和保存方式。

    1.可以用打开常规的程序文件,如。lgo、。txt等,还可以打开本地或网上网页文件中的文字或含藏的程序段。

    2.可以打开本地或网上的图形文件,作为图形对象,也可以作为背景。

    3.可以打开本地或网上的。MP3声音文件,播放音乐。

    4.可以保存程序到常规文本文件,也可以保存成内含藏有程序代码的网页文件。网页文件可以直接打开自动运行。

    5.可以将当前的画面转成。jpg文件保存在本地或用命令(uploadpic)命令上传至后台服务器中,可以实现在线浏览。

    6.初始化文件可以预先设定好一些参数,比如背景色、画笔色、画笔粗细,字体等。

    7.自动执行文件,可以让编写的程序自动运行展示。程序启动时自动判断在同文件夹下是否有自动执行文件,如果有就会将文件内容加载到程序编辑器中,并且自动定义,自动执行第一段子程序。

    (十)具备Flash文件所有具有的跨平台特点。

    1.本程序由FlashCS4用AS3语言编写,全中文系统。

    2.由Flash编程系统发布出两个文件,分别是SWF文件和EXE文件,它们的运行方法不同。

    ◎Flogo998.EXE文件,它自带播放器,可独立运行,支持现行的WindowsXP之后的所有版本。

    ◎Flogo998.swf文件,它不能独立播放,有两种方法运行:

    ·一个是由Flash的播放器来打开运行。

    ·另一个是由网页浏览器运行,所以它具有跨平台特性,只要能支持Flash插件的网页浏览器都可以运行此程序,不管是Windows、安卓还是Linux都可以运行。

    (十)自带全中文的帮助系统,学习起来更方便。

    (十一)命令格式要求与Logo语言有所不同。

    1、与PC-logo语言命令大多相同,但都用简写命令

    2、变量前可不用冒号(:)

    3、IF、For、AND和OR命令的格式不同(IF命令)if判断表达式可不用括号必须要有then例如:IFKK>10THENFD100(FOR命令)fori110[命令串]不能写成for[i110][命令串]例如:画正方形fori14[fd100rt90wait1]

    逻辑运算命令ANDOR的格式不同,例如abcd=1andb>4andc=5不能写成andabcd=1b>4c=5三、最新版9.99的改进。

    1、填加了Logo模块窗口,让Logo语言由字符命令方式转变成图形模块的方式,极大的提高了学生学习编程的兴趣,最具现实意义。

    2、填加了13个方便快捷的按钮。分别是:ASK替换、锁定、删除、放大、缩小、旋转、透明、复制、自绘、填充、障碍、火焰,水波。

    3、填加了海龟形象选择窗口,重新设计了背景和画笔颜色选择的窗口。

    4、填加了变量框和按钮,变量框和按钮都可以进行外观的设置,命令的设置,还可以保存,详细情况请看帮助。

    5、重新设计了探测器探测器由三根检测线,改变成一条检测线pin0~pin15的值体现了探测到对象时的距离,hitid0~hitid15的值是所对应探测器所探测到的对象的图形编号重新布置了探测器的使用方式,新增了灰度和图形传感器,共有6种探测器,16个端口没有变化,但每个端口的探测器各类可以任选,不必受限制,比如设置灰度探测器可以是0号到15号任何一个端口四、打开文件时出现汉字乱码怎么办?

    eaf808e45997c9de7abba23ae68a9674.png

    汉字乱码解决方法:

    1、由Flogo软件保存的。LGO和html文件已经是UTF-8类型没有问题,但如果是用其它软件编写的代码在保存时必须将编码改成(UTF-8)类型,不要存成默认的(ANSI)就没有问题了。

    2、可以用命令解决,使用MAKECODE“gb2312,将编码改为gb2312就可以了,如果还是乱码,还可以将编码改成(big5或gbk),可以打开CODE的帮助查看具体的使用方法。

    展开全文
  • 浅谈领域特定语言

    千次阅读 2021-07-16 15:43:29
    这些领域专家不是计算机科班出身,但是他们对自己的领域研究非常深入,他们非常期待能有一门面向领域的编程语言来帮助他们屏蔽计算机底层的复杂度,聚焦自己的领域,高效的进行编程。 在这样的背景下,.

    目录

    0  序言

    1  什么是 DSL

    1.1 生活中的 DSL

    1.2 DSL 与 GPL

    1.3  DSL 的分类

    1.4  DSL 的优势与劣势

    2  建立一个简单的 DSL

    2.1 领域建模与问题域和解答域

    2.2 确立共通的词汇

    2.3 设计 DSL 执行模型

    2.4 初次尝试 DSL

    3  DSL 的优势与发展

    3.1 eDSL 优势与分类

    3.2 业界语言 eDSL 扩展能力分析

    3.3  UI 领域的 eDSL —— SwiftUI

    4  总结

    4.1 小结

    4.2 未来的展望


    0  序言

     

    近年来,随着移动应用、人工智能、区块链、量子计算、芯片逻辑、音乐工程等领域的蓬勃发展,软件在各行各业的应用得到爆发式的增长,各行各业的研究人员和领域专家加入到软件开发的队伍,比如:芯片研发工程师需要通过编程来写芯片逻辑,人工智能算法研究人员需要通过编程写计算逻辑,音乐工程师需要通过编程构建音乐的交互式系统。这些领域专家不是计算机科班出身,但是他们对自己的领域研究非常深入,他们非常期待能有一门面向领域的编程语言来帮助他们屏蔽计算机底层的复杂度,聚焦自己的领域,高效的进行编程。

    在这样的背景下,领域特定语言如雨后春笋般在各行各业兴起。比如苹果在 2019 年推出基于 Swift 的 UI 描述语言 SwiftUI,FaceBook 在 2019 年推出安全灵活的 Libra 区块链编程语言 Move,微软在 2017 年推出量子计算编程语言 Q#,伯克利使用高层次构建语言 Chisel(基于 Scala 语言扩展)编写 RISC-V 的芯片逻辑,因此业界对领域特定语言的研究也进入了一个高峰期。其实领域特定语言(DSL)的概念并不是新的概念,它最早可以追溯到上世纪 50 年代,比如科学计算领域使用的程式语言 Fortran。而领域特定语言真正得到快速发展,还是得力于领域特定语言在理论、工程技术、工具等方面的发展。

    本文主要介绍领域特定语言(DSL)的基本概念、分类以及优劣势,并通过一个简单的例子入手讲解如何构建一个领域特定语言,并且结合 EDSL 的优势以及发展趋势,推导出宿主语言的特性需求,最后通过一个工业界的典型 DSL——SwiftUI 讲解元语言和对象语言的配合关系。

    当然如果读者想了解更多有关 DSL 相关的技术内容,可以持续关注 SIG-DSL 扩展发表的相关文章。我们也欢迎读者朋友加入我们的 编程语言技术社区 SIG-DSL 扩展小组 ,和我们一起深入探讨 DSL 相关技术。

    加入方式:文末有小助手微信,添加并备注加入 SIG-DSL 扩展


    1  什么是 DSL

    1.1 生活中的 DSL

    单看上面的叙述,对于初次接触这一领域的你来说,大概率还是会迷惑什么是 DSL,引用维基的定义:领域特定语言指的就是专注于某个应用程序领域的计算机语言 [1]。现在我们将这一句话换一种说法:领域特定语言,就是让解决领域特定问题的编程模型使用领域专有的语言来 “说话”。即用代码来说话,其目的是让用户通过阅读代码就可以明白建模里的业务规则,而非一堆架构图上的框框和箭头。

    如果要弄懂这个概念,首先我们要明白什么是领域专有的语言,这里举用一个和 Debasish Ghosh 所提到的买咖啡相似的用例 [2],这就如同,当你走进奶茶店点上一杯 “正常冰 3 分糖的多肉葡萄”,那么店员就会准确无误的给你制作一杯,550ml 当季葡萄果肉加绿茶底并配上醇香芝士再加上满满一杯子冰的饮品。你无需过多的描述每一项,只需按照菜单规则的名字来点单,而且这一说法只适用于奶茶饮品领域。

    在这个场景中,点单的过程就是用特定领域的语言来表达一个问题,店员根据你的订单,把饮品做出来是对于问题的解答。这种从问题域映射到解答域的实现模型就是 DSL 的基本思路。如果把上述的场景做成软件,那么客人们点单时所用到的语言就是你要找的 DSL。

    1.2 DSL 与 GPL

    认识一个新事物,我常常会从正面和对立面两个方向来看,正面就如上段内容所述,而与 DSL 处在对立面的就是 GPL(General Purpose Language),即通用编程语言,像我们熟悉的 Java、Python 或者 C 语言等,这类语言没有特定的使用场景,你可以拿他们来实现任意领域的计算机程序,他们的出现并不是为了解决特定领域的问题,我们称这种能力为具有通用的表达力。

    与其相反,DSL 都有相对应的专门的领域,在生活中常见的 DSL 如:HTML 是我们熟知的用于描述 Web 页面的标记语言;CSS 是用于描述页面样式的语言;SQL 是用于创建和检索关系型数据库的语言;这些语言都有一个特点,就是只能解决其特定领域的问题,正如你不可能拿一把菜刀来修汽车一样,你同样无法单独用 CSS 来搭建出一套证券交易系统,这也是正是 Martin Fowler 提出的 DSL 与 GPL 的根本区别,即 Limited Expressivity (有限的表达力)[3]。

    通用编程语言可以给任何事物建模,而 DSL 只适合给一个专门的领域建模。对于 DSL 与 GPL 的区别,可以借用编程语言 Lab 架构师徐潇在 QCon 大会上提出的一个例子来阐明,他将两种语言比作建筑材料,GPL 如水泥,而 DSL 如水泥做好的 “预制件”。

    图片
    图 1:GPL 与 DSL 区别的形象解释

    水泥可以做成任何建筑物,但是水泥管只能限定于做管道,而无法应用成楼板或其他建筑组件。但是当我们想要做管道的时候,我们更愿意接受可以直接使用的 “预制件”,而不是每次都从水泥铸型开始。这一例子也正是生动形象的描述出了 DSL 与 GPL 在表达力和易用度上的根本差异。

    1.3  DSL 的分类

    DSL 本身是一个宽泛的概念,它还可以细化成外部 DSL 和内部 DSL(Embedded DSL,简称 eDSL),像上述所列出的 HTML、CSS 以及 SQL,都是完全独立的语言,他们不依托于任何一门通用的宿主语言,我们称这种 DSL 为外部 DSL。

    与之相对应的,如在 UI 领域,基于 Swift 建立的 SwiftUI;基于 Ruby 设计的 IOS 依赖管理组件 CocoaPods;基于 Kotlin 或者 Groovy 设计的 Android 主流编译工具 Gradle;这些在现有宿主语言上实现的 DSL,我们称之为 eDSL。

    关于 eDSL 的详细介绍与优势对比,我们将在后续章节详细展开。

    1.4  DSL 的优势与劣势

    既然 DSL 的应用如此广泛,那么是否所有的项目都应该基于 DSL 开发?答案显然是否定的,没有一门技术具备完美解决所有问题的能力,DSL 同样在显著的优势下暗藏着危险,在确认是否引入 DSL 之前,我们需要评估一下 DSL 的优缺点。

    首先从 DSL 所扮演的角色来看,由于 DSL 更趋向于解决固定范围的事情,所以基于 DSL 的开发关注点会更加的集中,它仅需要提供范围足够小的一个领域的 API 接口,并且会将领域中的专有概念抽象成更加精确的统一语言来表达其语义(这一点将会在下一章节中说明)[2],这也就意味着 DSL 在有限的范围内具有更强的表现力,且可以消减开发人员与领域专家之间沟通的代沟。

    同时 DSL 是一层更高层的抽象,并不需要使用者懂得基于低层次语言的实现手法,所以对于没有编程经验和背景的领域用户来说,稍加学习便可以使用其来实现自己想要的程序,这也正是 DSL 最大的魅力。

    当然缺点也同样存在,首先不可规避的是 DSL 是一种语言设计类的工作,而要从零设计一门语言,需要设计相关的语法、语义,同时还需实现其对应的编译器(语法解析、类型系统和代码生成等),这并不是一个靠堆积人力就能解决的问题,而是对复杂度和专业度要求很高的工作,所以越来越多的人会将 DSL “寄身”于别的宿主语言,也就是所谓的 eDSL。即便如此,eDSL 的设计难度还是很高,对于 eDSL 的介绍将在第三章展开,这也将是本文的重点内容。

    再者就是一些配套开发工具的开发,如果从零开始设计一门语言,那么像 IDE、测试工具、调试工具和性能工具等相关配套工具都需要从零开始设计并实现,而 eDSL 可以让开发者复用宿主语言本身就具备的这些工具,这也是越来越多的人选择 eDSL 的原因之一。当然对于一些场景, IDE 或者测试工具还是有可能会需要基于宿主语言原生的工具做一些相对的扩展。

    另一方面,如果越来越多的外部 DSL 出现,那么对于开发者来说,将会出现语言永远学不完的现象,任何一个外部 DSL 出现,都需要开发者从零开始学习一门新的语言,而且由于这门新语言只针对特定领域,导致其使用场景有限,这也会带来学习成本与学习价值之间失衡的现象,这是另一个人们选取 eDSL 的原因,毕竟 eDSL 只需要开发者学习基于宿主语言新抽象出的接口即可。

    图片
    图 2:学不完的外部 DSL [4]


    2  建立一个简单的 DSL

    2.1 领域建模与问题域和解答域

    想要设计一款 DSL 需要从领域建模入手,领域建模用于以可视化的形式记录一个系统中的所有的关键概念和词汇表,并且描述出系统中各个实体之间的关系。在被用于软件开发阶段中,实体则可以演变为类别,方法和交互关系则可以演化为逻辑代码。上文中所提及的 “问题域” 和“解答域”则是领域建模的基本实践活动。

    那么什么是问题域?问题域是指我们在业务场景中的实体,过程和约束条件,如前面的例子中,芝士、冰、甜度、多肉和葡萄等这些主要元素即为问题域中所有的实体,其中葡萄和杨梅无法同时放入等规则是一些加在实体上的一些约束条件,再复杂的模型还会添加一些其他的行为,如是否需要打包、何时取餐等。

    解答域则为实现问题域的分析模型提供手段,换言之,问题域所有的元素都需要映射成解答域中的一种手段,如问题域中的冰度,则会映射到解答域中加冰这一解决方法上。而且这种组合必须符合映射的概念,即每个问题域在解答域中必须有且仅有唯一的元素与其对应,不能出现单对多或单对零的情况出现。如果是单对多,那么说明我们设计的解答对于当前的问题域出现了歧义;如果是单对零,那么说明我们设计的解答对于当前的问题域是不完备的。下图描述了领域建模的第一步,左边所有的实体,都可以在右边找到对应的表示。

    图片
    图 3:问题域到解决域的映射

    2.2 确立共通的词汇

    现在我们已经有了问题域和解答域,并且我们已经知道问题域和解答域的映射关系,那么设想如下场景:背景是作者接手了一个大型金融中介机构的后台操作建模的项目,有一次在参加金融中介机构的一次需求分析大会时,发现金融业的领域专家在会上大谈一些附息债券、折价债券等金融中介的常用术语,这便对建模实施者,也就是作者本身造成了困扰,因为对于作者而言,他并不是金融领域相关的从业者,所以不理解这些专有的词汇,甚至容易混淆一些同义词,这就导致作者难以明确最终的需求 [2]。(该实例来自于 Debasish Ghosh 《领域专用语言实战》一书)

    这里需要注意的是,这段故事中提到的两种人物身份,一类是身为领域相关从业者的领域专家,还有一类是身为建模人员的作者本身,当建模人员不熟知领域相关知识的情况时,那么领域专家与建模人员之间的交流便存在了问题。

    所以不难想出,为了解决这一问题,我们需要构建一门统一的词汇。在 “领域驱动设计之父” Eric Evans 所写的《Domain-Driven Design — Tackling Complexity in the Heart of Software》一书中,Eric 提出了 Ubiquitous Language(统一语言)[5],这一词的目的是创造一门可以在团队、开发者、领域专家、测试人员以及其余参与者之间共享的语言,而这种共通的词汇也正好是联系领域专家与建模开发者之间的桥梁。

    试想一下如果没有共通的词汇的存在,那么也就没有了一一对应的关系,这对于需求对齐来说是致命的,如此多的陌生词汇,甚至还参杂着同义词、近义词在其中,这些对于领域建模来说都是或多或少的噪音干扰。因此在领域建模的过程中我们需要设计这一门统一语言来作为需求对齐、会议研讨甚至测试编写的唯一语言,对于那种相同含义的词汇就应该按统一的一种名字来命名,这也正是 Eric 所强调的去除领域理解中难懂的术语与结构,避免设计中的歧义以及需求的不一致。

    请一定要注意这关键的一步,共通词汇的确立是需要时间反复提炼打磨的,它可以避免更多因需求没对齐而带来的返工开销。这就如同武侠小说中的内功心法一样,只要内力足够浑厚,后续只要学会了一两招的招式,那便是响当当的武林高手。

    所以统一语言的构建是建模的前提基础,有时我们在这上面花的时间甚至会比预期想象的要多得多。我们再回到上述买奶茶的例子,在确立共通的词汇前,我们问题域的一些实体,虽然小有体系,但却是杂乱无章的,甚至还会有混淆重叠的部分,如下图示:

    图片
    图 4:统一词汇前的问题域

    当建模者时而听到三分甜,时而听到 30% 糖度,又有时会听到 0.4Oz,虽然三者意思相近,但是对于建模者来说难免需要进一步思考三者的联系与差别,这还仅仅是一个词汇相对通俗易懂的场景,如果我们拿上文中所提到的金融中介的场景来看,那么这个问题的复杂程度可想而知,可不是简单的 “糖度” 可以比拟的。

    这时候统一语言的好处就显示出来了,当我们把所有的词汇都按照规定的统一语言规定好之后,对于上述场景,我们就统一规定这一规模的糖度为三分甜,那么对于建模者来说,这就是一档糖度的表示,同时对于领域专家来说,这就是代表着对于 500ml 的饮品需要添加 0.4Oz 的糖。这样当领域专家再和建模者讨论的时候,就达成了一致,而此时,我们上述的图就可以简化为下面的样子:

    图片
    图 5:统一词汇后的问题域

     同时好的统一语言对于 DSL 的设计是有着极大的正向促进效果的,建模者完全可以就把设计好的统一语言转换为 DSL 中的各个实体,比如在统一语言中,我们设置糖度为五个专有词汇 “全糖”、“七分糖”、“半糖”、“三分糖” 和“无糖”,且糖的种类可以分为 “果糖” 和“糖浆”,那么当建模者在设计一个添加糖度模块的时候,同样可以使用这些名字,如定义一个糖的对象,它具有糖度和种类两种属性,并设置这些属性的值就为这些统一语言规定的词。

    所以当我们的统一语言设计的足够好的时候,那么对应的 DSL 的实体的定义与词汇也就呼之欲出了。再进一步需要做的就是设计一层足够好的抽象和映射逻辑。回头看看,现在我们已经花了足够多的时间在领域词汇的确立和模型分析上,当然这一部分的开销是值得的,那么我们如何才能让领域专家直接基于系统的输入得到解答域的技术制品?或者说是否可以以上述设计的统一语言为基础,建立一种沟通模型,让无论是领域专家还是其他更多参与者都可以抛出问题并得到解答域制品?而这正是我们所需要的 DSL。

    2.3 设计 DSL 执行模型

    上文说到我们需要靠 DSL 来实现中间的映射关系,那么我们之前的图片就可以转换为下图:

    图片
    图 6:DSL 作为映射桥梁

     一个好的 DSL 脚本在联系两个区域时需要遵守一定的原则,Debasish 认为在设计 DSL 应该体现以下三项原则 [2]:

    • DSL 需要将问题域中的实体以同名的形式创建相对应的抽象

    • DSL 脚本的逻辑语言与词汇必须使用设计好的统一语言

    • DSL 脚本需要对语言实现进行抽象,DSL 脚本中不应该引入与解决特定领域问题本身无关的复杂逻辑

    显而易见的是这些原则在极力地用领域用户能看懂的方式来建立 DSL,并且尽力避免掉一些与领域用户无关的干扰,其根本目的就是为了加强与领域用户的沟通能力,使领域用户稍加学习便能基于 DSL 做出他们想要的应用程序。那么 DSL 脚本到底是如何执行的呢?

    图片
    图 7:三种常见的 DSL 运行方式

     上图展示了三种比较常见的 DSL 脚本执行方式:

    1. 源码可以直接执行

    2. 源码会编译成可执行的二进制

    3. 源码利用元编程等能力转译为另一份源码

    前两种并无过多需要描述的,直接执行就是指我们所建立的 DSL 基于的语义模型是解释执行的语言,类似于 Python 或者 JavaScript;而第二种就是指基于的语义模型是编译执行的语言,像 Java 或者 C++;第三种方式则被大量运用在 eDSL 之中,其利用宿主语言所具备的元编程的能力,将宿主语言的复杂性简化从而提高 DSL 的表现力和简洁度,对于元编程的介绍与优势将在后续的章节进行展开。

    2.4 初次尝试 DSL

    万事俱备,现在让我们回到最初的奶茶的那个例子,我们尝试着利用本章节所讲到的方法设计一个针对奶茶行业的简单 DSL,并用其做一个奶茶订单系统。

    在此之前我们需要做一些假设与背景故事的丰富来增强我们的体验感。我们假设现在有一台可以自动做奶茶的机器,它无需店员亲自手动的来搭配各种原料,店员仅需要依靠该奶茶制作系统点单,系统会依靠点单生成对应源码并运行调用奶茶机提供的接口,后者将自动做出店员想要做的奶茶。为了简化场景,我们的奶茶店仅有 3 种底料可供选择:杨梅汁、葡萄汁以及牛乳,对应的茶底也仅有三种:乌龙茶、红茶以及绿茶,同时我们有五种甜度(全糖、7 分糖、半糖、3 分糖和无糖)和四种温度(正常冰、少冰、无冰和加热)供用户选择。

    首先,我们先确立一下共通的词汇,由于本场景比较简单,上面的词汇已经能够很自然的作为我们所需要的共通词汇了。总结出如下表:

    图片
    表 1:统一词汇表

    现在有了共通的词汇,那么我们按照上文所提到的三项原则可以确定如下实体,我们采用枚举类型来表示出一杯饮品的各种属性,以及属性的值,在此次模型中,我们假定有这样一门宿主语言,它具备类型系统并可以与 JavaScript 互操作,我们将基于这一门宿主语言实现我们想要的 eDSL:

    // use enum to represent the tea taste
    ENUM Taste {
      bayberry | grape | milk
    }
    ​
    // tea types
    ENUM Tea {
      Oolong | black | green
    }
    ​
    // the sweetness types
    ENUM Sweetness {
      full | threeQuarter | half | oneQuarter | noSuger
    }
    ​
    // the temperature
    ENUM Temperature {
      ice | halfIce | noIce | heat
    }

    有了各种属性之后,我还需要定义一个订单的类,用于生成最后的订单发送到制作奶茶的机器:

    Class Order {
      constructor(taste, tea, sweetness, temperature) {
        let taste: Taste = taste,
        let tea: Tea = tea,
        let sweetness: Sweetness = sweetness,
        let temperature: Temperature = temperature
      }
    }

    现在我们已经有了订单,那么我们还需要一些行为来与奶茶店的设备做一些交互,比如假设奶茶制作机提供给我们一个 JavaScript 的接口 makeTea,接口的参数类型是 Object,并且,我们奶茶店的大屏也会提供给我们一个 JavaScript 的接口 showPrice,用于显示最终的价格(假定只按口味区分价格,分别为 15、14、16),那么我们现在借助语言互操作的能力给订单赋予这种能力:

    /* 借用语言和 JavaScript 互操作的能力,调取外部 machineAPIs 模块中的接口 */
    JSModule("machineAPIS") {
      func makeTea(order: Order): void
      func showPrice(price: String): void
    }
    Class Order {
      ...
      func getPrice() {
        let price = Switch (this.taste) {
          case: bayberry => "15"
          case: grape => "14"
          case: milk => "16"
        }
        return price
      }
      
      func sell() {
        makeTea(this)
        showPrice(this.getPrice())
      }
    }

    以上我们就简单地创建了一个极简的模型,那么当用户下发订单的时候,店员就可以直接用下面的代码实现:

    // 订单 A
    let orderA = Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
    orderA.sell()
    // 订单 B
    let orderB = Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    orderB.sell()

    我们由此可以发现 DSL 的神奇所在,即便你从未接触过这门假想中的编程语言,你仍然能够很轻易地理解这段代码在干嘛。下面我们再借用元编程的能力,使其变的更酷一些,我们可以通过宏定义的方式将上述代码中的一部分代码隐藏起来,即可变成下面的形式:

    @sellOrder
    Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
      
    @sellOrder
    Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    // 通过元编程的能力,上述代码在编译时将先转译成
    let orderA = Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
    orderA.sell() //元编程的能力将这句表达式折叠起来,靠宏定义将其展开
    let orderB = Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    orderB.sell()

    这样店员就可以编写简单的脚本来和奶茶制作机以及大屏幕做交互,哪怕他从未学习过这门语言甚至连编程也没有接触过,通过简单的学习,他同样可以上手写出相应的订单脚本。因为 DSL 提供了足够高的抽象,抛除了语言本身的学习成本,并且脚本中所使用的词汇全部都是建立在我们之前设计的共通词汇之上。


    3  DSL 的优势与发展

    3.1 eDSL 优势与分类

    在上述例子中,我们设计的是一门借助了宿主语言的 eDSL,由此我们也能看出当 DSL 借助宿主语言时的一些优势:

    • 最直观的一点,我们无需重新设计一门语言,这样就避免了语法设计和语义设计这种复杂的工作,我们要做的仅是利用宿主语言本身的特性来做抽象。

    • 正如上一条所提到的,我们可以利用宿主语言全部的语言特性。像例子中,我们就用到了 “枚举” 和“类”的语言类型,同时我们可以用到语言本身的类型系统或者语法糖等特性,并且可以直接借助语言本身互操作的能力与其他语言做交互,甚至可以借用元编程能力,使我们做更高一层的抽象,这都是 eDSL 本身的优势。当宿主语言特性足够强大丰富的时候,这也意味着相应的 eDSL 将有更多更灵活的功能,而且这些功能都是宿主语言 “免费” 提供的,eDSL 直接拿来使用即可。

    • 可以直接使用宿主语言提供的配套的工具,如 IDE 或者调试功能,无需从零开始投入到新语言的开发中。

    所以 eDSL 相比外部 DSL 来说,开发的成本更低,并且更易推广,这也是开发者更喜欢使用 eDSL 的根本原因之一。在 eDSL 这一类别下,我们还可以分成不同的形态模式,下图展示一些不太严谨的 eDSL 的各种实现模式 [2]:

    图片
    图 8:eDSL 细化分类

     相比于内嵌式,生成式则是指领域抽象可以通过使用一些转译技术转译到宿主语言,如编译时宏、预处理等。

    3.2 业界语言 eDSL 扩展能力分析

    如上文所说,eDSL 最大的好处之一就是可以借用宿主语言本身的特性,所以现如今很多主流语言本身就为实现 eDSL 设计了很多优质的特性,使开发者可以构建面向特定领域的扩展。接下来本章节会对 Swift、Kotlin、Dart 以及 Scala 展开分析,看看他们有哪些特性有利于其扩展出以其为宿主语言的 eDSL。
    Swift 的设计目标一直致力于 "Make Your Swift API Better",具体体现在有表现力、清晰无二义性且简单易用,这也正好是 DSL 所追逐的最终效果。关于 Swift 的 eDSL 分析如下:

    图片
    表 2:Swift 调研

     下面再来看看 17 年被 Google 官宣为安卓系统官方语言的 Kotlin,Kotlin 作为一个运行在 JVM 上兼容 Java 的静态语言,其语法更简洁,且兼具了很多实用功能,具体如下:

    图片
    表 3:Kotlin 调研

    目标成为下一代结构化 Web 开发语言,Google 主导开发的 Dart 语言也同样很易于扩展 eDSL:

    图片
    表 4:Dart 调研

     Scala 作为一门拥有强大类型系统和类型约束的语言,结合其本身简洁的语法设计,使得依赖类型化抽象能力实现的 eDSL 拥有较强的领域表现能力:

    图片
    表 5:Scala 调研

     从上述四门语言可以看出,易于实现 eDSL 的语言通常都具有以下特点:

    • 支持面向对象:可以用类或者接口等抽象映射出领域内专有的实体,甚至有时候会提供一些类型扩展的机制来对于无法修改的类型做扩展。

    • 元编程能力:同时我们可以发现以上四门语言都具备元编程能力,元编程能力可以将复杂的实现隐藏起来,使面对用户的语法保持简洁并且精炼,并且支持用户自定义语义,如利用宏或注解等编译时元编程能力创造出一种不同于宿主语言的语法。

    • 声明式范式:声明式范式完美契合 DSL 的理念,因为用户不用关心怎么做,他只需要关心自己要什么即可。为了达到这一功能,链式调用、宏、类型扩展等特性发挥了重大作用。

    • 语法简洁:为了减少宿主语言本身语法的噪音,语法糖是一种有效的手段,比如一些标点的省略,关键字的省略以及简化的 Lambda 或是尾随闭包。

    接下来我们将结合具体的 eDSL 实例来看看其相比外部 DSL 的优势与收益。

    3.3  UI 领域的 eDSL —— SwiftUI

    SwiftUI 是一门基于 Swift 构建的声明式 UI,这当然也是一门针对 UI 领域的 eDSL,下面是一段 SwiftUI 官网提供的代码 [6]:

    import SwiftUI
    Struct Content: View {
      @State var model = Themes.listModel
      var body: some View {
        List(model.items, action: model.selectItem) { item in
          Image(item.image)
          VStack(alignment: .leading) {
            Text(item.title)
            Text(item.subtitle)
              .color(.gray)
          }
        }
      }
    }

    当我们看到代码的时候,其实我们已经很容易的想像出对应的 UI 的布局,这便是声明式 UI 范式所带来的最大的收益。而为了实现这一范式,SwiftUI 借助了许多宿主语言本身的能力,这也正是 eDSL 的优势所在,通过这段代码我们可以看出上一章节所提到的所有四个特性:

    • 首先,它将组件等实体封装成为一个个对象,并且这些对象的命名都在前端领域的统一词汇中。这样当用户需要一个组件的时候,只需要将对应的组件实例化出来即可,这就加强了模型本身与用户的沟通能力,也是其为了实现 "UI as Code" 效果最根本的一步;

    • 再者,它通过注解的能力对其复杂的状态管理相关的逻辑代码做了隐藏,这段被隐藏的复杂逻辑在本文不做展开,有兴趣的读者可以去了解一下 SwiftUI 的 MVVM 模型以及其观察者模式;

    • 接下来,为了达到其声明式范式的效果,SwiftUI 借用了宿主语言命名参数以及链式调用的特性,使其达到用户可以通过 [组件名].[属性名].[属性名] 的形式绘制组件的效果。用户无需关心我如何去画这个组件,用户关心的就是我需要组件有哪些属性即可,这也正是上文提到的 "What";

    • 最后,SwiftUI 利用语法糖,如省略关键字 new 和 return,或者简化的枚举(比如例子中的 ".leading" 和 ".gray" )来消减语法的噪音。其还利用类型系统,如支持不透明返回类型,通过靠编译器本身的推导来简化开发者手写复杂的返回类型。

    同时 SwiftUI 可以使用 Swift 本身的开发工具如 IDE 等。正是得益于这些现代编程语言相关特性的发展,才使我们在现实的软件开发中见证了 DSL 所具备的潜力。


    4  总结

    4.1 小结

    本文到此就已接近尾声,回顾一下本文所有的内容,我们认识到了 DSL 是一种极其友好的领域建模方式,这得力于其强大的描述建模领域的表达能力。随着现代编程语言的发展,在语言层面对于 DSL 设计的支持越来越充分,比如借助高阶函数的能力,使用户在能够准确表达特定领域中的名词基础上,还能够很好地仿效该领域的动词 [2]。

    元编程的能力以及灵活的类型系统,更是打开了宿主语言本身表现力的限制,这里引用 Debasish Ghosh 说过的一句话 [2]:对于一种能力充分的语言来说,限制其表现力的只有使用者的创造力而已。

    总结最近发展起来的语言,不难发现众多语言的元编程的能力都在不断提高,这也正是各个通用语言为了实现 eDSL 所作的努力,所以元编程的发展对于 eDSL 的表现力与创造力是至关重要的一环,如果读者想了解有关元编程相关的细节,可以时刻关注 SIG-元编程 发表的相关文章,相信读者一定会大有收获。

    4.2 未来的展望

    像上述列举的 Scala、Kotlin、Swift 和 Dart 在 DSL 的发展上都有不同程度的布局,基于这些通用语言来看,类型系统以及元编程能力的发展,对于 DSL 未来的发展将会是挑战之一,同时如何最大程度消减宿主语言带入的噪音(如报错信息不够领域化、无关领域的类型信息)也是我们需要考虑的关键问题之一,再者我们还需要思考下如何让宿主语言配套的调试或者 IDE 支持其扩展的 eDSL。

    虽然仍有这么多挑战与问题值得我们去追寻,但是无论 DSL 如何发展,我们都需坚持其基本的设计原则,同时需多站在用户的角度来思考 DSL 未来的发展,这样 DSL 才会健康地成长。希望越来越多的软件开发者可以看见这一领域的价值与乐趣,并投身其中。

    参考:

    1. Domain-specific language - Wikipedia. (2021). Retrieved 28 June 2021, from https://en.wikipedia.org/wiki/Domain-specific_language

    2. Ghosh, D. (2010). DSLs in action. Simon and Schuster.

    3. Fowler, M. (2010). Domain-specific languages. Pearson Education.

    4. 可画 (2021). Retrieved 28 June 2021, from https://www.canva.cn/icons/MACF30PXThc/

    5. Evans, E., & Evans, E. J. (2004). Domain-driven design: tackling complexity in the heart of software. Addison-Wesley Professional.

    6. SwiftUI Overview - Xcode - Apple Developer. (2021). Retrieved 28 June 2021, from https://developer.apple.com/xcode/swiftui/

    在这里插入图片描述

     

    展开全文
  • 本文主要向大家介绍了JAVA语言借助Gradle Plugin解决模块化开发中模块如何对外暴露接口,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。直奔主题,在模块化开发中,模块间的数据交流大多数同学会...
  • 智慧职教: 形体训练的... 67°【单选题】传递球两头起主要借助 。A. 腰腹 力量 B. 腿部力量 C. 上肢 力量 D. 以上均不对【多选题】绩效考核的方法很多,但根据其性质,可以分为( )A. 正考核B. 客观考核法C. 负考核D....
  • 1. 内部类 很多时候我们创建类的对象的时候并不需要使用很多次,每次只使用一次,这个时候我们就可以使用内部类了 1.1 内部类概述 内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类...
  • java中final关键字、权限修饰符、内部类(成员内部类、局部内部类、匿名内部类)
  • 混合编程方法:模块链接法汇编指令嵌入法1: 模块链接法则模块链接法是指分别用汇编语言和C语言实现独立的模块(或子程序),再用链接程序把各模块生成的obj文件连接成一个可执行程序。1:C语言调用汇编语言子程序:即...
  • 新型敏捷硬件设计语言---Chisel初识

    千次阅读 2021-02-18 08:52:34
    在今天众多的编程语言中,Java常常是软件开发者的首选语言。而能让Java之父给出如此评价的Scala,想必有其吸引人之处。那么,Scala究竟是一门什么样的语言呢? Scala是一门基于JVM(Java Virtual Machine)运行的语言...
  • 一文带你解密 Go 语言之通道 channel

    千次阅读 2021-03-06 00:17:58
    Go 语言中的一大利器那就是能够非常方便的使用 go 关键字来进行各种并发,而并发后又必然会涉及通信。Channel 自然而然就成为了 Go 语言开发者中必须要明白明了的一个 “东西” 了...
  • 作者:丘小海来源:华为内部论坛这是华为内部论坛很火的一篇文章。内卷这个概念的内涵很丰富,与我们的生活息息相关。为了普及和传播知识,我参考了相关的信息,把我个人的粗浅理解奉献给朋友们。内卷 ...
  • 来自:python遇见NLP导读通过语言给予智能体指示使其完成通用性的任务是人工智能领域的愿景之一。近年来有越来越多的学者试图通过融合计算机视觉与自然语言处理领域的相关技术以期实...
  • 下载本文示例代码我们不需要将动态语言编译为 Java字节码就可以在 Java 应用程序中使用它们。使用 Java Platform, Standard Edition 6 (Java SE)中添加的脚本包(并且向后兼容 Java SE 5),Java 代码可以在运行时以一...
  • 点击左上方蓝字关注我们【飞桨开发者说】Xutan Peng,英国谢菲尔德大学Lincedo实验室博士在读,研究主要围绕自然语言处理和表示学习。项目背景据联合国科教文组织统计,全球现存七千余...
  • 企业内部培训常用的方法企业培训的效果在很大程度上取决于培训方法的选择,当前,企业培训的方法有很多种,不同的培训方法具有不同...1.讲授法:属于传统模式的培训方式,指培训师通过语言表达,系统地向受训者传授...
  • x86汇编语言:从实模式到保护模式2013年1月由电子工业出版社出版发行,总共6000行的源代码,全方位地向读者展现汇编语言程序设计之美。尽管汇编语言也是一种计算机语言,但却是与众不同的,与它的同类们格格不入。...
  • 7,以Discriminator实现Fine-tuning架构解析 8,ELECTRA的Generator数学机制及内部实现详解 9,Generator的Loss数学机制及实现详解 10,Discriminator的Loss数学机制及实现详解 11,Generator和Discriminator共享...
  • 在脚本语言领域,Lua是最快、最高效的脚本语言之一,因为它有资格作为游戏开发的备选方案。 1.2 脚本语言 1.3 编程语言 机器语言:0和1,人类几乎没办法阅读、理解 汇编语言:由一些特定指令构成,学习成本比较高;...
  • ©作者|邴立东、李昕、刘林林、周然、丁博生单位|阿里巴巴达摩院自然语言智能实验室研究方向|自然语言处理低资源、跨语言 NER 简介命名实体识别(NER)作为一个经典的 NLP ...
  • 开场白我(史斌)曾在Gopher China 2020大会上分享过《Go语言编译器简介》(https://github.com/gopherchina/conference/tree/ma...
  • 【单选题】挨打后的宝玉让晴雯送给黛玉两条 【判断题】共阳极数码管的内部是由发光二极管进行显示的。() 【单选题】37.在PROGRM状态下编制程序时,结束一行程序的输入并且换行,用( )键可实现。 【单选题】在【新建...
  • 上学的时候,为了考试,许多的同学经常是闷头...经过自己的一些思考,以及自己的实践,我觉得语言的学习不应该是记忆,语言的学习应该是条件反射的养成。语言的理解就是条件反射的自然反应。1、语言的学习不是记忆!...
  • Q# Quantum 编程语言02/01/2021本文内容Q# 语言指南中详细介绍了有关 Q# 编程语言的所有所需知识。 与其他内容一样,我们的语言设计过程为开放源代码,我们欢迎你的参与。有关 Q# 背后的基础和动机的更多背景信息,...
  • Java内部

    2021-11-15 13:08:38
    Java内部类成员内部类静态内部类局部(方法)内部类匿名内部类 成员内部类 什么是成员内部类 在类内部但在方法外部创建的非静态类称为成员内部类。 成员内部类的定义方法 class Outer{ //code class Inner{ ...
  • 自言语言处理基础知识参考:https://blog.csdn.net/meihao5/article/details/79592667英文资料:http://github.com/lovesoft5/ml一、自然语言处理概述1)自然语言处理:利用计算机为工具,对书面实行或者口头形式进行...
  • 随着计算机技术的不断发展,各种各样的编程语言层出不穷,有的语言大红大紫有的语言寂寂无名。这里就梳理一下那些出现过的编程语言,可能不一定都用得到,长长见识就行。当别人说起来的时候至少听说过,不会一脸懵逼。 ...
  • 一、Go语言设计初衷 1、设计Go语言是为了解决当时Google开发遇到的问题: 大量的C++代码,同时又引入了Java和Python 成千上万的工程师 数以万计行的代码 分布式的编译系统 数百万的服务器 ...
  • Go语言并发实践

    2021-01-11 14:40:18
    一、并发模型 ...在Go语言中,channel就是通道 process就是goroutine 。 Go语言调度模型 goroutine的调度模型抽象出来三个实体:M P G M:machine:一个内核线程 P:processor Go执行一段代码的上下
  • 上学的时候,为了考试,许多的同学经常是闷头...经过自己的一些思考,以及自己的实践,我觉得语言的学习不应该是记忆,语言的学习应该是条件反射的养成。语言的理解就是条件反射的自然反应。1、语言的学习不是记忆!...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 89,683
精华内容 35,873
关键字:

借助内部语言