对标java注解,仓颉语言宏功能简介
1.什么是仓颉宏
在企业级的软件开发市场,java语言长期处于绝对领先的位置,其中的原因比较多,比如开放性、生态等等,除此之外,java语言在开发过程中的易用性,也为此做出了贡献,比如java中的注解,通过简单的一个标记,就能完成复杂的功能,而spring等第三方框架的出现,更是让注解如虎添翼,大大简化了java程序的开发工作,初学者经过一段时间的培训,就可以使用基于注解的spring进行企业级开发。
仓颉语言作为一种面向应用层的通用开发语言,和java的开发范围高度重合,在对标java注解这一方向上,仓颉的宏在性能上有一定的优势,因为仓颉的宏是编译期展开的,不需要运行时处理,这样,性能会更高一点。不过,java注解和仓颉的宏并不完全一致,各有各的特点,使用得当的话都可以简化开发工作。
2.仓颉宏的定义
仓颉中宏的功能类似于函数,用来对输入的代码序列进行处理,输出处理后的代码序列,这个从输入代码映射到输出代码的过程称为宏展开。
和函数相比,宏定义具有如下特点:
宏定义所在的 package 需使用 macro package 来声明。
宏定义需要使用关键字 macro。
宏定义的输入和输出类型必须是 Tokens。
宏调用需要使用 @。
3.仓颉宏的使用示例
以下的示例代码模拟了登录以及入库、出库、查看库存等动作,包括多个类和顶层函数,假如需要把所有的函数调用都记录日志,也就是记录调用开始和结束的时间,以及传入的参数和返回的值,并且支持日志写入到控制台或者日志文件。
main(): Unit {
//模拟登录
if (!login("admin", "qD@0532")) {
println("用户名或者密码错误!")
return
}
//添加图书
let book = Book("仓颉语言元编程")
//模拟入库
book.input(88)
//模拟出库
book.output(66)
//查看库存
println(book.stock)
}
//登录
func login(userName: String, password: String): Bool {
let user = User.getUserByUserName(userName)
return user.passwd == password
}
//用户
public class User {
public User(var userId: Int64, var userName: String, var passwd: String) {}
//根据用户名称查找用户信息
public static func getUserByUserName(userName: String) {
return User(1, userName, "qD@0532")
}
}
public class Book {
public Book(var bookName: String, var stock: Int64) {}
public init(bookName: String) {
this.bookName = bookName
this.stock = 0
}
//入库
public func input(count: Int64) {
this.stock += count
return stock
}
//出库
public func output(count: Int64) {
this.stock -= count
return stock
}
}
要完成这样的功能,常规写法可能需要几百行代码才能实现,而且代码会嵌入到现有的函数中,带来一定的调试困难。但是,如果有了元编程的支持,通过宏定义一切就可以迎刃而解了。
假如已经自定义了一个名称为Cradle的宏,它可以通过切面织入的方式,自动拦截函数的调用,并且按照属性宏的入参来执行向控制台或者日志文件写入日志,那么,针对上面的要求,通过在函数和类的定义位置添加上Cradle宏调用即可,修改后的代码如下:
import cradle.*
from std import time.*
from std import collection.*
from std import fs.*
from std import io.*
from std import os.posix.*
@Cradle
main(): Unit {
//模拟登录
if (!login("admin", "qD@0532")) {
println("用户名或者密码错误!")
return
}
//添加图书
let book = Book("仓颉语言元编程")
//模拟入库
book.input(88)
//模拟出库
book.output(66)
//查看库存
println(book.stock)
}
//登录
@Cradle[console|logfile]
func login(userName: String, password: String): Bool {
let user = User.getUserByUserName(userName)
return user.passwd == password
}
//用户
@Cradle[console|logfile]
public class User {
public User(var userId: Int64, var userName: String, var passwd: String) {}
//根据用户名称查找用户信息
public static func getUserByUserName(userName: String) {
return User(1, userName, "qD@0532")
}
}
@Cradle[console|logfile]
public class Book {
public Book(var bookName: String, var stock: Int64) {}
public init(bookName: String) {
this.bookName = bookName
this.stock = 0
}
//入库
public func input(count: Int64) {
this.stock += count
return stock
}
//出库
public func output(count: Int64) {
this.stock -= count
return stock
}
}
可以看到,一共只加了四个注解,没有破坏原来函数的结构,既简单明了,又做到了逻辑分离。
下面是运行后的效果,包括输出到控制台的日志和写入到日志文件的日志:
通过上述示例,可以看到,基于仓颉元编程的仓颉宏功能还是很强大的,通过自定义宏可以帮助开发者实现天马行空的想法,在注重性能和效率的企业级开发上更是大有可为。
4.仓颉元编程示例获取
《仓颉语言元编程》是由张磊编写,清华大学出版社出版的一本仓颉元编程学习的入门书籍,该书从元编程的概念开始,逐步讲解仓颉元编程的基础知识、抽象语法树的常用用法,以及如何定义和使用仓颉宏。
该书包括将近60个完整的元编程示例,最新示例代码已全面适配仓颉最新的版本0.51.4,并上传到码云,全部可以免费下载:
https://gitee.com/zl3624/cangjie_meta_programming
- 点赞
- 收藏
- 关注作者
评论(0)