目前仓颉语言只开放了文档,未开放sdk让开发者测试开发。可以申请仓颉的开发者预览版Beta招募,链接Here
类型扩展
添加函数 (swift包含)
仓颉:
extend String {
func printSize() {
print(this.size)
}
}
"123".printSize() // 3
Swift:
extension String {
func printSize() {
print(self.size)
}
}
"123".printSize() // 3
添加属性 (swift不包含)
添加操作符重载 (swift包含)
仓颉:
struct Point {
let x: Int
let y: Int
init(x: Int, y: Int) {...}
operator func +(rhs: Point): Point {
return Point(
this.x + rhs.x,
this.y + rhs.y
)
}
}
let a: Point = ...
let b: Point = ...
let c = a + b
Swift:
struct Point {
let x: Int
let y: Int
init(x: Int, y: Int) {
self.x = x
self.y = y
}
static func +(lhs:Point, rhs: Point) -> Point {
return Point(x:
lhs.x + rhs.x,
y: lhs.y + rhs.y)
}
}
let c: Point = Point(x: 1, y: 1)
let d: Point = Point(x: 2, y: 2)
let e = c + d
实现接口 (swift包含)
仓颉:
sealed interface Integer {}
extend Int8 <: Integer {}
extend Int16 <: Integer {}
extend Int32 <: Integer {}
extend Int64 <: Integer {}
let a: Integer = 123 // ok
Swift:
protocol Integer {}
extension Int8 : Integer {}
let a :Integer = Int8(123)
代数数据类型和模式匹配
仓颉中的枚举定义与使用:
enum BinaryTree {
| Node(value: Int, left: BinaryTree, right: BinaryTree)
| Empty
}
func sumBinaryTree(bt: BinaryTree) {
match (bt) { //match关键字实际是rust语言中的模式匹配关键字。
case Node(v, l, r) =>
v + sumBinaryTree(l) + sumBinaryTree(r)
case Empty => 0
}
}
Swift中的枚举定义与使用:
indirect enum BinaryTree {
case Node(value: Int, left: BinaryTree, right: BinaryTree)
case Empty
}
func sumBinaryTree(bt: BinaryTree) -> Int {
switch bt {
case .Node(let value, let left, let right):
return value + sumBinaryTree(bt: left) + sumBinaryTree(bt: right)
case .Empty:
return 0
}
}
泛型
泛型函数的声明方式几乎一样,尤其是针对泛型类型T的限制,两者都使用where关键字。
仓颉:
func lookup<T>(element: T, arr: Array<T>): Bool where T <: Equatable<T> {
for (e in arr){
if (element == e){
return true
}
}
return false
}
Swift:
func lookup<T>(element: T, arr: Array<T>) -> Bool where T : Equatable {
for e in arr {
if (element == e){
return true
}
}
return false
}
命名参数&参数默认值
仓颉:
func dateOf(year!: Int64, month!: Int64, dayOfMonth!: Int64, timeZone!: TimeZone = TimeZone.Local) {
}
dateOf(year: 2024, month: 6, dayOfMonth: 21) // ok
dateOf(year: 2024, month: 6, dayOfMonth: 21, timeZone: TimeZone.UTC) // ok
Swift:
func dateOf(year: Int64, month: Int64, dayOfMonth: Int64, timeZone: TimeZone = TimeZone.current) {
}
dateOf(year: 2024, month: 6, dayOfMonth: 21) // ok
dateOf(year: 2024, month: 6, dayOfMonth: 21, timeZone: TimeZone.gmt) // ok
尾随lambda(trailing lambda)
仓颉:
func unless(condition: Bool, f: ()->Unit) {
if(!condition) {
f()
}
}
int a = f(...)
unless(a > 0) {
print("no greater than 0")
}
Swift:
func unless(condition: Bool, f: () -> Void) {
if !condition {
f()
}
}
unless(condition: true) {
print("no greater than 0")
}
属性
属性的get/set配置。
仓颉:
x和y是只读的,只有get实现,而color则是可变的,用mut prop修饰,同时具有get和set实现。
class Point {
private let _x: Int
private let _y: Int
private var _color: String
init(x: Int, y: Int, color: String) {...}
prop x: Int {
get() {
Logger.log(level: Debug, "access x")
return _x
}
}
prop y: Int {
get() {
Logger.log(level: Debug, "access y")
return _y
}
}
mut prop color: String {
get() {
Logger.log(level: Debug, "access color")
return _color
}
set(c) {
Logger.log(level: Debug, "reset color to ${c}")
color = c
}
}
}
main() {
let p = Point(0, 0, "red")
let x = p.x // "access x"
let y = p.y // "access y"
p.color = "green" // "reset color to green"
}
Swift:
x和y是只读的,只有get实现,而color则是可变的,同时具有get和set实现。
class Point2 {
private let _x: Int
private let _y: Int
private var _color: String
init(_ x: Int, _ y: Int,_ color: String) {
self._x = x
self._y = y
self._color = color
}
var x: Int {
get {
return _x
}
}
var y: Int {
get {
return _y
}
}
var color: String {
get {
return _color
}
set(c) {
_color = c
}
}
}
let p = Point2(0, 0, "red")
p.x = 100 //error
let x = p.x // "access x"
let y = p.y // "access y"
p.color = "green" // "reset color to green"
空引用安全
在仓颉中,对于任意类型T,都可以有对应的可选类型Option。具有Option类型的变量要么对应一个实际的具有T类型的值v,因此取值为Some(v),要么具有空值,取值为None。
可选类型(Option)是一种 enum 类型,是一个经典的代数数据类型,表示有值或空值两种状态。
在Swift,用来表示变量可空的关键字为Optional.
仓颉:
var a: ?Int = None
a?.toString() // None
a ?? 123 // 123
a = Some(321)
a?.toString() // Some("321")
a ?? 123 // 321
Swift:
var f: Int? = nil
print(f) //nil
print(f ?? 123) // 123
var g = Optional(321)
print(g) //Optional(321)
print(g ?? 123) // 321
值类型
仓颉和Swift都使用struct来实现用户自定义的值类型。
仓颉:
struct Point {
var x: Int
var y: Int
init(x: Int, y: Int) { ... }
...
}
var a = Point(0, 0)
var b = a
a.x = 1
print(b.x) // 0
Swift:
struct Point {
var x: Int
var y: Int
init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
var a1 = Point3(x:0,y: 0)
var b1 = a1
a1.x = 1
print(b1.x) // 0
宏
仓颉:
定义一个名为 DebugLog 的宏:
public macro DebugLog(input: Tokens) {
if (globalConfig.mode == Mode.development) {
return quote( println( ${input} ) )
}
else {
return quote()
}
}
使用 DebugLog 宏:
@DebugLog( expensiveComputation() )
Rust:
use proc_macro;
#[some_attribute]
pub fn some_name(input: TokenStream) -> TokenStream {
}
Actor
使用更简洁的语法来实现异步编程、并发编程中的数据竞争问题。
仓颉:
actor Account {
instance var balance: Int64
init (x: Int64) { this.balance = f1() }
instance func performWithdraw(amount: Int64): Unit {
balance -= amount
}
receiver func withdraw(amount: Int64): Bool {
if (this.balance < amount) {
return false
} else {
this.performWithdraw(amount);
return true
}
}
}
Swift:
注意:这段代码是来自于Swift的官方文档。仓颉的文档示例与swift的文档示例代码基本是一致的,看来仓颉语言应该是参考了Swift语言不少的东西。
actor Account {
var balance: Int = 20// current user balance is 20
// ...
func withdraw(amount: Int) {
guard balance >= amount else {return}
self.balance = balance - amount
}
}
可变性修饰符
可变性修饰符:let 与 var,分别对应不可变和可变属性,
垃圾收集方案
仓颉使用追踪式垃圾回收,类似于java中的基于可达性分析的垃圾回收算法;Swift使用引用计数法。(Swift有weak关键字)
管道(Pipeline)操作符
func double(a: Int) {
a * 2
}
func increment(a: Int) {
a + 1
}
double(increment(double(double(5)))) // 42
5 |> double |> double |> increment |> double // 42
类型扩展可添加属性
try-with-resources
该特性应该借鉴自java.
try (input = MyResource(),
output = MyResource()) {
while (input.hasNextLine()) {
let lineString = input.readLine()
output.writeLine(lineString)
}
}
溢出检查
这个机制使得大多数时候,整数溢出都会及时被感知,避免造成业务隐患。
@OverflowWrapping
func test(x: Int8, y: Int8) { // if x equals to 127 and y equals to 3
let z = x + y // z equals to -126
}
并发编程
线程创建简单且占用内存量小。使用Spawn关键字来创建新线程。
func fetch_data(url: String) {
let response = http_get(url)
process(response)
}
main() {
let urls = ["https://example.com/data1", "https://example.com/data2", ...]
let futures = ArrayList<Future<Unit>>()
for (url in urls) {
let fut = spawn { fetch_data(url) } // 创建仓颉线程进行网络请求
futures.append(fut)
}
for (fut in futures) { // 等待所有仓颉线程完成
fut.get()
}
}
无锁并发对象。
运行时库提供了一系列的原子操作对象,尽量让开发者少使用互斥量或者锁来实现线程安全。同时提供的这些原子操作对象,针对多线程操作做了优化,其效率比单纯使用互斥量要高得多。