第五篇博客
前言
本文将继续学习和研究仓颉函数
一、仓颉的函数
1.函数的命名变量和非命名变量
仓颉函数存在多个命名变量,在调用时顺序可以调换
public func execFun1(a!:Int64,b!:Int64)
{
println("1.${a},${b}")
}
public func call()
{
execFun1(b:200, a: 100)
}
2.函数的返回值
可以对函数的返回值类型做出要求,函数():返回值类型{ }
如果希望根据具体情况转换返回值类型,可以依靠之前学过的,所有类型的父类Any和转换的关键字as进行类型的转换
public func execFun1(a:Any):Any
{
a
}
public func call()
{
var result = execFun1("100")
if(result is Int64)
{
let a = (result as Int64).getOrThrow()
println("${a}")
}
else{
println("不能转换")
}
}
3.函数重载
同名函数,参数不同是方法重载
实际调用哪个函数由调用时给出的参数控制
而当局部变量和全局变量名称重合时,就近原则,决定打印哪个数值
var a = 100
public func show()
{
println("result:${a}")
}
public func show(a:Int64)
{
var a1 = a
a1 =200
println("${a}")
}
public func call()
{
show(10) //10
show() //result:100
}
4.递归函数
递归函数就是函数调用自己
函数不断自身调用自己递归需要有出口,就是一个递归头
//1.调用阶段
//2.返回阶段
//1.调用阶段
//2.返回阶段
public func fn(n:Int64):Int64{
if(n==0)
{
1 // 递归出口 返回阶段,开始逐层返回
}
else{
fn(n-1)*n
}
}
public func call()
{
println(fn(4)) //24
}
5.函数嵌套
注意没有规定返回值类型,因为不清楚返回值类型hsi'shen
public func Outer(){
func Inner()
{
println("这是内部函数Inner")
}
Inner
}
public func call()
{
let fn = Outer()
fn()
}
二、面向函数式编程
1.面向函数思想
一个函数可以等于一个变量 一个函数可以赋值给一个变量
值得注意的是一般来说变量是有类型的,当把函数赋值给变量时,类型如何定义?
变量类型 (a1:Int64,b1:Int64)->Int64 【(函数参数)->函数返回值类型 】
当直接将函数赋值给变量时,根据自动类型推断,也可直接赋值
public func add(a:Int64,b:Int64):Int64{
a+b
}public func call()
{
//面向函数式编程思想 一个函数可以等于一个变量 一个函数可以赋值给一个变量
var f1 : (a1:Int64,b1:Int64)->Int64 = add//f1是个函数变量
println(f1(10,20))
var f2 = add //自动类型推断}
public func add(a:Int64,b:Int64):Int64{
a+b
}public func add(a:String,b:String):String{
a+b
}public func call()
{
//面向函数式编程思想 一个函数可以等于一个变量 一个函数可以赋值给一个变量
var f1 : (a1:Int64,b1:Int64)->Int64 = add//f1是个函数变量
println(f1(10,20))//错误
// var f2 = add //自动类型推断,不能自行推断//存在 (a1:Int64,b1:Int64)->Int64和(a:String,b:String)->String两种类型可能性
}
仓颉的方法作为另外一个方法的参数进行传递
//函数可以作为方法的参数
public func add(a:Int64,b:Int64):Int64
{
a+b
}public func sub(a:Int64,b:Int64):Int64
{
a-b
}public func execFun1(a:Int64,b:Int64,op:(a:Int64,b:Int64)->Int64):Int64{
op(a,b)
}//op是个函数类型,指向哪个具体的实现方法,是由业务决定的
//参数和返回值类型保持一致即可
public func call()
{
execFun1(10,20,sub)
execFun1(10,20,add)
}
2.切面编程思想
切面编程思想就是就是切方法,在进入主方法之前,进行前置控制,通过切入的面来判断,是否可以执行主方法
切面分为五类:
前置切面:在方法执行之前执行的切入,权限控制
环绕切面:在方法执行的前后都执行的切入,缓存机制
异常通知:在方法抛出异常时执行,操作的图文
后置切面:在方法执行之后执行,不管方法是否发生异常,日志
最终切面:在方法正常返回后执行,总结
//前置切面
public func before(a: Int64): Bool {
if (a > 18) {
true
} else {
false
}
}
//主方法
public func execAction() {
println("你可以毕业")
}
public func execBank(){
println("你可以去银行办理贷款")
}
public func execFun2(a: Int64, be: (a: Int64) -> Bool, action: () -> Unit) {
//切面编程思想 切面就是切方法,在进入主方法之前,进行前置控制
if (before(a)) {
action()
} else {
println("你没有能力去执行")
}
}
public func call(){
execFun2(22,before,execAction) //你可以毕业
execFun2(18,before,execBank) //你没有能力去执行
}
以上代码是前置切面编程思想,通过前置控制,判断主方法是否执行
需要注意的是进行前置控制时,注意返回函数类型并给定出口,以使得在没有条件满足时调用,否则会出现报错
public func add(a: Int64, b: Int64): Any {
a + b
}
public func sub(a: Int64, b: Int64): Any {
a - b
}
public func any(a: Int64, b: Int64): Any {
println("不满足条件")
}
public func exec(op: String): (Int64, Int64) -> Any {
if (op == "+") {
return add //return可以省略
} else if (op == "-") {
return sub
}
any //需要一个出口,没有条件满足时进行调用
}
public func call() {
var result = exec("*")(100, 200)
let re = (result as Int64).getOrThrow()
println("${re}")
}
继承是 Son< :Father
函数类型赋值是var f1:(参数)-> 返回值类型= 方法名 要求是方法名和被赋值函数类型一致
3.lamdba表达式
lamdba就是匿名函数,所谓的匿名函数,就是没有名字的函数,就是函数的具体实现
var f1 : ( )->Unit = 没有名字的方法 (lamdba表达式)
分为两种调用赋值调用和立即调用
public func exec1()
{
var f1: ()->Unit = { =>println("这是lamdba表达式")}
f1()
}public func exec2()
{
//立即调用{ =>println("这是lamdba表达式")}() //需要加括号表示函数调用
}public func exec3(){
var f2:(Int64,Int64)->Int64 = {a:Int64,b:Int64 => a+b}
println(f2(30,40))//带参数的立即调用
{a:Int64,b:Int64 =>println("${a+b}")}(10,20)
}
lamdba表达式做为方法的参数
public func execOne(a:Int64,b:Int64,op:(Int64,Int64)->Int64):Int64{
op(a,b)
}
public func call()
{
execOne(10,20, {a,b =>a*b})
}
lamdba表达式做为方法体
public func op():(String,String)->String{
{a,b=>a+b}
}
public func call()
{
// lamdba函数表达式的参数和返回值类型和函数保持一致
println(op()("10","20")) //输出结果为1020
}
调用lamaba函数
public func Outer(flag:Bool):(Int64,Int64)->Int64
{
if(true)
{
{a,b=>a+b}
}
else{
{a,b=>a-b}
}
}
三.枚举类型
仓颉类型:
1. 基本数据类型 值类型: Int、String、 struct类型
2. 引用类型 类,接口和枚举类型
枚举类型是个固定的取值类型
枚举类型关键字enum
枚举类型的值必须大写,值用竖线分割
枚举类型可以有实例函数和静态函数,不能有构造函数和属性设计器
public enum Famialy {
| FATHER | MOTHER | SON // 枚举类型的值必须大写//枚举类型可以有实例函数和静态函数,不能有构造函数和属性设计器
public func execFamialy() {
println("枚举类型的函数")
}
}public func call() {
var f = Famialy.FATHER
f.execFamialy()
}
枚举类型和结构体都可以继承接口
public interface A{
}
//一个枚举类型可以继承一个接口
public enum Values <: A{
|FATHER|MONTHER
}
public struct User <:A {
}
利用枚举函数进行模式匹配
public enum Fam {
| FATHER | MONTHER | SON
}public func execEnum1(v: Fam): Unit {
match (v) {
case FATHER => println("这是父亲") //枚举类型进行模式匹配时,每个元素都需要匹配上
case MONTHER => println("这是母亲")
case SON => println("这是儿子")
}
}public func execEnum2(v: Fam): String {
let result = match (v) {
case FATHER => "父亲"
case MONTHER => "母亲"
case SON => "儿子"
}
result
}
总结
本文深入探讨了仓颉函数的多个方面,包括函数的命名变量与非命名变量、返回值类型、函数重载、递归函数、函数嵌套等。文章还介绍了面向函数式编程的思想,如函数作为变量赋值、切面编程思想、lambda表达式的使用等。此外,文中还涉及了枚举类型的基本概念及其在仓颉语言中的应用,包括枚举类型的定义、实例函数、静态函数以及枚举类型与接口的继承关系。通过这些内容,本文为读者提供了仓颉函数编程的全面视角,帮助理解其核心概念和高级特性。
更多推荐


所有评论(0)