(仓颉) 仓颉语言入门

2024-09-07 16:44
文章标签 语言 入门 仓颉

本文主要是介绍(仓颉) 仓颉语言入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • ⭐前言
  • 🔠1 基本概念
    • 🔤Hello World
    • 🔤标识符
    • 🔤内置类型
    • 🔤if表达式
    • 🔤for表达式
    • 🔤while表达式
    • 🔤demo 手动计算Π
  • 🔠2 函数
    • 🔤普通函数
    • 🔤lambda
    • 🔤demo 递归遍历目录
  • 🔠3 枚举
    • 🔤enum
    • 🔤match表达式
    • 🔤option 解析数字
    • 🔤demo 计算表达式
  • 🔠4 struct
    • 🔤值类型
    • 🔤二叉树
  • 🔠5 calss
    • 🔤引用类型
    • 🔤继承
    • 🔤prop 属性
  • 🔠6 接口与扩展
    • 🔤interface
    • 🔤extend
    • 🔤泛型
  • 🔠7 异常处理
    • 🔤try catch finally
  • 🔠8 并发编程
    • 🔤Future
  • 🔠9 跨语言互操作
  • 🔠10 宏
    • 🔤macro
  • ⭐END
    • 🌟交流方式

⭐前言

仓颉-鸿蒙原生应用编程语言-华为开发者联盟 (huawei.com)

初识仓颉语言-仓颉编程语言开发指南-学习仓颉语言 - 华为HarmonyOS开发者 (huawei.com)

【原创】仓颉编程语言入门教程

楼主作为主语言C++,副语言python。仅做基础的入门了解。

本文不做任何格外的语法说明,仅在代码中用简短的注释辅助。

下文均为教学视频中的实例demo(上方的视频也出现在官网的视频一栏中)。

本文所有代码均在下方的在线编译器中进行尝试。

除了最后两章,9,10无法进行单文件操作其余均有验证。

仓颉 Playground (zxilly.dev)

https://github.com/Zxilly/playground-cj

仓颉版本 0.54.3

package cangjie// 编写你的第一个仓颉程序
main(): Int64 {println("你好,仓颉!")return 0
}

🔠1 基本概念

🔤Hello World

// main 可以没有返回值
main() {println("你好,仓颉!")
}

🔤标识符

main() {// 普通变量let num = 10let ___x = "___Str"println(num)println(___x)// 原始表示符// 用于将关键字作为标识符let `for` = "这是一个将for关键字用作原始标识符"println(`for`)
}

🔤内置类型

main() {/*** 字面量后缀* 整形* Int8  -> i8* Uint8 -> u8* 浮点型* Float16 -> f16*/let a: Int64 = 2024let b = 67u8let c: Float64 = 6.21let d: Bool = true || falseprintln(d)// 字符类型,表示一个 unicode 字符// 运行下来双引号也可以运行let e: Rune = '仓'let f: Rune = '\u{9889}'println("${e} ${f}")// 单行字符串let g: String = "Cang" + "jie"let h: String = """第1行,这是多行字符串第2行
"""// 插值字符串// 要求表达式类型实现了 ToString 接口let i: String = "Cangjie${a}"println("${h}${i}")// 引用类型数组let j: Array<UInt8> = [1u8, 2u8]// 值类型数组// 没有 ToString// let k: VArray<Rune, $2> = ['C', 'J']let k: VArray<Rune, $2> = [e, f]println("引用类型数组${j}")// 元组类型let l: (Int64, Float64) = (2024, 9.6)// expected 'Struct-String', found 'Tuple<Int64, Float64>'// println(l)// 区间类型// 主要用于for in表达式中let m: Range<Int64> = 2019..2024// expected 'Struct-String', found 'Struct-Range<Int64>'// println(m)
}

🔤if表达式

import std.random.*main() {let speed = Random().nextFloat64() + 20.0println("${speed} km/s")// if 表达式// 类似于 gcc 中的大括号表达式let level = if (speed > 16.7) {"第3宇宙速度"} else if (speed > 11.2) {"第2宇宙速度"} else if (speed > 7.9) {"第1宇宙速度"} else {"第0宇宙速度"}println(level)
}

🔤for表达式

main() {// 1. forvar sum = 0// range(1, 100, 2)for (i in 1..99 : 2) {sum += i}println(sum)// 2. forlet arr = [(1, 2), (3, 4)]// 元组可以解构for ((x, y) in arr) {println("x=${x} y=${y}")}// 3. forvar num = 2// 用 _ 作为占用,避免编译器警告for (_ in 0..5) {num *= num}// 4. for// 当 where 为 true 才执行循环体for (i in 0..10 where i % 2 == 1) {println(i)}
}

🔤while表达式

main() {var result = 0.0var lower = 1.0var upper = 2.0while (upper - lower > 1.0E-10) {result = (lower + upper) / 2.0if (result ** 2 - 2.0 > 0.0) {upper = result} else {lower = result}}println("√2 ≈ ${result}")
}

🔤demo 手动计算Π

// 在在线仓颉Playground 中运行失败
// from std import random.*
// from std import math.*
import std.random.*
import std.math.*main() {/*** 手动计算圆周率* 在一个正方形中随机投点*/const N = 10000var n: UInt32 = 0let random = Random()for (_ in 0..N) {let x = random.nextFloat64()let y = random.nextFloat64()if ((x - 0.5) ** 2 + (y - 0.5) ** 2 < 0.25) {n++}}let pi = Float64(n) / Float64(N) * 4.0println("Π = ${pi}")println("deviation: ${abs(Float64.PI - pi)}")
}

🔠2 函数

🔤普通函数

func void() {// pass
}// 将函数作为参数
func node(value: Int32, left!: () -> Unit = void, right!: () -> Unit = void) {// 二叉树的中序遍历func show() {left()print(value)right()}return show
}main() {let tree = node(0,left: node(1, left: node(2, right: node(3))),right: node(4, left: node(5), right: node(6)))tree()
}

🔤lambda

func iter(n: Int64, x0: Float64, f: (Float64) -> Float64) {var x = x0for (_ in 0..n) {print("${x}, ")x = f(x)}println("${x}")
}main() {// lambda 表达式// { 参数列表 => 函数体 }// { params => block }// 周期3iter(5, 0.8, {x: Float64 => 1.0 / (1.0 - x)})// 没有周期,产生未随机数iter(10, 0.8, {x: Float64 => 4.0 * x * (1.0 - x)})
}

🔤demo 递归遍历目录

import std.fs.*func forEachFileDo(root: Path, handler: (Path) -> Unit): Unit {let current = Directory(root)for (file in current.files()) {handler(file.path)}for (directory in current.directories()) {forEachFileDo(directory.path, handler)}
}main() {forEachFileDo(Path("."), {path: Path => println(path)})
}

🔠3 枚举

🔤enum

enum Tree {// 枚举项Empty | Leaf(Int64) | Node(Int64, Tree, Tree)// 成员函数public func traverse(): Unit {match (this) {case Empty => ()case Leaf(value) => print(value)case Node(value, left, right) =>left.traverse()print(value)right.traverse()}}public static func generate(depth: UInt8): Tree {if (depth == 1) {return Leaf(1)}return Node(Int64(depth),generate(depth - 1),generate(depth - 1))}
}main() {let tree = Node(1,Node(2, Node(3, Empty, Leaf(4)), Empty),Node(5, Leaf(6), Leaf(7)))tree.traverse()println()let fullTree = Tree.generate(5)fullTree.traverse()
}

🔤match表达式

func fib(n: Int64): Int64 {// math 表达式match (n) {case 0 | 1 => ncase other where other > 0 => fib(other - 1) + fib(other - 2)case _ => 0}
}main() {println(fib(-1))for (i in 1..=10) {print("${fib(i)} ")}
}

🔤option 解析数字

func parseInt(text: String): Option<Int64> {if (text.isEmpty() || text == ".") {return None}var sign = if (text[0] == 45u8) {1} else {0}var sum = 0for (i in sign..text.size) {if (text[i] > 57u8 || text[i] < 48u8) {return None}let digit = Int64(text[i] - 48u8)sum = 10 * sum + digit}// 自动包装为 optionreturn if (sign == 1) {-sum} else {sum}
}main() {let number = parseInt("-123456")// getOrThrow 从 Option 取值println(number.getOrThrow())let result = parseInt("123-456")if (result.isNone()) {println("parse failed")}
}

🔤demo 计算表达式

enum Expr {Num(Float64)| Add(Expr, Expr)| Sub(Expr, Expr)| Mul(Expr, Expr)| Div(Expr, Expr)public func calc(): Float64 {match (this) {case Num(number) => numbercase Add(a, b) => a.calc() + b.calc()case Sub(a, b) => a.calc() - b.calc()case Mul(a, b) => a.calc() * b.calc()case Div(a, b) => a.calc() / b.calc()}}public operator func +(that: Expr): Expr {return Add(this, that)}public operator func -(that: Expr): Expr {return Sub(this, that)}public operator func *(that: Expr): Expr {return Mul(this, that)}public operator func /(that: Expr): Expr {return Div(this, that)}
}main() {let x = Num(1.2) + Num(3.4) + Num(2.0) - Num(1.0) / Num(2.0)println(x.calc())
}

🔠4 struct

🔤值类型

struct Point {static let name = "Point"// 主构造函数// 自动成为成员变量Point(private var x: Float64, private var y: Float64) {println("Create a point: (${x}, ${y})")}public func copy() {return this}// 用 mut 修饰可以使用 this 引用当前实例public mut func set(x: Float64, y: Float64) {this.x = xthis.y = y}public func show() {println("Visit the point: (${x}, ${y})")}
}main() {println(Point.name)let p1 = Point(3.0, 4.0)var p2 = p1.copy()p2.set(1.0, 2.0)p1.show()p2.show()
}

🔤二叉树

struct Node {public Node(var value: Int32, let left!: ?Node = None, let right!: ?Node = None) {}public func traverse(): Unit {// Option 类型的语法糖left?.traverse()print(value)right?.traverse()}static let name: String// 静态构造函数static init() {name = "Binary Tree"}public static func intro() {println(name)}
}main() {Node.intro()let root = Node(1,left: Node(2, left: Node(3, right: Node(4))),right: Node(5, left: Node(6), right: Node(7)))root.traverse()
}

🔠5 calss

🔤引用类型

class Point {static let name = "Point"public Point(private var x: Float64, private var y: Float64) {println("Create a point: {${x}, ${y}}")}// this 是当前的引用public func ref() {return this}public func set(x: Float64, y: Float64) {this.x = xthis.y = y}public func show() {println("Visit the point: (${x}, ${y})")}
}main() {println(Point.name)let p1 = Point(3.0, 4.0)var p2 = p1.ref()p2.set(1.0, 2.0)p1.show()p2.show()
}

🔤继承

// 使用了 open 关键字的才能被继承
open class NodeA {public NodeA(protected var value: String,protected let left!: ?NodeA = None,protected let right!: ?NodeA = None) {}// 中序遍历public open func traverse(): Unit {left?.traverse()print(value)right?.traverse()}
}class NodeB <: NodeA {public init(value: String,left!: ?NodeA = None,right!: ?NodeA = None) {super(value, left: left, right: right)}// 前序遍历public func traverse(): Unit {print(value)left?.traverse()right?.traverse()}
}main() {let root = NodeA('a',left: NodeA('b', left: NodeA('c', right: NodeA('d'))),right: NodeB('e', left: NodeB('f'), right: NodeB('g')))root.traverse()
}

🔤prop 属性

class Node {private var value: Int64 = 0public Node(private var name: String,private let left!: ?Node = None,private let right!: ?Node = None) {}// 是 class 不是 struct// 属性,mut 中才能定义set// 此处属性名:param// 这里的目的是和成员变量 value 进行关联public mut prop param: Int64 {get() {value}set(number) {value = numberupdate()left?.param = number / 2right?.param = number / 2}}private func update() {println("${name} has been updated to ${value}")}
}main() {var root = Node('a',left: Node('b', left: Node('c', right: Node('d'))),right: Node('e', left: Node('f'), right: Node('g')))println(root.param)root.param = 128
}

🔠6 接口与扩展

🔤interface

import std.math.*interface Slot {func compute(t: Float64): Float64operator func <<(that: Slot): Slot {return this}operator func >>(that: Slot): Slot {that << thisreturn this}
}extend Float64 <: Slot {public func compute(t: Float64): Float64 {return this}
}class Wave <: Slot {public Wave(let freq: Float64, let phi: Float64) {}public func compute(t: Float64): Float64 {return sin(2.0 * Float64.PI * freq * t + phi)}
}class Mut <: Slot {public Mut(let a: Slot, let b: Slot) {}public func compute(t: Float64): Float64 {a.compute(t) * b.compute(t)}
}class Integrator <: Slot {var input: ?Slot = Nonevar sum = 0.0public Integrator(let dt: Float64) {}public func compute(t: Float64): Float64 {sum += dt * input.getOrThrow().compute(t)return sum}public operator func <<(that: Slot): Slot {input = Some(that)this}
}main() {const DT = 0.001let left = 1.0 >> Integrator(DT)let right = Wave(0.5 / Float64.PI, 0.0)let flow = Mut(left, right) >> Integrator(DT)for (t in 0..1000) {println(flow.compute(Float64(t) * DT))}
}

🔤extend

// 默认情况下,扩展仅在当前包中有效
extend String {operator func >>(n: Int64): String {if (n <= 0) {return this.clone()}let size = this.sizelet offset = size - n % sizethis[offset..size] + this[0..offset]}
}main() {let text = "Cangjie2024"println(text >> 2 >> 2)
}

🔤泛型

class Node<T> where T <: ToString {public Node(protected var value: T,protected let left!: ?Node<T> = None,protected let right!: ?Node<T> = None) {}// 中序遍历public func traverse(): Unit {left?.traverse()print(value)right?.traverse()}
}main() {let tree1 = Node('a',left: Node('b', left: Node('c', right: Node('d'))),right: Node('e', left: Node('f'), right: Node('g')))tree1.traverse()println()let tree2 = Node(1,left: Node(2, left: Node(3, right: Node(4))),right: Node(5, left: Node(6), right: Node(7)))tree2.traverse()
}

🔠7 异常处理

🔤try catch finally

class ParseException <: Exception {public init() {super("Parse Failed")}
}func parseInt(text: String): Int64 {if (text.isEmpty() || text == ".") {throw ParseException()}var sign = if (text[0] == 45u8) {1} else {0}var sum = 0for (i in sign..text.size) {if (text[i] > 57u8 || text[i] < 48u8) {throw ParseException()}let digit = Int64(text[i] - 48u8)sum = 10 * sum + digit}// 自动包装为 optionreturn if (sign == 1) {-sum} else {sum}
}main() {println(parseInt("-123456"))let number = try {parseInt("123-456")} catch (e: ParseException) {println("not an integer")0}println(number)try {parseInt("123x456")println(parseInt("-123456"))} catch (e: ParseException) {println(e.message)} finally {println("clean up")}// parseInt("x123456")println("end")
}

🔠8 并发编程

🔤Future

import std.collection.*
import std.random.*
import std.math.*const M = 200000
const N = 16func task(): Int64 {var n: Int64 = 0let random = Random()for (_ in 0..M) {let x = random.nextFloat64()let y = random.nextFloat64()if ((x - 0.5) ** 2 + (y - 0.5) ** 2 < 0.25) {n++}}return n
}main() {let futures = ArrayList<Future<Int64>>()for (_ in 0..N) {let future = spawn {task()}futures.append(future)}var n = 0for (future in futures) {n += future.get()}let pi = Float64(n) / Float64(M * N) * 4.0println("Π = ${pi}")println("deviation: ${abs(Float64.PI - pi)}")
}

🔠9 跨语言互操作

🔠10 宏

🔤macro

// macro.cj
// 宏需要定义在宏包
macro package meta
import std.ast.*public macro transform(tokens: Tokens): Tokens {for (token in tokens) {println("${token.value}\t\t${token.kind}")}println("--------------")return tokens
}// main.cj
import meta.*@transform
func add(x: Int64, y: Int64) {return x + y
}main() {@transform(add(1, 2))
}



⭐END

🌟交流方式

⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区

关注我,学习更多C/C++,python,算法,软件工程,计算机知识

B站:

👨‍💻主页:天赐细莲 bilibili

这篇关于(仓颉) 仓颉语言入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145589

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ