# Day5--Funny Function!一招函式打天下?

函式是每个程序语言都会有的一个语法,非常的实用,只要是编写功能,一定与函式脱离不了关系,而函式的内容,主要会有几个部分,也是这篇文章主要会提到的内容,本文章将分成几个描绘function基础功能的部分:

function的构造

内部参数(internal parameter)、外部参数(external parameter)
省略参数(Omitting parameter)、默认参数(default parameter)、可变参数函式(Variadic functions)

函式的结构,主要会长这样:

  1. 基本型
func someNoise(){
    let message = "Oops!"
    print(message)
}
someNoise()
  1. 有参数输入的型态

如果有输入参数的话,要记得在括弧内填入(参数:型别)
然後作为外部函式执行的时候,要记得函式(参数:型别)。

  1. 可回传值的型态

如果是有回传值记号:->的话,则一定要记得Return一定要在下面加上去。
原则上,上面三种样态是函式的最基础样貌。下面,则会进一步地提到函式在细节上的一些规则。

参数:内部参数(internal parameter)、外部参数(external parameter)
在上述提到函式可能产生的样态,接着要说函式在使用上,具有的一些小规则:
在使用函式的时候,可以先把函式先想成两个部分:内部、外部

  1. 内部:基本上就是func…{ }中,{}里面的地方,就是内部,而所谓的内部参数,就是game:String的部分,因为他直接的对应到的是String的输入。

  2. 外部:外部的部分,就是函式的呼叫,也就是game_commenrt(name:String)的部分,在上述的定义函式中,name这个字眼的意义就是外部参数,专门用在当函式作为是一个外面呼叫的字眼的时候,为了区分而使用的。
    所以在上面这段程序里面,name就是外部参数,game就是内部参数。

省略外部参数(Omitting parameter)

当然,假若你今天不想要额外的给定外部参数的名称,也可以用另一种方式:底线“ _ ”来做作为省略外部参数
如下所述:

那也必须注意,既然都省略了外部参数的名称了,那函数呼叫的时候,就不应该有外部参数的名字,直接把值输进去就可以运行整个函式。

默认参数(default parameter)

默认参数这件事情是建立在Bool值上的,如果在内部参数的部分,便认定goodgame的预设是true,那可以看到以下会发生的选择路径:

根据第一个呼叫函式的样态,game_comment()只需要放置外部参数的内容即可,Swift基本上会默认参数就是true,所以就直接走向回传第一个值。
而根据第二个呼叫函式的样态,game_comment()则是给定了外部参数额外的goodgame:false,所以既然特意给定了,就代表会影响Swift对於呼叫函式的认定,因而回传第二个值。

可变参数函式(variadic functions)

可变参数函数的内容其实是像下面这样的,如果Int给上了“…”就代表了可以接受多个值,而numbers就是接收了2,3,12这三个值

因此走访了这几个数字之後,就得出了下面的结果:

接着,我们要谈两种函式不一样的功能:

  1. 函式作为参数
    Well,函式作为参数这件事情,你大概就心里有个底,函式的型别大概会是这样:( )->( )、(Int)->(Int)……etc
    这是一个很巧妙的设计,而在实例中,则如下:

你可以看到outsideFunction里面承载了三个参数:

第一个是someFunction、第二个是a ,
第二个是b,
而三者共同建构出打印的字串:”Result(someFunction(a, b))”

这个时候,我们到外部来看,我们呼叫outsideFunction,然後就把三个参数个字塞了进去:insideFunction、4、50三个参数。
你看到了吗?insideFunction可以这样做为参数被使用的,但要记得它的型别!不然你就得debug了

  1. 函式作为返回型别
    函式作为反回型别这件事情,跟上面的做为参数就不同了,因为返回型别是「传回来的东西」,所以可以注意的事情则是这样:

我们可以看到在someFunction这个函式,它参数型别设定是传入布林值,传出函式型别(Int)->Int,而这个函式要我们返回一个三元运算子的运算,三元运算子的内容是这样:假若Bools是true,则走returnFunctionA,false,则走returnFunctionB。

ok,这个时候下面的someFunction(number>0)就是一个比大小的机制,它拿number来比,结果就是大,结果为true。

下面true就传入了finalFunction,既然传入值是true,那势必就选了returnFunctionA作为内部的另一个函式,所以这个时候,finalFunction(10)的10就是returnFunctionA的传入参数了。

巢状函式(nested function)

原则上,我们在过往所及的函式皆为全域函式(global function),意即:你今天只要写好了某个函式,那它在你的编译器中,都是可以被使用、应用的。
而第三者巢状函式则有不同,如果我们要描述它的结构,可以了解到:巢状函式就是一个函式包着函式的状态,里面的函式只能被包在外部的函式应用,也可以被当作返回值返回其他地方使用。

以下将以上述所及的三个重点作为主要说明:

如果将函式建立在另一个函式中,称作巢状函式(nested function),被建立在其内的函式只能在里面使用,也可以当做返回值返回以让其他地方也可以使用。

意即:我们在函式A里面建构的另一个函式B,函式B只能在函式A里使用

巢状函式的逻辑我就不再多说了,因为它大部分的程序码跟2.函式作为返回值的部分是几乎一模一样的,只是把someFunction移到最前面,然後让下面returnFunctionA、returnFunctionA两者缩排到someFunction的作用域里面。
这样就可以知道,谁是这个函式的老大,谁是小弟。

抛出函式(throwing function)

100Days of Swift中,大概对抛出函式有了这样的概念的描述:

Sometimes functions fail because they have bad input, or because something went wrong internally. Swift lets us throw errors from functions by marking them as throws before their return type, then using the throw keyword when something goes wrong.

翻译翻译:有时候函式的失败,是因为他们在输入的时候就发生错误了,或者有些东西在内部就错了,Swift让我们藉由标记throws抛出错误,因此我们使用throw这个关键字来表示有些东西错了。

不过,在执行抛出错误之前,我们大抵上会先设定,什麽东西是错误的,因此,我们会先设置一个枚举(Enum)来放置这些错误的提示,如下:

枚举在设置这些错误的时候,会先等於一个Error的协定(Protocol,
这个在之後会谈到),然後在「passwordProblem」的下面描述各式不同类型的错误。
而function则在这些错误的范例下,以抛出(throws)的关键字定义这个函式的运作方式,而如果都没有符合的条件,就以抛出(throw)这个关键字来引入枚举里面定义错误问题的项目。
不过,抛出问题,总是要解决问题吧?
所以在抛出问题後,就会需要捕获抛出的问题,因此,会使用do…catch的方式来把问题解决:

处理抛出的错误(do…try…catch)

我们先来问一个问题:假若我们没有处理错误,会发生什麽问题呢?
我这里有一个从其他地方引述的相关解答:
如果遇到错误时会将错误抛出并传递至错误处理的地方,目前尚未定义怎麽处理错误,所以这时 Swift 会自动处理,不过这可能会导致程序中止,所以我们还是自行定义错误处理的方式。

而Swift针对错误,就有它处理的方式:

Swift 使用do-catch语句来定义错误的捕获(catch)及处理,每一个catch表示可以捕获到一个错误抛出的处理方式。

总之,就上述的例子,try後面接的是抛出函式的内容,以及要置入的值,後面的catch就是针对错误的返回的处理。如果要用公式来描述,会是下面这个样子:

总之,这大概会是关於抛出函式最基础的样子,大致上再复述一下上面提到的内容:

会先定义好错误的可能项目:枚举Enum会是一个不错的方式
写一个抛出函式,注记好throws的部分,以及从中延伸出的throw的内容
再用do…try…catch去处理错误的内容。

小记:本篇会有几个基本小问题:

  1. 协定(Protocol)的理解
  2. 其实可以更多的搭配class、struct的演示,不过基於这些东西都还没有说到,所以就先不提。
tags: 铁人赛

<<:  Android Studio初学笔记-Day5-TextView

>>:  < 关於 React: 开始打地基| 图片的使用方式 >

[Day3] Playing with CSS Variables and JS

[Day3] Playing with CSS Variables and JS 运用 CSS 和 ...

TailwindCSS 从零开始 - 每个 Utility class 都支援响应式与伪类

手刻响应式网站,对我来说其实没有到很困难,但如果页面一多,时程又赶,就会很麻烦,而 Tailwin...

【网页设计 入门 】如何使用 Bootstrap 与 Github Pages 制作 个人网站 ?

简单架设 x 不失质感 目录 源起 : 开发者网站 开发工具 : Adobe Brackets 基础...

全端入门Day28_後端程序撰写之一点的Golang

昨天Go弄出了Hello World,今天就来解释怎麽写的。 Golang入门一点 先贴上昨天写的程...