import Foundation

// swift 函数定义
// func 函数名(参数名0:参数类型,参数名1:参数类型,。。。)->函数返回值类型{
//  函数实现
//}
//调用 函数名(实际参数)

//1.定义一个无参无返回值的函数
func myPrintHelloWorld(_: Void)->Void {
    print("Helloworld!")
}
//调用函数 函数名()

myPrintHelloWorld()

//2.如果参数是Void 或者 返回值类型 是Void 那么可以省略不写

func myPrintHelloWorld2(){
    print("Helloworld!")
}
myPrintHelloWorld2()

//带参数的函数 和返回值

//1.参数 是常量类型
func myadd(let a:Int,let b:Int) -> Int {
    return a+b
}
var ret = myadd(1, b: 2)
print("ret = \(ret)")
//1.1参数定义成常量 那么 定义的时候let 关键字可以省去
//下面默认的参数 a 和 b 是常量Int类型
func myadd2(a:Int,b:Int) -> Int {
    //a = 1  常量不能改
    return a+b
}
ret = myadd2(1, b: 2)
print("ret = \(ret)")
//2.返回多个值  (返回一个元组类型)
func myFunc()->(Int,Int,Int) {
    return (1,2,3)
}
print(myFunc())

//3.函数重载 (函数名 一样   参数类型 和 参数的个数不一样 就是函数重载) 和c++ 的函数重载类似

func myadd(a:Double,b:Double) -> Double {
    return a+b
}
func myadd(a:Double,b:Int) -> Int {
    return Int(a)+b
}
func myadd(a:Int,b:Double) -> Double {
    return Double(a)+b
}
func myadd(a:Int,b:Int, c:Int) -> Int {
    return a+b+c
}
let aaaa = myadd(1.2,b: 1.3)
print("-----\(aaaa)")
let aaaa1 = myadd(1,b: 1.3)
let aaaa2 = myadd(1.2,b: 1)
let aaaa3 = myadd(1,b: 1,c: 2)

//上面 5个myadd是同名的 是函数重载

//外部参数(标签名)和内部参数
//不带标签的 参数
func sub(a:Int,b:Int)->Int {
    //a 和 b 可以理解为 内部参数
    return a-b
}
var r = sub(3, b: 1)

//带标签(标签可以理解为外部参数)的函数
//标签就是在调用函数的时候 使用
//给两个参数加标签arguA arguB
func sub(arguA a:Int, arguB b:Int) -> Int {
    
    return a-b
}
//这里的标签和OC方法中的标签类似

//- (int)addA:(int)a andB:(int)b;
//调用的时候显示 标签 标签名后面 写实参
var newRet = sub(arguA: 3, arguB: 1)
//一般加标签的时候 是从第二个参数开始加标签
func subarguA(a:Int,arguB b:Int) -> Int {
    return a - b
}
//如果出现标签名 和 参数名 一样 参数名前加#
/*
func sub(a a:Int, b b:Int) -> Int {
    return a-b
}*/
func sub(aa aa:Int, bb:Int) -> Int {
    return aa-bb
}
print(sub(aa: 3, bb: 1))

//默认参数
//实现一个 函数 在两个字符串中间 拼接一个新的 字符串

//默认参数 定义函数的时候参数可以直接初始化 
//直接初始化的参数就是默认参数
func jionString(s1:String,toString s2:String  ,byString s3:String = "xxxx") -> String {
    return s1 + s3 + s2
}
//如果一个函数有默认参数 那么这个参数调用的时候可以不传值,内部就使用定义的时候的默认值
var newStr = jionString("xiaohong", toString: "xiaohuang")
print(newStr)//xiaohongxxxxxiaohuang

//如果 不想要默认参数的值 那么就给默认参数传值
newStr = jionString("xiaohong", toString: "xiaohuang",byString:"love")
print(newStr)//xiaohonglovexiaohuang


//假设默认参数的标签不写
func jionString2(s1:String,toString s2:String ,s3:String = "xxxx") -> String {
    return s1 + s3 + s2
}
//使用默认参数的默认值
newStr = jionString2("xiaohuang", toString: "xiaofen")
print(newStr)

//如果默认参数不写标签 那么 会自动的把参数名也作为标签名
newStr = jionString2("xiaohuang", toString: "xiaofen", s3: "love")


print(newStr)
//c++ 的默认参数 必须是 最后一个参数
//swift 的默认参数 以前版本也是最后一个参数才能是默认参数 新版本的可以在任意一个参数都可以是默认参数