第一篇:groovy对DSL的语法支持
引子
我们用一段gradle的脚本做引子,理解这一段脚本与一般的groovy代码是怎么联系起来的
buildscript {
repositories {
jcenter()
mavenLocal()
//或者使用指定的本地maven 库
maven{
url "file://D:/repo"
}
} dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
DSL的定义
DSL(Domain Specific Language)定义:针对某一领域,具有受限表达性的一种计算机程序设计语言。
所谓针对某一领域,其基本思想是“求专不求全”,不像通用目的语言那样目标范围涵盖一切软件问题,而是专门针对某一特定问题的计算机语言。
DSL伴随语义模型出现,语义模型会表现为程序库或者框架,对于构建DSL而言,语义模型不可或缺。DSL只是位于其上的一层而已。定义做什么,而不是用一堆命令语句来描述怎么做,所以它是声明式编程(如SQL),这一点很重要。DSL的受限表达性可以使DSL语言不易出错,即便出错,也易于发现。这是受限表达性的意义。
DSL是通用语言的特定用法。内部DSL通常是一段合法的程序,但是具有特定的风格。而且只用到了语言一部分特性。防止DSL逐渐演变为一种通用语言,要受限表达。目的防止DSL过于复杂,可维护性降低,学习成本提升,偏离方向。不要让DSL读起来向自然语言。它是程序语言,比自然语言更加准确和简洁。语义模型位于语言和DSL之间,为二者解耦。DSL脚本,解析器,语义模型,模型——DSL自上而下几个层次。
Groovy语法对DSL的支持
我们先看一个简单的类和一个奇葩的语法现象:分号省略;默认public省略;有形参的方法调用,括号可以省略;返回的return可以省略,默认最后一行代码的值返回。
import groovy.xml.*
import java.io.* class Task{
//默认省略public和分号
String summary
String description
Date dueDate
Map m static void main(args){
//默认有set和get方法
Task task1 = new Task()
task1.setSummary("this is Task1")
println task1.getSummary()
//有形参的方法调用,括号可以省略
task1.setDescription "this is Task class"
task1.printDescription ""
//可以直接传map
Task task3 = new Task()
task3.setM (['summary':'this is Task3','description':'Task'])
println task3.getM()
//map的分号可以省略
Task task2= new Task('summary':'this is Task2','description':'Task')
println task2.getSummary()
//括号也可以省略
Task task4 = new Task()
task4.setM 'summary':'this is Task4'
println task4.getM()
} public void printDescription(def str){
println "the task description is : $description"
}
}
看完省略括号的语法现象,下面看另一个重量级的语法现象——闭包
闭包是用{符号括起来的代码块,它可以被单独运行或调用,也可以被命名。类似‘匿名类’或内联函数的概念。
闭包中最常见的应用是对集合进行迭代,下面定义了3个闭包对map进行了迭代:
map.each({key,value-> //key,value两个参数用于接受每个元素的键/值
println "$key:$value"})
map.each{println it} //it是一个关键字,代表map集合的每个元素
map.each({ println it.getKey()+"-->"+it.getValue()})
除了用于迭代之外,闭包也可以单独定义:
def say={word->
println "Hi,$word!"
}
调用:
say('groovy')
say.call('groovy&grails')
输出:
Hi,groovy!
Hi,groovy&grails!
看起来,闭包类似于方法,需要定义参数和要执行的语句,它也可以通过名称被调用。然而闭包对象(不要奇怪,闭包也是对象)可以作为参数传递(比如前面的闭包作为参数传递给了map的each方法)。而在java中,要做到这一点并不容易(也许C++中的函数指针可以,但不要忘记java中没有指针)。其次,闭包也可以不命名(当然作为代价,只能在定义闭包时执行一次),而方法不可以。
当闭包遇到括号省略,一切都不一样了
Project.groovy
public class Project{
Date date void setDateFormat(Closure formatDate){
println formatDate(date)
}
}
Main.groovy
public class Main{ public static void main(def args){
Project p = new Project()
p.setDate new Date()
//正常
p.setDateFormat({
return it.format('yyyy-MM-dd HH:mm:ss')
}) //减return
p.setDateFormat {
it.format('yyyy-MM-dd HH:mm:ss')
} //减括号(是不是很像我们的gradle脚本?) p.setDateFormat {
it.format 'yyyy-MM-dd HH:mm:ss'
} } }
减完之后,像不像下面的脚本?
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
唯一的区别是我们需要用对象来引用方法,其实去掉对象也不难,自己调用自己的方法就可以了,看下面的代码:
public class Project{
Date date void setDateFormat(Closure formatDate){
println formatDate(date)
} //将format内置
String format(String f){
date.format(f)
}
//无形参的方法
void showDate(){
print date.toString()
} void run(){
//对象去掉,是不是一模一样了?
setDateFormat{
println 'this is a scrip'
format 'yyyy-MM-dd HH:mm:ss'
//没有形参的话就只能乖乖写括号了
showDate()
}
}
}
DSL的两个关键点,某一领域,gradle只为编译,也只用于编译。受限表达,一般只调用脚本运行上下文环境中的方法,为的就是尽量简单,出错的话,排错方便。伴随而生的语义模型就是那一套编译框架。
Groovy对DSL的支持,表现为可以省略:分号,调用方法的括号,return,默认public等。
参考:
http://docs.groovy-lang.org/latest/html/documentation/
第一篇:groovy对DSL的语法支持的更多相关文章
- Bootstrap:Bootstrap_table第一篇:快速用bootstrap_table(支持参数)筛选并展示数据,固定表格前几列,实现表格单元格编辑
1.准备好css和js文件 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstr ...
- Python编程笔记(第一篇)Python基础语法
一.python介绍 1.编程语言排行榜 TIOBE榜 TIOBE编程语言排行榜是编程语言流行趋势的一个指标,每月更新,这份排行榜排名基于互联网有经验的程序员.课程和第三方厂商的数量. 2.pytho ...
- 【ABAP系列】SAP ABAP7.40新语法简介第一篇
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP7.40新语法简 ...
- 用仿ActionScript的语法来编写html5——第一篇,显示一张图片
第一篇,显示一张图片 一,代码对比 as代码: public var loader:Loader; public function loadimg():void{ loader = new Loade ...
- Groovy 与 DSL
一:DSL 概念 指的是用于一个特定领域的语言(功能领域.业务领域).在这个给出的概念中有 3个重点: 只用于一个特定领域,而非所有通用领域,比如 Java / C++就是用于通用领域,而不可被称为 ...
- 我的第一篇Markdown语法博客
这是我的第一篇使用markdown语法编写的博客 使用的编辑器为Sublime Text2 并且使用了sublog插件, sublog是一个开源项目 sublog 并且参考了作者的博客 AmongOt ...
- 我的第一篇Markdown博客
我的第一篇Markdown博客 这是我第一次用Markdown写博客,发现还是比较好用的,加上Marsedit也支持了Markdown的博客预览,博客园也加了Markdown的格式支持,就更加方便了, ...
- 微型 ORM 的第一篇 DapperLambda发布
引言:因为接触过多个ORM,但使用的时候都遇到了各自的一些不够理想的地方,从最早开始开始公司自己分装的,到后面用EF,以及Dapper和DapperExtensions 到现在用的FluentDat ...
- Scala语言笔记 - 第一篇
目录 Scala语言笔记 - 第一篇 1 基本类型和循环的使用 2 String相关 3 模式匹配相关 4 class相关 5 函数调用相关 Scala语言笔记 - 第一篇 最近研究了下scala ...
随机推荐
- 在VS.NET中根据条件设置不同的MainForm
在VS.NET中有时候需要根据不同的条件设置不同的MainForm,例如:在程序第一次运行时候打开设置基本信息或服务器信息窗口等. 1.找到VS.NET中设置MainForm的窗口: 2.在编辑窗口中 ...
- 详解Oracle创建用户权限全过程
本文将介绍的是通过创建一张表,进而实现Oracle创建用户权限的过程.以下这些代码主要也就是为实现Oracle创建用户权限而编写,希望能对大家有所帮助. 注意:每条语语分开执行,结尾必须用分号; // ...
- PyQt入门系列(一):Hello World
开始搞PyQt了,顺便记录一下自己的学习!资料参考某大神的PyQt4 精彩实例分析,以及<征服Python>这本书. 下面是Demo: #-*- coding:utf-8 -*- #编码声 ...
- 单例模式总结(Java版)
1:懒汉的设计模式,在第一次调用的时候才完成相关的初始化操作 懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间.当然,如果一直没有人使用的话,那就不会创建实例 ...
- Mac下生成RSA密钥
MAC OS自带了OpenSSL,直接在命令行里使用OPENSSL就可以. 打开命令行工具,然后输入 openssl打开openssl,接着只要三句命令就可以搞定. 第一句命令生成1024位私钥: O ...
- 怎么去掉li标签前面的点??
<ul class="list"> <li> </li> <li> </li> </ul> .list li ...
- Codeforces Round #326 (Div. 2) C. Duff and Weight Lifting 水题
C. Duff and Weight Lifting Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...
- C# 利用范型与扩展方法重构代码
在一些C#代码中常常可以看到 //An Simple Example By Ray Linn class CarCollection :ICollection { IList list; public ...
- 利用text插件和css插件优化web应用
JavaScript的模块化开发到如今,已经相当成熟了,当然,一个应用包含的不仅仅有js,还有html模板和css文件. 那么,如何将html和css也一起打包,来减少没必要的HTTP请求数呢? 本文 ...
- MySQL · BUG分析 · Rename table 死锁分析
http://mysql.taobao.org/monthly/2016/03/06/ 背景 InnoDB buffer pool中的page管理牵涉到两个链表,一个是lru链表,一个是flush 脏 ...