javaScript 新方向 (8)

作者们付出进度中必备会用到支行语句,不常候大概为了越来越好增添性和易维护性会思量动用政策情势来取代分支语句,不过每一个语言都提供了对分支语句支持,大家看一看下边javascript 中的分支语句,在分支语句大家必得经过 break 在输入条件满足我们定义一种状态后跳出循环。

本章将会介绍

控制流
For-In 循环
While 循环
If 条件语句
Switch 语句
调控转移语句 continue,break,fallthrough
提早退出 guard语句
检查测验API的可用性
函数定义和调用
函数参数与重返值
函数参数标签和参数名称
函数类型
嵌套函数

图片 1

控制流(Control Flow)

斯威夫特提供了各个流程序调节制结构,蕴涵能够反复实行职责的while循环,基于特定条件选用推行不一样代码分支的if、guard和switch语句,还应该有调控流程跳转到其他代码地方的break和continue语句。

Swift还提供了for-in循环,用来更简短地遍历数组(array),字典(dictionary),区间(range),字符串(string)和别的种类类型。

Swift 的switch语句比 C 语言中更抓实硬。在 C 语言中,如若有个别 case 十分大心漏写了break,这些 case 就能够贯通至下二个 case,斯维夫特无需写break,所以不会发生这种贯穿的境况。case 还足以宽容非常多不一的情势,蕴含间隔相配(interval match),元组(tuple)和转移到一定项目。switch语句的 case 中相称的值能够绑定成不经常常量或变量,在case体内选拔,也得以用where来说述更目眩神摇的非常原则。

只要大家忘记写 break 的话,大家在 printSwitchedValue 输入 2 时候,在满意条件后就能挨个试行下去,打字与印刷出 two three default。

1.For-In 循环
  • 您能够动用 for-in 循环来遍历二个成团中的全部因素,比如数组中的成分、数字范围大概字符串中的字符。
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, (name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
  • 你也能够由此遍历三个字典来拜访它的键值对。遍历字典时,字典的每项因素会以 (key, value) 元组的格局再次来到,你可以在 for-in 循环中利用显式的常量名称来解读 (key, value) 元组。上边的事例中,字典的键解读为常量 animalName,字典的值会被解读为常量 legCount:
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("(animalName)s have (legCount) legs")
}
// ants have 6 legs
// spiders have 8 legs
// cats have 4 legs

字典的剧情本质上是冬日的,遍历成分时不能够保障顺序。极其地,将成分插入二个字典的相继并不会调节它们被遍历的逐条。

  • 假设你无需区间体系内各类的值,你能够运用下划线(_)代替变量名来忽略这些值:
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
    answer *= base
}
print("(base) to the power of (power) is (answer)")
// 输出 "3 to the power of 10 is 59049"

这么些事例总计 base 那个数的 power 次幂(本例中,是 3 的 10 次幂),从 1( 3 的 0 次幂)最早做 3 的乘法, 举办 10 次,使用 1 到 10 的闭区间循环。那些总结并不供给知道每一趟巡回中计数器械体的值,只供给实施了正确的循环次数就可以。下划线符号 _ (代替循环中的变量)可以忽视当前值,并且不提供循环遍历时对值的会见。

  • 在好几景况下,你大概不想选取闭区间,包含四个端点。在三个钟表上每分钟绘制叁个刻度线。要绘制 60 个刻度,从 0 分钟初步。使用半开区间运算符(..<)来含有下限,但不包罗上限。
let minutes = 60
for tickMark in 0..<minutes {
    // 每1分钟呈现一个刻度线(60次)
}
  • 有个别客商恐怕在其UI中或许需求少之甚少的刻度。他们能够每5分钟作为一个刻度。使用 stride(from:to:by:) 函数跳过无需的标记。
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // 每5分钟呈现一个刻度线 (0, 5, 10, 15 ... 45, 50, 55)
}
  • 能够在闭区间使用 stride(from:through:by:) 起到平等效劳:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // 每3小时呈现一个刻度线 (3, 6, 9, 12)
}

图片 2图片 3

2.While 循环
  • while循环会向来运行一段语句直到条件成为false。那类循环相符采用在首先次迭代前,迭代次数未知的景观下。Swift提供二种while循环格局:

    • while循环,每一遍在循环开端时总括标准是或不是切合;
    • repeat-while循环,每便在循环截止时总括原则是不是顺应。
  • While
    while循环从总计八个法则开首。即使基准为true,会重复运营一段语句,直到条件成为false。上边是 while 循环的貌似格式:

while condition {  
    statements
}
  • Repeat-While
    while循环的别的一种样式是repeat-while,它和while的界别是在认清循环条件在此之前,西施行一遍巡回的代码块。然后再次循环直到条件为false。
    上面是 repeat-while循环的相似格式:
repeat {
    statements
} while condition

注意:
Swift语言的repeat-while循环和其余语言中的do-while循环是看似的。

大家谋算尝试任何格局来达成同分支语句一样效果还是能够幸免犯分支语句同样错误,大家重构一下代码,大家用三目运算来一层一层完毕。

3. 标准语句

Swift提供两连串型的尺度语句:if语句和switch语句。平时,当法规较为轻巧且可能的意况非常少时,使用if语句。而switch语句更适用于条件较复杂、有越来越多排列组合的时候。并且switch在急需动用方式相配(pattern-matching)的图景下会更有用。

  • If

    • if语句最简易的款型正是只含有叁个法规,唯有该准则为true时,才试行有关代码:
    • if语句允许二选一实施,叫做else从句。约等于当条件为false时,实行else 语句
    • 使用else if语句完结愈来愈多的道岔
  • Switch
    switch语句会尝试把某部值与若干个格局(pattern)实行相称。依据第二个异常成功的方式,switch语句会施行相应的代码。当有相当大可能的状态比较多时,平时用switch语句替换if语句。

    • switch语句最简易的样式就是把某部值与二个或若干个一律档案的次序的值作相比:
switch some value to consider {
case value 1:
    respond to value 1
case value 2,
    value 3:
    respond to value 2 or 3
default:
    otherwise, do something else
}
  • switch语句由四个 case 构成,种种由case关键字开首。为了合营有个别更特定的值,Swift提供了二种艺术来进行更眼花缭乱的形式相配,这几个格局将要本节的稍后有的关联。
  • 与if语句类似,每贰个 case 都是代码实行的一条分支。switch语句会决定哪一条分支应该被施行,那一个流程被称作依照给定的值切换(switching)。
  • switch语句必需是万事俱备的。那正是说,每二个或许的值都必得最少有一个case 分支与之相应。在好几不容许带有全数值的景况下,你能够应用暗许(default)分支来含有别的具备未有对号入座的值,这几个暗中认可分支必得在switch语句的最后面。

上面包车型大巴例子使用switch语句来协作多个名称为someCharacter的小写字符:

let someCharacter: Character = "z"
switch someCharacter {
case "a":
    print("The first letter of the alphabet")
case "z":
    print("The last letter of the alphabet")
default:
    print("Some other character")
}
// 输出 "The last letter of the alphabet"

在那个事例中,第一个 case 分支用于相配第贰个韩文字母a,第三个 case 分支用于匹配最终三个字母z。 因为switch语句务必有一个case分支用于覆盖全数极大恐怕的字符,而不光是具备的匈牙利(Hungary)语字母,所以switch语句使用default分支来相称除了a和z外的享有值,那么些分支保障了swith语句的完备性。

  • 不设有隐式的贯通

与 C 和 Objective-C 中的switch语句分裂,在 Swift 中,当相配的 case 分支中的代码施行实现后,程序会告一段落switch语句,而不会继续实施下三个 case 分支。那也算得,无需在 case 分支中显式地选择break语句。那使得switch语句更安全、更易用,也制止了因忘记写break语句而发出的一无所长。

  • 各种 case 分支都不能够不含有起码一条语句。像下边那样书写代码是低效的,因为第七个case 分支是空的:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 无效,这个分支下面没有语句
case "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// 这段代码会报编译错误
  • 不像 C 语言里的switch语句,在 Swift中,switch语句不会共同相称"a"和"A"。相反的,上边的代码会挑起编写翻译期错误:case "a": 不含有其余可试行语句——这就防止了不测地从贰个 case 分支贯穿到另外三个,使得代码更安全、也越来越直观。为了让单个case同期般配a和A,能够将这些多个值组合成三个复合相称,而且用逗号分开:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// 输出 "The letter A
  • 距离相称

case 分支的方式也足以是贰个值的距离。上面包车型地铁例子显示了如何行使间隔相称来输出任性数字对应的自然语言格式:

let approximateCount = 62
let countedThings = "moons orbiting Saturn"
var naturalCount: String
switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are (naturalCount) (countedThings).")
// 输出 "There are dozens of moons orbiting Saturn."

在上例中,approximateCount在多少个switch表明中被评估。每八个case都与之举办相比。因为approximateCount落在了 12 到 100 的距离,所以naturalCount等于"dozens of"值,何况此后的实行跳出了switch语句。

  • 元组

    • 作者们可以选拔元组在同贰个switch语句中测量试验三个值。元组中的成分得以是值,也能够是距离。别的,使用下划线(_)来协作全数十分的大希望的值。

    • 下边包车型客车事例体现了什么采纳四个(Int, Int)类型的元组来分类下图中的点(x, y):

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("((somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, (somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
    print("((somePoint.0), (somePoint.1)) is inside the box")
default:
    print("((somePoint.0), (somePoint.1)) is outside of the box")
}
// 输出 "(1, 1) is inside the box"

在地点的例证中,switch语句会判定有些点是或不是是原点(0, 0),是或不是在革命的x轴上,是还是不是在橘粉末蓝的y轴上,是或不是在贰个以原点为基本的4x4的紫藤色矩形里,也许在那一个矩形外面。

不像 C 语言,Swift 允许八个 case 相配同三个值。实际上,在那么些事例中,点(0, 0)能够相配全部七个case。不过,要是存在多少个门户格外,那么只会实行第二个被相配到的 case 分支。思虑点(0, 0)会率先相配case (0, 0),因而结余的能够宽容的分支都会被忽视掉。

  • 值绑定

    • case 分支允许将合作的值绑定到贰个暂时的常量或变量,何况在case分支体内使用 —— 这种作为被称为值绑定(value binding),因为门户特其余值在case分支体内,与权且的常量或变量绑定。

    • 上面的例证显示了哪些在三个(Int, Int)类型的元组中使用值绑定来分类下图中的点(x, y):

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of (x)")
case (0, let y):
    print("on the y-axis with a y value of (y)")
case let (x, y):
    print("somewhere else at ((x), (y))")
}
// 输出 "on the x-axis with an x value of 2"

在地点的事例中,switch语句会剖断有个别点是不是在新民主主义革命的x轴上,是不是在橘玉绿的y轴上,或然不在坐标轴上。

那多个 case 都宣示了常量x和y的占位符,用于一时获取元组anotherPoint的一个或五个值。第贰个case ——case (let x, 0)将合作叁个纵坐标为0的点,并把这些点的横坐标赋给不常的常量x。类似的,第3个case ——case (0, let y)将相配三个横坐标为0的点,并把这些点的纵坐标赋给不时的常量y。

假设注脚了那个临时的常量,它们就能够在其对应的 case 分支里使用。在这些事例中,它们用于打印给一定的种类。

请小心,那几个switch语句不包罗默许分支。那是因为最终叁个 case ——case let(x, y)阐明了一个能够相称余下全体值的元组。那使得switch语句已经完备了,由此不必要再挥洒默许分支。

  • Where
    • case 分支的格局能够利用where语句来判断额外的标准。
    • 下边包车型地铁例子把下图中的点(x, y)举办了分类:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("((x), (y)) is on the line x == y")
case let (x, y) where x == -y:
    print("((x), (y)) is on the line x == -y")
case let (x, y):
    print("((x), (y)) is just some arbitrary point")
}
// 输出 "(1, -1) is on the line x == -y"

在下面的例子中,switch语句会判定有个别点是不是在铁锈棕的对角线x == y上,是还是不是在紫藤色的对角线x == -y上,或许不在对角线上。

那多个 case 都宣示了常量x和y的占位符,用于不常获取元组yetAnotherPoint的八个值。那七个常量被作为where语句的一有的,进而创立二个动态的过滤器(filter)。当且仅当where语句的标准为true时,相配到的 case 分支才会被实行。

就如值绑定中的例子,由于最终三个 case 分支相配了剩余全体希望的值,switch语句就早已完备了,因而无需再挥洒私下认可分支。

  • 复合相称
    当七个尺码能够应用同样种办法来拍卖时,能够将这两种或然位于同叁个case前边,而且用逗号隔开分离。当case后边的随便一种方式相配的时候,那条分支就能够被匹配。而且,假若相配列表过长,还是能够分小篆写:
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
    print("(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
     "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("(someCharacter) is a consonant")
default:
    print("(someCharacter) is not a vowel or a consonant")
}
// 输出 "e is a vowel"

本条switch语句中的第叁个case,相称了英语中的七个小写元音字母。相似的,第一个case相称了俄文中具备的小写辅音字母。最终,default分支相配了任何具备字符。 复合相配同样能够分包值绑定。复合匹配里全数的非常格局,都不可能不包罗一样的值绑定。并且每三个绑定都不能够不获得到均等类其他值。那保险了,无论复合匹配中的哪个情势发生了非凡,分支体内的代码,都能取得到绑定的值,並且绑定的值都有同样的连串。

let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
    print("On an axis, (distance) from the origin")
default:
    print("Not on an axis")
}

// 输出 "On an axis, 9 from the origin"

位置的case有多个方式:(let distance, 0)匹配了在x轴上的值,(0, let distance)相配了在y轴上的值。多个情势都绑定了distance,并且distance在三种形式下,都以整型——这意味着分支体内的代码,只要case相配,都足以获得到distance值

图片 4

4.说了算转移语句

决定转移语句退换你代码的推行各样,通过它能够兑当代码的跳转。Swift有二种调整转移语句:continue,break,fallthrough,return,throw

  • continue

    • continue语句告诉二个循环体立刻停下此番巡回,重新初步后一次循环。就恍如在说“此番巡回作者早就进行完了”,不过并不会相差整个循环体。

    • 上边包车型地铁例证把叁个小写字符串中的元音字母和空格字符移除,生成了一个意义模糊的短句:

let puzzleInput = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput.characters {
    switch character {
    case "a", "e", "i", "o", "u", " ":
        continue
    default:
        puzzleOutput.append(character)
    }
}
print(puzzleOutput)
    // 输出 "grtmndsthnklk"

在地点的代码中,只要匹配到元音字母只怕空格字符,就调用continue语句,使本次巡回结束,重新开头下一次循环。这种作为使switch相称到元音字母和空格字符时不做管理,实际不是让每多个相称到的字符都被打字与印刷。

  • Break
    • break语句会登时终止全数调控流的试行。当您想要更早的截止叁个switch代码块只怕一个循环体时,你都得以应用break语句。
    • 循环语句中的 break 当在三个循环体中运用break时,会及时行车制动器踏板该循环体的进行,然后跳转到表示循环体停止的大括号(})后的第一行代码。不会再有本次巡回的代码被施行,也不会再有后一次的循环爆发。
    • Switch 语句中的 break 当在三个switch代码块中选用break时,会立即暂停该switch代码块的施行,况兼跳转到表示switch代码块截止的大括号(})后的率先行代码。

这种本性能够被用来合营也许忽视一个或四个分支。因为 Swift的switch必要包罗全体的支行何况不容许有为空的分层,不时为了使您的意向更引人注目,要求特地相称也许忽视某些分支。那么当您想忽视某些分支时,能够在该分支援内地建设写上break语句。当那些分支被匹配到时,分支援内地建设的break语句立即甘休switch代码块。

静心: 当八个switch分支仅仅满含注释时,会被报编译时不当。注释不是代码语句何况也无法让switch分支到达被忽视的效益。你应该利用break来忽略有些分支。

下边包车型大巴例证通过switch来判别二个Character值是不是意味上面八种语言之一。为了简洁,多个值被含有在了同贰个支市价况中。

let numberSymbol: Character = "三"  // 简体中文里的数字 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
case "3", "٣", "三", "๓":
    possibleIntegerValue = 3
case "4", "٤", "四", "๔":
    possibleIntegerValue = 4
default:
    break
}
if let integerValue = possibleIntegerValue {
    print("The integer value of (numberSymbol) is (integerValue).")
} else {
    print("An integer value could not be found for (numberSymbol).")
}
// 输出 "The integer value of 三 is 3."

那些例子检查numberSymbol是或不是是拉丁,阿拉伯,中文或许日文中的1到4之一。如若被相配到,该switch分支语句给Int?类型变量possibleIntegerValue设置叁个整数值。

当switch代码块试行完后,接下去的代码通过应用可选绑定来判定possibleIntegerValue是还是不是业已被设置过值。因为是可选类型的因由,possibleIntegerValue有贰个隐式的初步值nil,所以独有当possibleIntegerValue曾被switch代码块的前三个支行中的有些设置过二个值时,可选的绑定才会被判别为成功。

在上面的例子中,想要把Character全部的的可能性都枚举出来是不具体的,所以选拔default分支来含有全部地方未有相配到字符的境况。由于这几个default分支无需实行其他动作,所以它只写了一条break语句。一旦落入到default分支中后,break语句就完事了该支行的持有代码操作,代码继续向下,伊始施行if let语句。

  • 贯穿 fallthrough

    • Swift 中的switch不会从上二个 case 分支落入到下叁个 case 分支中。相反,只要第一个极度到的 case 分支完毕了它要求举行的言语,整个switch代码块完结了它的推行。比较之下,C 语言要求您显式地插入break语句到各样 case 分支的最后来阻拦自动落入到下四个 case 分支中。Swift的这种幸免暗许落入到下二个分层中的性子意味着它的switch 功用要比 C 语言的愈加分明和可预测,可以制止无意识地进行多个 case 分支从而抓住的失实。

    • 例如您真正必要 C 风格的贯通的性状,你能够在各样要求该特性的 case 分支中动用fallthrough关键字。下边包车型大巴例证使用fallthrough来创设贰个数字的陈述语句。

let integerToDescribe = 5
var description = "The number (integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description)
// 输出 "The number 5 is a prime number, and also an integer."

本条例子定义了一个String类型的变量description而且给它设置了三个早先值。函数使用switch逻辑来决断integerToDescribe变量的值。当integerToDescribe的值属于列表中的质数之有的时候,该函数在description后增多一段文字,来申明那些数字是多个质数。然后它选用fallthrough关键字来“贯穿”到default分支中。default分支在description的末段增多一段额外的文字,至此switch代码块施行完了。

借使integerToDescribe的值不属于列表中的任何质数,那么它不会协作到第一个switch分支。而这里未有另外非常的支市场价格况,所以integerToDescribe相配到default分支中。

当switch代码块施行完后,使用print(_:separator:terminator:)函数打字与印刷该数字的汇报。在这几个例子中,数字5被正确准确的鉴定区别为了一个质数。

只顾: fallthrough关键字不会检查它下三个将会落入施行的 case 中的相配原则。fallthrough轻松地使代码继续连接到下二个 case 中的代码,那和 C 语言专门的职业中的switch语句天性是均等的。

  • 带标签语句

在 Swift中,你可以在循环体和规范化语句中嵌套循环体和规格语句来成立复杂的调整流结构。而且,循环体和标准语句都得以采取break语句来提前甘休整个代码块。由此,显式地指明break语句想要终止的是哪位循环体只怕规格语句,会很有用。类似地,纵然您有那个嵌套的循环体,显式指明continue语句想要影响哪一个循环体也会十二分管用。

为了落实这么些指标,你能够应用标签(statement label)来标识叁个循环体也许规格语句,对于二个规范化语句,你能够行使break加标签的方式,来终结这几个被标识的语句。对于叁个循环语句,你能够利用break只怕continue加标签,来了却可能延续那条被标志语句的实施。

宣称五个带标签的口舌是由此在该语句的要紧词的同一行前边放置四个标签,作为那一个讲话的最初关键字(introducor keyword),而且该标签前边紧跟着三个冒号。下边是三个对准while循环体的价签语法,同样的条条框框适用于具备的循环体和准则语句。

label name: while condition { statements }
  • 提前退出

像if语句一样,guard的实施决意于贰个表明式的布尔值。大家得以使用guard语句来供给标准必需为真时,以举办guard语句后的代码。差异于if语句,二个guard语句总是有二个else从句,要是条件不为真则试行else从句中的代码。

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello (name)")
    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }
    print("I hope the weather is nice in (location).")
}
greet(["name": "John"])
// 输出 "Hello John!"
// 输出 "I hope the weather is nice near you."
greet(["name": "Jane", "location": "Cupertino"])
// 输出 "Hello Jane!"
// 输出 "I hope the weather is nice in Cupertino."

要是guard语句的准绳被满足,则继续施行guard语句大括号后的代码。将变量只怕常量的可选绑定作为guard语句的尺度,都得以维护guard语句前面包车型客车代码。

如果基准不被满足,在else分支上的代码就能被实践。那些分支必需转变调整以脱离guard语句出现的代码段。它能够用调控转移语句如return,break,continue或然throw做那件事,大概调用三个不回去的法子或函数,举例fatalError()。

看待于可以兑现均等效劳的if语句,按需利用guard语句会升高大家代码的可读性。它能够使您的代码连贯的被实施而没有供给将它包在else块中,它能够让你在左近条件推断的地方,处理不合法的动静。

诸有此类即使幸免在分支语句爆发一些主题素材,不过大家看这么写的是有局限性,不恐怕写一些叶影参差的逻辑。品质也应有是三个难题。然后尝试任何渠道来兑现分支语句作用,我们定义 values 对象,然后经过输入类型,大家在对象 values 找对应属性,假如找到属性就对应重返值。若无找到就重返默许值。

5.检测 API 可用性

斯维夫特内置辅助检查 API 可用性,那可以保险我们不会在当下配备机器上,非常大心地行使了不可用的API。

编写翻译器使用 SDK 中的可用消息来验证大家的代码中选用的兼具 API 在类型钦赐的布局目的上是还是不是可用。假诺大家尝试采纳三个不可用的 API,Swift会在编译时报错。

我们在if或guard语句中动用可用性条件(availability condition)去有准则的实行一段代码,来在运作时判定调用的API是或不是可用。编写翻译器使用从可用性条件语句中获得的新闻去印证,在这些代码块中调用的 API 是否可用。

if #available(iOS 10, macOS 10.12, *) {
    // 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
    // 使用先前版本的 iOS 和 macOS 的 API
}

以上可用性条件钦命,在iOS中,if语句的代码块仅仅在 iOS 10 及更加高的连串下运作;在 macOS中,仅在 macOS 10.12 及更加高才会运转。最终二个参数,*,是必得的,用于钦定在颇有其余平台南,假如版本号高于你的器械钦赐的最低版本,if语句的代码块将会运作。

在它平常的款式中,可用性条件使用了八个平台名字和本子的列表。平台名字能够是iOS,macOS,watchOS和tvOS——请访谈评释属性来得到完整列表。除了钦定像 iOS 8的主板本号,大家得以内定像iOS 8.3 以及 macOS 10.10.3的子版本号。

if #available(platform name version, ..., *) {
    APIs 可用,语句将执行
} else {
    APIs 不可用,语句将不执行
}

图片 5

6.调控流总括
// 控制流

// for-in 循环
for _ in 1...5 {
    print("hehe")
}

let minutes = 60
let minuteInterval = 5

for tickMark in stride(from: 0, through: minutes, by: minuteInterval) {
    print(tickMark)
}

let someCharacter: Character = "z"
switch someCharacter {
case "a":
    print("The first letter of the alphabet")
case "z":
    print("The last letter of the alphabet")
default:
    print("Some other Character")
}

let somePoint = (0, 0)
switch somePoint {
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("((somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, (somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
    print("((somePoint.0), (somePoint.1)) is inside the box")
default:
    print("((somePoint.0), (somePoint.1)) is outside the box")
}

// 值绑定
let anotherPoint = (2, 4)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of (x)")
case (0, let y):
    print("on the y-axis with a y value of (y)")
case (let x, let y):
    print("somewhere else at ((x), (y))")
}

// where语句
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("((x), (y)) is on the line x == y")
case let (x, y) where x == -y:
    print("((x), (y)) is on the line x == -y")
case let (x, y):
    print("((x), (y)) is just some arbitraty point")

}

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello (name)")
    guard let location = person["location"] else {
        print("I home the wheather is nice near you")
        return
    }
    print("I hope the wheather is nice in (location)")
}
greet(person: ["name" : "John"])
greet(person: ["name": "xiaoming", "location": "BeiJing"])

if #available(iOS 10, macOS 10.12, watchOS 2, *) {
    print("hehe")
} else {
    print("haha")
}

然而作为 developer 一个写 bug 的人大家难免会犯上面错误。如若我们将某叁个属性值 false null 或 undefined 就能够获得 default 暗中认可值

函数(Functions)

函数是一段完结一定任务的独立代码片段。你能够通过给函数命名来标志有个别函数的法力,那一个名字能够被用来在须要的时候"调用"那一个函数来变成它的任务。

斯威夫特统一的函数语法特别的灵活,能够用来表示别的函数,包含从最不难易行的未有参数名字的 C 风格函数,到复杂的带一些和外界参数名的 Objective-C 风格函数。参数可以提供暗中同意值,以简化函数调用。参数也得以既当做传入参数,也充当传出参数,也正是说,一旦函数施行完成,传入的参数值将被修改。

在 斯维夫特中,各种函数都有四个由函数的参数值类型和再次来到值类型组成的品类。你能够把函数类型充作任何其余日常性变量类型同样管理,那样就足以更简便地把函数当作其他函数的参数,也足以从别的函数中回到函数。函数的定义能够写在另外函数定义中,那样能够在嵌套函数范围内达成效果与利益封装。

图片 6图片 7

1.函数的定义和调用

当你定义三个函数时,你可以定义三个或三个盛名字和等级次序的值,作为函数的输入,称为参数,也能够定义某体系型的值作为函数实施达成时的输出,称为重回类型。

每一个函数有个函数名,用来陈诉函数执行的天职。要利用多个函数时,用函数名来“调用”那么些函数,并传给它非凡的输入值(称作 实参 )。函数的实参必得与函数参数表里参数的相继一致。

下边例子中的函数的名字是greet(person:),之所以叫那么些名字,是因为那个函数用一人的名字当做输入,并回到向此人问候的讲话。为了成功那几个职责,你须要定义多个输入参数——叁个叫作 person 的 String 值,和一个含有给这厮问候语的 String 类型的重临值:

func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}

不无的这一个音讯聚集起来成为函数的定义,并以 func 作为前缀。钦点函数重回类型时,用重回箭头 ->(贰个连字符后跟七个右尖括号)后跟回来类型的称呼的艺术来代表。

该定义描述了函数的效应,它仰望接收什么作为参数和实施完成时它回到的结果是什么品种。这样的定义使得函数能够在别的地方以一种清晰的办法被调用:

print(greet(person: "Anna"))
// 打印 "Hello, Anna!"
print(greet(person: "Brian"))
// 打印 "Hello, Brian!"

调用 greet(person:) 函数时,在圆括号中传给它叁个 String 类型的实参,举例greet(person: "Anna")。正如上边所示,因为那个函数再次来到贰个 String 类型的值,所以greet 能够被含有在 print(_:separator:terminator:) 的调用中,用来输出那一个函数的重临值。

在 greet(person:) 的函数体中,先定义了二个新的名称为 greeting 的 String 常量,同期,把对 personName 的问讯音讯赋值给了 greeting 。然后用 return 关键字把那些问候再次回到出去。一旦 return greeting 被调用,该函数停止它的进行并重返 greeting 的眼下值。

你能够用分歧的输入值数次调用 greet(person:)。上边包车型客车事例显示的是用"Anna"和"Brian"调用的结果,该函数分别再次回到了分裂的结果。

2.函数参数与再次回到值

函数参数与重返值在 斯威夫特中相当的灵活。你能够定义任何项目标函数,富含从只带叁个未名参数的简练函数到复杂的带有表达性参数名和见仁见智参数选项的目迷五色函数。

  • 无参数函数

函数能够未有参数。下边那么些函数正是叁个无参数函数,当被调用时,它回到固定的 String 音讯:

func sayHelloWorld() -> String {
    return "hello, world"
}
print(sayHelloWorld())
// 打印 "hello, world"

就算那么些函数未有参数,然而定义中在函数名后要么需求一对圆括号。当被调用时,也亟需在函数名后写一对圆括号。

  • 多参数函数

函数能够有七种输入参数,这一个参数被含有在函数的括号之中,以逗号分隔。

上边那些函数用两个姓名和是或不是已经打过招呼作为输入,并回到对这厮的适当问候语:

func greet(person: String, alreadyGreeted: Bool) -> String {
    if alreadyGreeted {
        return greetAgain(person: person)
    } else {
        return greet(person: person)
    }
}
print(greet(person: "Tim", alreadyGreeted: true))
// 打印 "Hello again, Tim!"

你能够经过在括号内采取逗号分隔来传递叁个String参数值和叁个标志为alreadyGreeted的Bool值,来调用greet(person:alreadyGreeted:)函数。注意那一个函数和上边greet(person:)是例外的。即使它们都装有一样的名字greet,可是greet(person:alreadyGreeted:)函数要求五个参数,而greet(person:)只供给贰个参数。

  • 无重回值函数

函数能够没有再次来到值。上面是 greet(person:) 函数的另一个版本,那些函数直接打字与印刷二个String值,并非回去它:

func greet(person: String) {
    print("Hello, (person)!")
}
greet(person: "Dave")
// 打印 "Hello, Dave!"

因为那些函数无需再次来到值,所以这一个函数的定义中未有回到箭头(->)和再次回到类型。

注意
从严上的话,即便尚未重临值被定义,greet(person:) 函数依旧重返了值。没有概念重返类型的函数会回来二个破例的Void值。它其实是二个空的元组(tuple),未有任何因素,能够写成()。

被调用时,三个函数的再次回到值能够被忽视:

func printAndCount(string: String) -> Int {
    print(string)
    return string.characters.count
}
func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// 打印 "hello, world" 并且返回值 12
printWithoutCounting(string: "hello, world")
// 打印 "hello, world" 但是没有返回任何值

先是个函数 printAndCount(string:),输出三个字符串并赶回 Int 类型的字符数。第一个函数 printWithoutCounting(string:)调用了第一个函数,不过忽略了它的重返值。当第贰个函数被调用时,音讯如故会由第三个函数输出,可是再次来到值不会被用到。

注意:
再次来到值可以被忽略,但定义了有重回值的函数必得回到一个值,假如在函数定义后面部分未有回来任何值,将促成编写翻译时不当(compile-time error)。

  • 多种重回值函数

您能够用元组(tuple)类型让多少个值作为三个复合值从函数中回到。

下例中定义了二个名称为 min马克斯(array:) 的函数,作用是在三个 Int 类型的数组中寻找最小值与最大值。

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

min马克斯(array:) 函数重临八个满含两个 Int 值的元组,这么些值被标志为 min 和 max ,以便查询函数的回来值时能够由此名字访问它们。

在 min马克斯(array:) 的函数体中,在伊始的时候设置多个办事变量 currentMin 和 currentMax的值为数组中的第二个数。然后函数会遍历数组中多余的值并检讨该值是或不是比 currentMin 和 currentMax更加小或越来越大。最终数组中的最小值与最大值作为一个包含多个 Int 值的元组再次回到。

因为元组的成员值已被取名,由此得以通过 . 语法来探搜索到的最小值与最大值:

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is (bounds.min) and max is (bounds.max)")
// 打印 "min is -6 and max is 109"

亟需专心的是,元组的积极分子无需在元组从函数中回到时命名,因为它们的名字一度在函数重返类型中钦点了。

  • 可选元组再次来到类型

借使函数再次来到的元组类型有望所有元组都“未有值”,你能够运用可选的( optional ) 元组再次来到类型反映全体元组能够是nil的实际情状。你可以通过在元组类型的右括号后放置一个问号来定义三个可选元组,举个例子(Int, Int)? 或 (String, Int, Bool)?

瞩目 可选元组类型如 (Int, Int)? 与元组包蕴可选类型如 (Int?, Int?) 是差别的.可选的元组类型,整个元组是可选的,而不只是元组中的每一种成分值。

这两天的 minMax(array:) 函数再次回到了二个蕴涵八个 Int 值的元组。然则函数不会对传播的数组实施别的安检,要是 array 参数是叁个空数组,如上定义的 min马克斯(array:) 在筹划访谈 array[0] 时会接触二个运维时不当(runtime error)。

为了安全地管理那几个“空数组”难题,将 min马克斯(array:) 函数改写为利用可选元组再次回到类型,而且当数组为空时重返 nil:

func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

你能够应用可选绑定来检查 min马克斯(array:) 函数再次来到的是二个设有的元组值依然nil:

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is (bounds.min) and max is (bounds.max)")
}
// 打印 "min is -6 and max is 109"
3.函数参数标签和参数名称
  • 种种函数参数都有一个参数标签( argument label )以及三个参数名称( parameter name )。参数标签在调用函数的时候使用;调用的时候需求将函数的参数标签写在相应的参数前边。参数名称在函数的完成中应用。暗许意况下,函数参数使用参数名称来作为它们的参数标签。
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}
someFunction(firstParameterName: 1, secondParameterName: 2)

享有的参数都必得有二个旷世的名字。即便三个参数具备同等的参数标签是大概的,但是二个独一的函数标签能够让你的代码更具可读性。

  • 钦点参数标签

您能够在参数名称前线指挥部定它的参数标签,中间以空格分隔:

func someFunction(argumentLabel parameterName: Int) {
    // 在函数体内,parameterName 代表参数值
}

本条本子的 greet(person:) 函数,接收一位的名字和她的家门,何况重临一句问候:

func greet(person: String, from hometown: String) -> String {
    return "Hello (person)!  Glad you could visit from (hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// 打印 "Hello Bill!  Glad you could visit from Cupertino."

参数标签的运用能够让三个函数在调用时更有表达力,更近乎自然语言,况且仍维持了函数内部的可读性以及清晰的意图。

  • 马虎参数标签

比如您不希望为有些参数加多三个标签,能够行使叁个下划线(_)来替代一个分明的参数标签。

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
     // 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}
someFunction(1, secondParameterName: 2)

假定二个参数有一个标签,那么在调用的时候必得使用标签来标识这些参数。

  • 暗许参数值

您能够在函数体中经过给参数赋值来为随便多少个参数定义默认值(Deafult Value)。当暗许值被定义后,调用那些函数时可以忽略这么些参数。

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // 如果你在调用时候不传第二个参数,parameterWithDefault 会值为 12 传入到函数体中。
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault = 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault = 12

将不含有默许值的参数放在函数参数列表的最前。平常的话,未有暗许值的参数越来越主要,将不带私下认可值的参数放在最前保证在函数调用时,非默许参数的次第是一样的,同期也使得同样的函数在差异景况下调用时显得更为显明。

  • 可变参数

二个可变参数(variadic parameter)尚可零个或多个值。函数调用时,你能够用可变参数来钦定函数参数能够被流传不明显数量的输入值。通过在变量类型名背后出席(...)的法子来定义可变参数。

可变参数的流传值在函数体中造成此类型的三个数组。举个例子,一个誉为 numbers 的 Double... 型可变参数,在函数体内能够用作一个叫 numbers 的 [Double] 型的数组常量。

上边包车型地铁这一个函数用来计算一组随机长度数字的 算术平均数(arithmetic mean):

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// 返回 3.0, 是这 5 个数的平均数。
arithmeticMean(3, 8.25, 18.75)
// 返回 10.0, 是这 3 个数的平均数。

注意:
三个函数最八只可以具备三个可变参数。

  • 输入输出参数

函数参数暗许是常量。试图在函数体中退换参数值将会招致编写翻译错误(compile-time error)。这表示你无法错误地更改参数值。如若您想要八个函数能够修改参数的值,并且想要在这几个修改在函数调用截止后依然存在,那么就应有把这一个参数定义为输入输出参数(In-Out Parameters)。

概念贰个输入输出参数时,在参数定义前加 inout 关键字。一个输入输出参数有扩散函数的值,这些值被函数修改,然后被流传函数,替换原本的值。

您不得不传递变量给输入输出参数。你无法传回常量或许字面量,因为那一个量是不能够被修改的。当传入的参数作为输入输出参数时,须求在参数名前加** & **符,表示这些值可以被函数修改。

在乎 输入输出参数无法有暗许值,何况可变参数无法用 inout 标识。

下例中,swapTwoInts(_:_:) 函数有八个分外称得上叫 a 和 b 的输入输出参数:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

swapTwoInts(_:_:) 函数简单地调换 a 与 b 的值。该函数先将 a 的值存到二个一时常量 temporaryA 中,然后将 b 的值赋给 a,最后将 temporaryA 赋值给 b。

你能够用八个 Int 型的变量来调用 swapTwoInts(_:_:)。须要静心的是,someInt 和 anotherInt 在传出 swapTwoInts(_:_:) 函数前,都加了 & 的前缀:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now (someInt), and anotherInt is now (anotherInt)")
// 打印 "someInt is now 107, and anotherInt is now 3"

从地点这一个例子中,大家能够看出 someInt 和 anotherInt 的原始值在 swapTwoInts(_:_:) 函数中被涂改,即便它们的概念在函数体外。

注意:
输入输出参数和重返值是分化等的。下面的 swapTwoInts 函数并未概念任何再次来到值,但依旧修改了 someInt 和 anotherInt 的值。输入输出参数是函数对函数体外发生震慑的另一种情势。

4.函数类型

各种函数都有种特定的函数类型,函数的花色由函数的参数类型和重回类型组成。例如:

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

以那件事例中定义了四个简易的数学函数:addTwoInts 和 multiplyTwoInts。那多个函数都接受多个 Int 值, 再次来到四个 Int 值。

那五个函数的连串是 (Int, Int) -> Int,能够解读为“那一个函数类型有五个Int 型的参数并赶回一个 Int 型的值。”。

上边是另三个例子,一个未曾子舆数,也从未重返值的函数:

func printHelloWorld() {
    print("hello, world")
}

本条函数的等级次序是:() -> Void,只怕叫“未有参数,并回到 Void 类型的函数”。

  • 利用函数类型

在 Swift中,使用函数类型似乎使用其余类别一样。举例,你能够定义二个门类为函数的常量或变量,并将方便的函数赋值给它:

var mathFunction: (Int, Int) -> Int = addTwoInts

这段代码能够被解读为:”定义三个叫做 mathFunction 的变量,类型是‘八个有七个 Int 型的参数并再次来到四个 Int 型的值的函数’,并让那几个新变量指向 addTwoInts 函数”。

addTwoInts 和 mathFunction 有一样的门类,所以这么些赋值进度在 Swift类型检查(type-check)中是同意的。未来,你能够用 mathFunction 来调用被赋值的函数了:

print("Result: (mathFunction(2, 3))")
// Prints "Result: 5"

有平等相称类型的不相同函数能够被赋值给同三个变量,就疑似非函数类型的变量一样:

mathFunction = multiplyTwoInts
print("Result: (mathFunction(2, 3))")
// Prints "Result: 6"

就像别的项目同样,当赋值一个函数给常量或变量时,你能够让 Swift来估算其函数类型:

let anotherMathFunction = addTwoInts
// anotherMathFunction 被推断为 (Int, Int) -> Int 类型
  • 函数类型作为参数类型

你能够用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数类型。那样你能够将函数的一局地完结留给函数的调用者来提供。

上边是另一个事例,正如上边的函数同样,同样是出口某种数学生运动算结果:

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: (mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// 打印 "Result: 8"

以此事例定义了 printMathResult(_:_:_:) 函数,它有八个参数:第贰个参数叫 mathFunction,类型是 (Int, Int) -> Int,你可以流传任何那种类型的函数;第二个和第三个参数叫 a 和 b,它们的品类都以 Int,这两个值作为已交由的函数的输入值。

printMathResult(_:_:_:) 被调用时,它被传到 addTwoInts 函数和整数 3 和 5。它用传入 3 和 5 调用 addTwoInts,并出口结果:8。

printMathResult(_:_:_:) 函数的法力就是出口另一个体面类型的数学函数的调用结果。它不珍惜传入函数是如何落到实处的,只关切传入的函数是否四个不容置疑的类型。那使得 printMathResult(_:_:_:) 能以一种等级次序安全(type-safe)的不二秘诀将一部分效果与利益转给调用者实现。

  • 函数类型作为再次回到类型

您能够用函数类型作为另贰个函数的归来类型。你须求做的是在回来箭头(->)后写四个完整的函数类型。

上面的那些例子中定义了三个差相当少函数,分别是 stepForward(_:)stepBackward(_:)stepForward(_:)函数再次回到贰个比输入值大 1 的值。stepBackward(_:) 函数再次回到一个比输入值小 1 的值。这两个函数的门类都以 (Int) -> Int:

如下名字为 chooseStepFunction(backward:) 的函数,它的回到类型是 (Int) -> Int 类型的函数。chooseStepFunction(backward:) 依照布尔值 backwards 来重回 stepForward(_:) 函数或 stepBackward(_:) 函数:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}

你将来得以用chooseStepFunction(backward:)来获取三个函数当中的三个:

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 现在指向 stepBackward() 函数。

地点这么些事例中总计出从 currentValue 渐渐接近到0是内需向正数走依旧向负数走。currentValue 的起头值是 3,那表示 currentValue > 0 为真(true),那将使得 chooseStepFunction(_:) 返回 stepBackward(_:) 函数。二个对准再次来到的函数的引用保存在了 moveNearerToZero 常量中。

现行反革命,moveNearerToZero指向了不利的函数,它能够被用来数到零:

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!
5.嵌套函数

到近期截止本章中你所看见的富有函数都叫全局函数(global functions),它们定义在全局域中。你也足以把函数定义在别的函数体中,称作 嵌套函数(nested functions)。

暗中认可意况下,嵌套函数是对外部不可知的,然则能够被它们的外场函数(enclosing function)调用。三个外界函数也足以回到它的某一个嵌套函数,使得那么些函数能够在别的域中被利用。

您能够用再次回到嵌套函数的点子重写 chooseStepFunction(backward:) 函数:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
    print("(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
6.函数总计
// 函数

// 函数的定义
func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}
print(greet(person: "XiaoMing"))

// 上边函数的简写
func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))

// 无参数函数
func sayHelloWorld() -> String {
    return "Hello World"
}
print(sayHelloWorld())

// 多参数函数
func greet(person: String, alreadyGreeted: Bool) -> String {
    return alreadyGreeted ? greetAgain(person: person) : greet(person: person)
}
print(greet(person: "Tim", alreadyGreeted: false))

// 无返回值函数
func greet2(person: String) {
    print("Hello, (person)")
}
greet2(person: "Li Lei")

// 可以忽略返回值的
func printAndCount(string: String) -> Int {
    print(string)
    return string.characters.count
}
func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
}
printAndCount(string: "Hello World")
printWithoutCounting(string: "Hello, world")

// 多重返回值函数 使用元组作为返回值
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[0..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
// 使用可选绑定进行检查
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is (bounds.min) and max is (bounds.max)")
}

// 函数参数标签和参数名称
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}
someFunction(firstParameterName: 1, secondParameterName: 2)

// 指定参数标签
func someFunction(argumentLabel parameterName: Int) {
    // 在函数体内,parameterName 代表参数值
}
someFunction(argumentLabel: 1)

func greet(person: String, from hometown: String) -> String {
    return "Hello, (person)! Glad you could visit from (hometown)"
}
print(greet(person: "XiaoHong", from: "Beijing"))

// 忽略参数标签
func someFunction2(_ firstParameterName: Int, _ secondParameterName: Int) {
    // 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}
someFunction2(1, 2)

// 默认参数值
func someFunction3(firstParameterName: Int, secondParameterName: Int = 12) {
    // 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
    print("First: (firstParameterName), and Second: (secondParameterName)")
}
someFunction3(firstParameterName: 10)
someFunction3(firstParameterName: 10, secondParameterName: 2)

// 可变参数 求一组数据的平均值
func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
print(arithmeticMean(1, 2, 3, 4, 5))

// 输入输出函数 可以改变参数
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 5
swap(&someInt, &anotherInt)
print("someInt now is (someInt) and anotherInt now is (anotherInt)")

// 函数类型
func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

var mathFunction: (Int, Int) -> Int = addTwoInts
print(mathFunction(2, 3))
mathFunction = multiplyTwoInts
print(mathFunction(2, 3))

// 函数类型作为参数类型
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: (mathFunction(a, b))")
}
printMathResult(addTwoInts, 4, 5)
printMathResult(multiplyTwoInts, 4, 5)

// 函数类型作为返回类型
func stepForward(_ input: Int) -> Int {
    return input + 1
}

func stepBackward(_ input: Int) -> Int {
    return input - 1
}

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}

var currentValue = 3
var moveNearToZero = chooseStepFunction(backward: currentValue > 0)

print("Counting to zero:")
repeat {
    print("(currentValue)...")
    currentValue = moveNearToZero(currentValue)
} while currentValue != 0
print("zero!")
print("--------------------------")

// 嵌套函数
func anotherChooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(_ input: Int) -> Int {
        return input + 1
    }

    func stepBackward(_ input: Int) -> Int {
        return input - 1
    }

    return backward ? stepBackward : stepForward
}

currentValue = -4
moveNearToZero = chooseStepFunction(backward: currentValue > 0)

print("Counting to zero:")
repeat {
    print("(currentValue)...")
    currentValue = moveNearToZero(currentValue)
} while currentValue != 0
print("zero!")

本文由365bet体育在线官网发布于网络编程,转载请注明出处:javaScript 新方向 (8)

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。