浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
基本函数定义:func 关键字,位置参数,显式返回类型与 return 语句。
package demo
func add(a: Int64, b: Int64): Int64 {
return a + b
}
main() {
let a=20
let b=30
println("${a}+${b}的结果是:${add(a,b)}")
}
四个 Int64 位置参数,import std.math.* 使用 sqrt,返回 Float64 距离值。
package demo
import std.math.*
func distance(x1: Int64, y1: Int64, x2: Int64, y2: Int64): Float64 {
let dx = x2 - x1
let dy = y2 - y1
return sqrt(Float64(dx * dx + dy * dy))
}
main() {
let x1 = 20
let y1 = 30
let x2 = 200
let y2 = 300
println("点A(${x1}, ${y1})到点B(${x2}, ${y2})的距离是:${distance(x1, y1, x2, y2)}")
}
将参数改为命名参数并设置默认值,调用时可全部省略,直接写 distance()。
package demo
import std.math.*
func distance(x1!: Int64=20, y1!: Int64=30, x2!: Int64=200, y2!: Int64=300): Float64 {
let dx = x2 - x1
let dy = y2 - y1
return sqrt(Float64(dx * dx + dy * dy))
}
main() {
println("ab的距离是:${distance()}")
}
函数返回类型可由最后一个表达式推断;myfun() 显式声明返回 Unit 类型。
package demo
import std.math.*
func distance(x1: Float64, y1: Float64, x2: Float64, y2: Float64){
let dx = x2 - x1
let dy = y2 - y1
sqrt(dx*dx+dy*dy)
}
func myfun(): Unit {
let s = "两点距离计算结果:"
print(s)
}
main() {
let x1 = 20.4
let y1 = 30.5
let x2 = 200.5
let y2 = 300.8
myfun()
println("点A(${x1}, ${y1})到点B(${x2}, ${y2})的距离是:${distance(x1, y1, x2, y2)}")
}
concat(str1, str2) 两个位置参数,按声明顺序传入。
package demo
func concat(str1: String, str2: String):String {
return str1 + str2
}
main() {
let s1: String = "Hello, "
let s2: String = "Cangjie!"
let result = concat(s1, s2)
println("${result}")
}
str1 为位置参数,str2! 为命名参数,调用时写 concat(s1, str2: s2)。
package demo
func concat(str1: String, str2!: String):String {
return str1 + str2
}
main() {
let s1: String = "Hello, "
let s2: String = "Cangjie!"
let result = concat(s1,str2:s2)
println("${result}")
}
全部声明为命名参数(str1!, str2!),调用时可写 concat(str2: s2, str1: s1)。
package demo
func concat(str1!: String, str2!: String):String {
return str1 + str2
}
main() {
let s1: String = "Hello,"
let s2: String = "Cangjie!"
let result = concat(str2:s2,str1:s1)// 参数的顺序不同
println("${result}")
}
str2! 设置默认值 "Cangjie!",调用 concat(s1) 时可省略 str2。
package demo
func concat(str1: String, str2!: String= "Cangjie!"):String {
return str1 + str2
}
main() {
let s1= "Hello,"
let result = concat(s1) // 参数个数可以不同
println("${result}")
}
同样的函数,通过 concat(s1, str2: s2) 显式覆盖默认值。
package demo
func concat(str1: String, str2!: String= "Cangjie!"):String {
return str1 + str2
}
main() {
let s1= "Hello,"
let s2= "仓颉!"
let result = concat(s1,str2:s2)// 参数个数可以不同
println("${result}")
}
printAdd 接收一个 (Int64, Int64) -> Int64 类型的函数参数,体现高阶函数思想。
package demo
func printAdd(add: (Int64, Int64) -> Int64, a: Int64, b: Int64): Unit {
println(add(a, b))
}
main() {
// 定义 addFunction 函数,接受两个 Int64 类型的参数并返回它们的和
let addFunction: (Int64, Int64) -> Int64 = { x, y => x + y }
// 调用 printAdd 函数,传入 addFunction 和两个数值作为参数
printAdd(addFunction, 5, 3)
}
returnAdd() 返回类型为 (Int64, Int64) -> Int64,将函数本身作为返回值传递。
package demo
func add(a: Int64, b: Int64): Int64 {
return a + b
}
func returnAdd(): (Int64, Int64) -> Int64 {
return add
}
main() {
// 获取返回的函数
var addFunc = returnAdd()
// 调用返回的函数并传入参数
println(addFunc(1, 2))
}
通过类型标注 let f: (Int64, Int64) -> Int64 = add 将函数赋值给变量。
package demo
func add(p1: Int64, p2: Int64): Int64 {
return p1 + p2
}
main() {
let f: (Int64, Int64) -> Int64 = add
let result = f(1, 2) // 使用变量 f 调用函数 add
println(result) // 输出 3
}
var f = add 在重载情况下有二义性(编译错误);需显式声明类型消除歧义。
package demo
func add(i: Int64, j: Int64) {
i + j
}
func add(i: Float64, j: Float64) {
i + j
}
main() {
var f = add // 错误
var plus: (Int64, Int64) -> Int64 = add // 正确
}
在 foo() 内部定义 nestAdd,并将其作为函数类型返回值传出作用域。
package demo
func foo() {
func nestAdd(a: Int64, b: Int64): Int64 {
return a + b + 3
}
println(nestAdd(1, 2)) // 输出 6
return nestAdd
}
main() {
let f = foo() // f 是 foo 返回的嵌套函数 nestAdd
let x = f(1, 2) // 调用返回的函数
println("result: ${x}") // 输出 result: 6
}
{ => 表达式 } 形式的无参 Lambda,赋值给变量后像普通函数一样调用。
package demo
var helloWorld = { => println("Hello World") }
main(): Int64 {
helloWorld() // 调用并输出 "Hello World!"
return 0
}
var add = { a: Int64, b: Int64 => a + b },参数类型在 Lambda 内标注。
package demo
var add = { a: Int64, b: Int64 => a + b }
main(): Int64 {
let result = add(5, 7)
println("结果是:${result}")
return 0;
}
f({ a2 => a2 + 10 }) 将内联 Lambda 直接作为实参,省去单独定义函数的步骤。
package demo
func f(a1: (Int64) -> Int64): Int64 {
return a1(5)
}
main(): Int64 {
let result = f({ a2 => a2 + 10 })
println("结果是:${result}")
return 0;
}
内部函数 add 捕获外层局部变量 num,通过 returnAddNum() 返回后仍可访问 num。
package demo
func returnAddNum(): (Int64) -> Int64 {
let num: Int64 = 10
// 显式声明 add 的返回类型
func add(a: Int64): Int64 {
return a + num
}
return add
}
main() {
let f = returnAddNum()
println(f(10)) // 输出应为 20
}
嵌套函数 f1 直接访问外层函数 f 中定义的变量 x,展示作用域捕获规则。
package demo
func f() {
let x = 9
func f1() {
println(x)
}
f1()
}
main() {
f()
}
myIf(true) { 100 } 将 Lambda 写在括号外,适合最后一个参数是函数类型的场景。
package demo
// 定义一个接收布尔值和函数类型参数的函数
func myIf(a: Bool, fn: () -> Int64): Int64 {
if (a) {
return fn() // 如果 a 为真,则执行传入的函数并返回结果
} else {
return 0 // 如果 a 为假,返回 0
}
}
// 使用尾随 Lambda 调用 myIf 函数
func test(): Unit {
let result = myIf(true) { // 尾随 Lambda 调用
100 // 当条件为真时,返回 100
}
println("结果: ${result}") // 打印结果
}
main(): Int64 {
test() // 调用 test 函数执行
return 0
}
f { i => i * i } 省略小括号,Lambda 紧跟函数名,代码更简洁。
package demo
// 定义函数 f,接受一个类型为 (Int64) -> Int64 的函数 fn
func f(fn: (Int64) -> Int64): Unit {
let result = fn(2) // 调用传入的函数,并传入 2
println("结果: ${result}") // 输出结果
}
// 测试函数,使用尾随 Lambda 传入一个计算平方的 Lambda 表达式
func test(): Unit {
f { i => i * i } // 尾随 Lambda,计算 i 的平方
}
// 主函数,调用 test 函数
main(): Int64 {
test() // 调用 test 函数,执行计算平方操作
return 0
}
arr |> inc |> sum 将数组依次送入 inc(每元素+1)再送入 sum(求和),链式调用。
package demo
// 定义inc 函数:将数组中的每个元素加 1
func inc(x: Array<Int64>): Array<Int64> {
let s = x.size // 获取数组大小
var i = 0
// 遍历数组,逐个元素加 1
for (e in x where i < s) {
x[i] = e + 1
i++
}
return x
}
// sum 函数:返回数组元素的总和
func sum(x: Array<Int64>): Int64 {
var total = 0
for (item in x) { // 累加数组中的每个元素
total += item
}
return total
}
// 主程序
main(): Int64 {
let arr: Array<Int64> =[1, 3, 5] // 创建一个数组
let result = arr |> inc |> sum // 使用管道操作符依次调用 inc 和 sum
println("结果: ${result}") // 输出结果
return 0
}
f ~> g 等价于 { x => g(f(x)) },先执行 f 再执行 g,组合为新函数。
package demo
// 定义函数 f 和 g
func f(x: Int64): Float64 {
return Float64(x)
}
func g(x: Float64): Float64 {
return x
}
// 主程序
main(): Int64 {
// 使用组合操作符 ~> 将 f 和 g 组合成 fg
var fg = f ~> g // 等价于 { x: Int64 => g(f(x)) }
// 调用组合后的函数 fg
let result = fg(10) // f(10) = 10, g(10.0) = 10.0
println("结果:${result}") // 输出 10.0000
return 0
}
({ x: Int64 => x }) ~> f 将匿名 Lambda 与具名函数 f 组合为新函数。
package demo
// 定义函数 f 和一个 lambda 表达式
func f(x: Int64): Float64 {
return Float64(x)
}
// 主程序
main(): Int64 {
let lambdaComp = ({ x: Int64 => x }) ~> f // 等价于 { x: Int64 => f({x: Int64 => x}(x)) }
// 调用组合后的函数 lambdaComp
let result = lambdaComp(10) // {x => x}(10) -> 10, f(10) = 10.0
println("结果:${result}") // 输出 10.0
return 0
}
h1
package demo
// 定义两个泛型函数 h1 和 h2
func h1<T>(x: T): T {
return x
}
func h2<T>(x: T): T {
return x
}
main(): Int64 {
// 使用组合操作符 ~> 将 h1 和 h2 组合成 hh
var hh = h1<Int64> ~> h2<Int64> // 等价于 { x: Int64 => h2<Int64>(h1<Int64>(x)) }
// 调用组合后的函数 hh
let result = hh(10) // h1(10) = 10, h2(10) = 10
println("结果:${result}") // 输出 10
return 0
}
func sum(arr: Array
package demo
func sum(arr: Array<Int64>) {
var total = 0
for (x in arr) {
total += x
}
return total
}
main() {
println(sum()) // 输出 1
println(sum(1, 2, 3)) // 输出 7
}
arr! 为命名参数时不能变长调用;须用 length(arr: [...]) 形式,否则编译报错。
// 运行错误的例子
package demo
func length(arr!: Array<Int64>) {
return arr.size
}
main() {
println(length()) // 错误,期望 1 个参数,但找到 0 个
println(length(1, 2, 3)) // 错误,期望 1 个参数,但找到 3 个
}
f() 传入 0 个或多个参数时,arr 自动组装为 Array
package demo
func f(arr: Array<Int64>) {
println("array: ${arr}")
}
main() {
f() // 输出 "array: []"
f(1) // 输出 "array: [1]"
f(1, 2) // 输出 "array: [1, 2]"
}
标准求和函数:初始值为 0,演示 sum()=0、sum(1,2,3)=6、sum(10,20)=30。
package demo
func sum(arr: Array<Int64>) {
var total = 0
for (x in arr) {
total += x
}
return total
}
main() {
println(sum()) // 输出 0
println(sum(1, 2, 3)) // 输出 6
println(sum(10, 20)) // 输出 30
}
f(a: Int64, arry: Array
package demo
func f(a: Int64, arry: Array<Int64>) {
println("a: ${a}, array: ${arry}")
}
main() {
f(1,2,3) // 输出 "a: 1, array: [2, 3]"
}
b!: Int64 = 2 使 b 既是命名参数又有默认值,调用时可只传 a。
package demo
func f(a: Int64, b!: Int64 = 2) {
println("a: ${a}, b: ${b}")
}
main() {
f(1) // 输出 "a: 1, b: 2"
f(2) // 输出 "a: 2, b: 2"
f(3) // 输出 "a: 3, b: 2"
}
f(Int64) 与 f(Int64, Float64) 同名但参数个数不同,编译器根据调用自动选择。
package demo
func f(a: Int64): Unit {
println("Function with one Int64 argument: ${a}")
}
func f(a: Int64, b: Float64): Unit {
println("Function with one Int64 and one Float64 argument: ${a}, ${b}")
}
main() {
f(10)
f(10, 3.14)
}
f(Int64) 与 f(Float64) 参数个数相同但类型不同,字面量类型决定调用哪个版本。
package demo
func f(a: Int64): Unit {
println("Function with Int64 argument: ${a}")
}
func f(a: Float64): Unit {
println("Function with Float64 argument: ${a}")
}
main() {
f(10)
f(3.14)
}
f(Int64, Int64) 与 f(Int64, Float64) 第一个参数相同,第二个参数类型不同。
package demo
func f(a: Int64, b: Int64): Unit {
println("Function with two Int64 arguments: ${a}, ${b}")
}
func f(a: Int64, b: Float64): Unit {
println("Function with one Int64 and one Float64 argument: ${a}, ${b}")
}
main() {
f(10, 20)
f(10, 3.14)
}
定义 max(a, b) 函数,用 if-else 返回较大值,体现基本函数定义与调用。
package demo
// 定义一个高阶函数 apply,它接受一个整数数组和一个转换函数作为参数
func apply(arr: Array<Int>, f: (Int) -> Int): Array<Int> {
var result = Array<Int>(arr.size,repeat:0) // 创建与输入数组相同大小的结果数组
for (x in 0..arr.size) {
result[x] = f(arr[x]) // 对arr[x]应用函数f,结果存储到result[x]
}
return result
}
// 示例函数1:求2倍
func double(x: Int): Int {
return x * 2
}
// 示例函数2:求平方
func square(x: Int): Int {
return x * x
}
// 示例函数3:加10
func addTen(x: Int): Int {
return x + 10
}
main() {
// 创建测试数组
var numbers=Array<Int>(5, repeat: 0)
numbers[0] = 1
numbers[1] = 2
numbers[2] = 3
numbers[3] = 4
numbers[4] = 5
println("原始数组: [1, 2, 3, 4, 5]")
// 示例1:使用 double 函数求每个元素的2倍
var doubled = apply(numbers, double)
print("求2倍: [")
for (i in 0..doubled.size) {
print("${doubled[i]}")
if (i < doubled.size - 1) {
print(", ")
}
}
println("]")
// 示例2:使用 square 函数求每个元素的平方
var squared = apply(numbers, square)
print("求平方: [")
for (i in 0..squared.size) {
print("${squared[i]}")
if (i < squared.size - 1) {
print(", ")
}
}
println("]")
// 示例3:使用 addTen 函数给每个元素加10
var addedTen = apply(numbers, addTen)
print("加10: [")
for (i in 0..addedTen.size) {
print("${addedTen[i]}")
if (i < addedTen.size - 1) {
print(", ")
}
}
println("]")
// 示例4:使用匿名函数(lambda表达式)求3倍
var tripled = apply(numbers, {x => x * 3})
print("求3倍(lambda): [")
for (i in 0..tripled.size) {
print("${tripled[i]}")
if (i < tripled.size - 1) {
print(", ")
}
}
println("]")
// 示例5:使用匿名函数求负数
var negated = apply(numbers, {x => -x})
print("求负数(lambda): [")
for (i in 0..negated.size) {
print("${negated[i]}")
if (i < negated.size - 1) {
print(", ")
}
}
println("]")
// 示例6:复合操作 - 先乘2再加5
var complex = apply(numbers, {x => x * 2 + 5})
print("乘2加5(lambda): [")
for (i in 0..complex.size) {
print("${complex[i]}")
if (i < complex.size - 1) {
print(", ")
}
}
println("]")
}
跨包调用示例:hoch/mathops.cj 提供高阶函数,hoch/characters.cj 提供汉字组合,main.cj 统一调用。
package demo.hoch
public func double(x: Int64): Int64 { // 求倍函数
return x * 2
}
public func applyTwice(f: (Int64) -> Int64, value: Int64): Int64 {
return f(f(value)) // 高阶函数:对 value 应用 f 两次
}
package demo.hoch
// 不依赖索引,遍历每个元素,只在不是第一个元素时加分隔符
public func compose(char: String, parts: Array<String>) {
var partsStr = ""
var first = true
for (p in parts) {
if (!first) {
partsStr += "+" // 在后续元素前加分隔符
}
partsStr += p
first = false
}
println("${char} = ${partsStr}")
}
package demo
import demo.hoch.*
main() {
let result = applyTwice(double, 3) // 高阶函数 applyTwice
println("高阶函数调用结果是:${result}")
println("汉字组合是:")
compose("林", ["木", "木"])
compose("森", ["木", "木", "木"])
}
makeAdder() 返回一个捕获常量 5 的 Lambda,体现闭包与函数作为返回值的组合。
package demo
func makeAdder(): (Int64) -> Int64 {
return { x: Int64 => x + 5 }
}
main() {
let add5 = makeAdder()
println("10 + 5 = ${add5(10)}") // 输出:15
}
outer() 内定义 inner(x),inner 捕获 offset=100 并返回 x + offset。
package demo
func outer(): (Int64) -> Int64 {
let offset = 100
func inner(x: Int64): Int64 {
return x + offset
}
return inner
}
main() {
let f = outer()
println(f(200)) // 输出:300
}
getIncrementer() 返回一个闭包,每次调用递增并打印 Counter 类实例的 count 字段。
package demo
main() {
let result = { a: Int64, b: Int64 => a * b }(6, 7)
println("6 * 7 = ${result}") // 输出:42
}
package demo
// 定义一个元组数组,每个元组存储汉字和对应的部件
let partsList = [
("仓", (r'人', r'㔾')),
("颉", (r'吉', r'页'))
]
// 定义分析函数
func analyze(char: String): String {
// 遍历元组数组,查找匹配的汉字
for (entry in partsList) {
if (entry[0] == char) {
// 使用字符串拼接代替 .join()
let partsStr = entry[1][0].toString() + "和" + entry[1][1].toString()
return "${char}由${partsStr}组成"
}
}
return "${char}暂时不支持解析"
}
main(): Int64 {
// 调用 analyze 函数
println(analyze("仓")) // 输出: 仓由人和㔾组成
println(analyze("颉")) // 输出: 颉由吉和页组成
return 0
}