Swift4 函数, 元组, 运算符

创建: 2018/02/19

完成: 2018/02/19

更新: 2018/02/25 修改标题 [Swift4 函数] -> [Swift4 函数, 元组, 运算符]

更新 :2018/03/30 补充不带参数的函数声明的例

 

【任务表】TODO

 

 函数定义的基础
 函数定义的概要

  简单的声明方法

func 函数名 (参数: 类型) -> 型 { //参数可多个,也可省略。返回类型可省略
    ...
}

 函数内部也可以定义函数 

 带标签

  参数名是默认标签,要自定义就在前面加

func 函数名(标签名 变量名:型) -> 型 {
    ...
}

 ● 哪怕函数名相同, 标签名不同,函数也就不同

 ● 标签名可以重复

func sample() {} // 不带参数, 不带返回值。 不带参数也不能省略()

func sample(a a1: Int, b a2: Int) -> Bool {} //

func sample(AAAAA a1: Int, b a2: Int) -> Bool {} //标签不同,和上一个不是一个函数


func sample(X a1: Int, X a2: Int) -> Bool {} //标签可以相同

func sample(_ a1: Int, _ a2: Int) -> Bool {} // 呼出时省略标签

 

 内部完全不用的参数  
func sample(target: Int, _: Bool) -> Bool {} // 完全不用的参数名就_

注:

 ● 参数名_和标签名_的区别

  func test(a: Int, _:Bool) {}

  func test(aa: Int, _ a: Bool) {}

 呼出时: 参数名_的 test(a: Int, Bool)

            标签名_的 test(aa: Int, a: Bool)

 通配符_

 ● 不用声明,能和一切配合

 ● 表示没有值, 无视

_ = 1 // 代入例

for _ in 0..<10 {} //循环例

 

   
   
   
   
   
   
 函数定义的选项

 改变参数

 (相当于C的指针)

 
func 函数名(sample: inout 类型) -> 类型 {}

 ● 型前面加上inout

呼出

sample(sample: &1)

 

 设定默认值 

 不能既有默认值又是inout

func sample(target t: Int = 1) {} // 型后面 = 值

 ● 设定默认值参数的右边的没默认值的参数都设定标签,不设定不能省略有默认值的

 ● 呼出时参数按顺序写

 无法改变传入的值

  参数的值不能被改变(改变报错), 要改变,定义同名量

func sample(a: Int) {
    var a = a
    ...
}

 

 允许不用返回值

 @discardableResult

@discardableResult
func sample(...) {
    ...
}

 

 嵌套函数

 函数内部也可以有函数

 ● 最外側函数不用考虑先后

 ● 内部的函数有先后

   
   
   
   
   
 重载(overload)
 重载

 同一个函数名,参数的类型或者数量或者标签不同或者返回类型不同就是重载

 ● 参数的数量

 ● 标签不同

 ● 参数的类型, 最外部可以。内部的嵌套函数不能只有此处不同

 ● 返回类型不同, 最外部可以。内部的嵌套函数不能只有此处不同

 函数的文档表达方式  
函数名(标签:)

sample(a:b:c) // func sample(a: Int, b: Double, c: Bool)
sample(_:_:) // func sample(_ a: Int, _ b: Int)

 

   
 元组(tuple)
 元组

 ● 多个数据的组合

 ● 不能添加属性和方法

 ● 多用在函数返回值

 ● 不应该用元组为基础去生成复杂的数据结构,用结构体和类 

var 变量: (类型, 类型, ...) 

var sample : (String, Int) = ("sample", 1)

 

获取内部元素, .0, .1, ...

sample.0 // "sample"

 

 代入 

 ● 代入时候必须型相同

 ● 可以用元组一次代入多个

let info = (2018, 2, 19)
let (y, m ,d) = info // y = 2018, m = 2, d = 19

 

 返回元组  
func sample() -> (Double, Double) {}

 ● 一个元素的元组自动看做元素本身

 ● 没有元素的元组()别名Void

 ● 返回值永远是元组

 ● 可以有标签

func sample() -> (fst: Double, snd: Double) {}

 

 带标签的元组  
(标签: 类型, 标签: 类型)

var sample: (fst: Int, snd: Int) = (fst: 0, snd: 1)

 ● 只有一部分有标签也可以

 带标签的元组的代入

 ● 只能和相同标签的元组或者没有标签的元组相互代入

 ● 标签顺序变化也没事

 ● 标签不同的类转换以后可以代入

 

as

 

 元组的比较

 ● 限制: 同型,无视标签,最多6个元素,元素不能有元组, 元素必须可以进行大小比较(Bool无法比大小) 

 ● 按第一个第二个...的顺序比较

   
   
   
   
 Swift的运算符
 运算符的优先级

 后置运算符>前置运算符>二项运算符

 二项运算符的优先度: 由高到低从上往下

 

运算符 优先度群

结合规则

 <- 从右往左 +(+p)  p+(q+r)

 -> 从左往右 (p+)+  (p+q)+r

 x  没有

<<

>>

&<<

&>>

BitwiseShiftPrecedence  x

*

/

%

&

&*

MultiplicationPrecedence  ->

+

-

|

^

&+

&-

AdditionPrecedence ->

..<

...

RangeFormationPrecedence x

is

as  as? as!

CastingPrecedence x
?? NilCoalescingPrecedence <-

<    <=

>    >=

~=

==   !=

===  !==

ComparisonPrecedemce x
&& LogicalConjunctionPrecedence ->
|| LogicalConjunctionPrecedence ->
con ? ex1 : ex2 TernaryPrecedence <-

= += -= *= /=

%= &= ^= |=

<<= >>=

&<<= &>>=

AssignmentPrecedence <-
     

 

 除余

 a%b = c

 c的符号总是和a一致

 比特运算符和移位运算符

 ● 比特运算符和C规则一样: &, &=, |, |=, ^, ^=

 ● 移位运算符也和C规则一样, >>, >>=, <<, <<=

 ● 安全的移位运算符(masking shift, 不会超出范围) &<<, &<<=, &>>, &>>=

 溢出运算符

 &+, &-, &* 

 超出取值范围或者低于取值范围自动转换,不报错

    # TODO: Supply [补充nill, as/as?/as!, is, ===, !==, ~=  p59]
   
   
   
   
   
 运算符的定义 
 运算符的声明

分类

 ● (1)定义全新的运算符

 ● (2)已有的运算符添加新的用法

    (a)单项运算符定义二项,或者相反

    (b)现有运算符运用于新型上

 

(1), (2)(a)的情况需要声明运算符(最外侧,位置任意)

// 二项运算符
infix operator 运算符 (: 优先群)
// 前置运算符
prefix operator 运算符
// 后置运算符
postfix operator 运算符

 ● 不指定优先群的默认DefaultPrecedence(只是比三项运算符高, 连续用要自己用括号)

 ● 一旦定义了就不能改变优先度和结合法则

 可以作为运算符的字符串

 可用的字符, 一个或多个组合成新的运算符

/ = - + ! * % < > & | ^ ~ ?
. //必须在开头要有.才能包含.
// 其他能用的字符不好打,无视

不能用的组合

 

 =   代入以外,泛型也用
 ->  函数声明的返回值处用
 .  命名空间使用
 //  单行注释
 /*  多行注释开头
 */  多行注释结尾
 ?  三项运算符, 可选链等
 &

 不可用做前置运算符

 inout参数的指定时用

 <

 不能用作前置运算符

 类型参数<T>的括号

 >  

 不能用作后置运算符

 类型参数<T>的括号

 !

 不能用作后置运算符

 开示运算符(打开optional)

 

 二项运算符的定义  
infix operator 运算符 ( : 优先群) // 把指定符号作为二项运算符的声明
func 运算符 (左参数, 右参数) -> 类型 {
    ...
}

infix operator <|<| // 二项运算符, 右边的数字添加到左侧的字符串上
func <|<| (lhand: String, rhand: Int) -> String {
    return lhand + "\(rhand)"
}

// 使用
print("hello, " <|<| 6) // hello, 6

 ● 运算符的定义函数参数不能有标签

 

 单向运算符的定义
prefix/postfix operator 运算符 // 单项运算符的声明
prefix/postfix func 运算符(参数) -> 类型 { // 单项运算符的定义
    ...
}

 例 

prefix operator ^| // 前置运算符, 把数字转换成字符串
prefix func ^|(num: Int) -> String {
    return "\(num)"
}

// 使用
print("前置运算符测试: " + ^|6) // 前置运算符测试: 6

 

 改变参数  需要改变的地方的类型加上inout
 自定义优先群

 写在最顶层

precedencegroup 优先群名 {
    (associativity: ) //结合规则, right, left, none. 默认none
    (higherThan: 其他的优先群名) // 优先度
    (lowerThan: 其他的优先群名) // 优先度
    (assignment: 值) // true, false
}

# TODO: Supply [补充assignment意义, 可选链相关]

# TODO: Supply [补充assignment默认值]

   
   
   
   
posted @ 2018-02-19 02:38  懒虫哥哥  阅读(164)  评论(0编辑  收藏  举报