6.函数[Functions]

发布时间:2019-01-13  栏目:MyBatis  评论:0 Comments

https://docs.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql?view=sql-server-2017

注意
假诺您提供了外部参数名,那么函数在被调用时,必须接纳外部参数名。
这个版本的sayHello(_:)函数,接收多少人的名字,会同时再次来到对他们的问候:

三. 剖析函数 (Analytic
Function)

您可以用函数类型作为另一个函数的回到类型。你需要做的是在回去箭头(->)后写一个总体的函数类型。

二. 聚合函数 (Aggregate
Function)

注意
因为第一个参数默认忽略其外部参数名称,显式地写下划线是剩下的。

drop table if exists test_aggregate;

create table test_aggregate
(
event_id      varchar(100),
rk            int,
price         int
)

insert into test_aggregate
values
('a',1,10),
('a',2,10),
('a',3,50),
('b',1,10),
('b',2,20),
('b',3,30)


--1. 没有窗口函数时,用子查询
select a.event_id, 
       a.rk,  --build ranking column if needed
       a.price, 
     (select sum(price) from test_aggregate b where b.event_id = a.event_id and b.rk <= a.rk) as totalprice 
  from test_aggregate a


--2. 从SQL Server 2012起,用窗口函数
--2.1 
--没有PARTITION BY, 没有ORDER BY,为全部总计;
--只有PARTITION BY, 没有ORDER BY,为分组小计;
--只有ORDER BY,没有PARTITION BY,为全部累计求和(RANGE选项,见2.2)
select *,
     sum(price) over() as TotalPrice,
     sum(price) over(partition by event_id) as SubTotalPrice,
       sum(price) over(order by rk) as RunningTotalPrice
  from test_aggregate a

--2.2 注意ORDER BY列的选择,可能会带来不同结果
select *,
     sum(price) over(partition by event_id order by rk) as totalprice 
  from test_aggregate a
/*
event_id    rk    price    totalprice
a    1    10    10
a    2    10    20
a    3    50    70
b    1    10    10
b    2    20    30
b    3    30    60
*/

select *,
     sum(price) over(partition by event_id order by price) as totalprice 
  from test_aggregate a
/*
event_id    rk    price    totalprice
a    1    10    20
a    2    10    20
a    3    50    70
b    1    10    10
b    2    20    30
b    3    30    60
*/

--因为ORDER BY还有个子选项ROWS/RANGE,不指定的情况下默认为RANGE UNBOUNDED PRECEDING AND CURRENT ROW 
--RANGE按照ORDER BY中的列值,将相同的值的行均视为当前同一行
select  *,sum(price) over(partition by event_id order by price) as totalprice from test_aggregate a
select  *,sum(price) over(partition by event_id order by price range between unbounded preceding and current row) as totalprice from test_aggregate a

--如果ORDER BY中的列值有重复值,手动改用ROWS选项即可实现逐行累计求和
select  *,sum(price) over(partition by event_id order by price rows between unbounded preceding and current row) as totalprice from test_aggregate a

你可以在函数体中为每个参数定义默认值(Deafult
Values)。当默认值被定义后,调用这多少个函数时方可忽略这一个参数。

https://www.sqlpassion.at/archive/2015/01/22/sql-server-windowing-functions-rows-vs-range/

拔取函数类型(Using Function Types)

drop table if exists test_first_last

create table test_first_last
(
EmployeeID             int,
EnterTime              datetime,
ColorOfClothes         varchar(20)
)

insert into test_first_last
values
(1001, GETDATE()-9, 'GREEN'),
(1001, GETDATE()-8, 'RED'),
(1001, GETDATE()-7, 'YELLOW'),
(1001, GETDATE()-6, 'BLUE'),
(1002, GETDATE()-5, 'BLACK'),
(1002, GETDATE()-4, 'WHITE')

--1. 用子查询
--LastColorOfColthes
select * from test_first_last a
where not exists(select 1 from test_first_last b where a.EmployeeID = b.EmployeeID and a.EnterTime < b.EnterTime)

--LastColorOfColthes
select *
from 
(select *, ROW_NUMBER() over(partition by EmployeeID order by EnterTime DESC) num
from test_first_last ) t
where t.num =1


--2. 用窗口函数
--用LAST_VALUE时,必须加上ROWS/RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING,否则结果不正确
select *, 
       FIRST_VALUE(ColorOfClothes) OVER (PARTITION BY EmployeeID ORDER BY EnterTime DESC) as LastColorOfClothes,
       FIRST_VALUE(ColorOfClothes) OVER (PARTITION BY EmployeeID ORDER BY EnterTime ASC) as FirstColorOfClothes,
       LAST_VALUE(ColorOfClothes) OVER (PARTITION BY EmployeeID ORDER BY EnterTime ASC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as LastColorOfClothes,
       LAST_VALUE(ColorOfClothes) OVER (PARTITION BY EmployeeID ORDER BY EnterTime DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) as FirstColorOfClothes
from test_first_last

--对于显示表中所有行,并追加Last/First字段时用窗口函数方便些
--对于挑选表中某一行/多行时,用子查询更方便

一个可变参数(variadic
parameter)可以承受零个或五个值。函数调用时,你可以用可变参数来指定函数参数可以被传播不确定数量的输入值。通过在变量类型名背后插足(…)的法子来定义可变参数。

 

您可以在局部参数名前点名外部参数名,中间以空格分隔:

drop sequence if exists test_seq

create sequence test_seq
start with 1
increment by 1;

GO

drop table if exists test_next_value

create table test_next_value
(
ID         int,
Name       varchar(10)
)

insert into test_next_value(Name)
values
('AAA'),
('AAA'),
('BBB'),
('CCC')

--对于多行数据获取sequence的next value,是否使用窗口函数都会逐行计数
--窗口函数中ORDER BY用于控制不同列值的计数顺序
select *, NEXT VALUE FOR test_seq from test_next_value
select *, NEXT VALUE FOR test_seq OVER(ORDER BY Name DESC) from test_next_value

你能够使用可选绑定来检查min马克斯(_:)函数重返的是一个其实的元组值仍旧nil:

drop table if exists test_ranking

create table test_ranking
( 
id int not null,
name varchar(20) not null,
value int not null
) 

insert test_ranking 
select 1,'name1',1 union all 
select 1,'name2',2 union all 
select 2,'name3',2 union all 
select 3,'name4',2

select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY name) as num
from test_ranking

select id , name, ROW_NUMBER() over (PARTITION by id) as num
from test_ranking
/*
Msg 4112, Level 15, State 1, Line 1
The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.
*/

--ORDERY BY后面给一个和原表无关的派生列
select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY GETDATE()) as num
from test_ranking

select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY (select 0)) as num
from test_ranking

地点这么些例子中总计出从 currentValue
渐渐接近到0是需要向正数走依然向负数走。currentValue
的开首值是3,这象征 currentValue > 0 是实在(true),这将使得
chooseStepFunction(🙂 返回 stepBackward(🙂
函数。一个针对再次回到的函数的引用保存在了 moveNearerToZero 常量中。

代码示例2:移动平均

你可以用元组(tuple)类型让六个值作为一个复合值从函数中回到。

代码示例2:分组中某列最大/最小值,对应的此外列值

你可以用不同的输入值多次调用
sayHello(_:)。上边的事例体现的是用”安娜”和”Brian”调用的结果,该函数分别重回了不同的结果。

一经有个门禁系统,在职工每一遍进门时写入一条记下,记录了“身份号码”,“进门时间”,“服装颜色”,查询每个职工最终一遍进门时的“衣裳颜色”。

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)
}
  1. 排序函数 (Ranking Function) ;

  2. 聚合函数 (Aggregate Function) ;

  3. 剖析函数 (Analytic Function) ;

  4. NEXT VALUE FOR Function, 这是给sequence专用的一个函数;

下边这么些称呼 chooseStepFunction(🙂 的函数,它的回来类型是 (Int) ->
Int 类型的函数。chooseStepFunction(
🙂 按照布尔值 backwards 来回到
stepForward(🙂 函数或 stepBackward(🙂 函数:

SQL Server 2005中,窗口聚合函数仅辅助PARTITION
BY,也就是说仅能对分组的数量全体做聚合运算;

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

四. NEXT VALUE FOR Function

您不得不传递变量给输入输出参数。你不可以传播常量或者字面量(literal
value),因为这一个量是不可以被涂改的。当传入的参数作为输入输出参数时,需要在参数名前加&符,表示这么些值可以被函数修改。

 

注意
输入输出参数和再次来到值是不一样的。上边的 swapTwoInts
函数并没有概念任何重返值,但还是修改了 someInt 和 anotherInt
的值。输入输出参数是函数对函数体外爆发震慑的另一种艺术。

代码示例1:总结/小计/累计求和

在 Swift中,每个函数都有一种档次,包括函数的参数值类型和再次来到值类型。你可以把函数类型当做任何其余一般性变量类型一样处理,这样就可以更简明地把函数当做其它函数的参数,也足以从此外函数中回到函数。函数的概念可以写在其他函数定义中,这样可以在嵌套函数范围内实现效益封装。

drop table if exists test_analytic

create table test_analytic
(
SalesYear         varchar(10),
Revenue           int,
Offset            int
)

insert into test_analytic
values
(2013,1001,1),
(2014,1002,1),
(2015,1003,1),
(2016,1004,1),
(2017,1005,1),
(2018,1006,1)

--当年及去年的销售额
select *,lag(Revenue,1,null) over(order by SalesYear asc) as PreviousYearRevenue from test_analytic
select *,lag(Revenue,Offset,null) over(order by SalesYear asc) as PreviousYearRevenue from test_analytic
select *,lead(Revenue,1,null) over(order by SalesYear desc) as PreviousYearRevenue from test_analytic

--当年及下一年的销售额
select *,lead(Revenue,1,null) over(order by SalesYear asc) as NextYearRevenue from test_analytic
select *,lead(Revenue,Offset,null) over(order by SalesYear asc) as NextYearRevenue from test_analytic
select *,lag(Revenue,1,null) over(order by SalesYear desc) as NextYearRevenue from test_analytic

--可以根据offset调整跨度

在 Swift(Swift)中,使用函数类型就像使用此外连串一样。例如,你可以定义一个品类为函数的常量或变量,并将适宜的函数赋值给它:

--移动平均,举个例子,就是求前N天的平均值,和股票市场的均线类似
drop table if exists test_moving_avg

create table test_moving_avg
(
ID    int, 
Value int,
DT    datetime
)

insert into test_moving_avg 
values
(1,10,GETDATE()-10),
(2,110,GETDATE()-9),
(3,100,GETDATE()-8),
(4,80,GETDATE()-7),
(5,60,GETDATE()-6),
(6,40,GETDATE()-5),
(7,30,GETDATE()-4),
(8,50,GETDATE()-3),
(9,20,GETDATE()-2),
(10,10,GETDATE()-1)

--1. 没有窗口函数时,用子查询
select *,
(select AVG(Value) from test_moving_avg a where a.DT >= DATEADD(DAY, -5, b.DT) AND a.DT < b.DT) AS avg_value_5days
from test_moving_avg b

--2. 从SQL Server 2012起,用窗口函数
--三个内置常量,第一行,最后一行,当前行:UNBOUNDED PRECEDING, UNBOUNDED FOLLOWING, CURRENT ROW 
--在行间移动,用BETWEEN m preceding AND n following (m, n > 0)
SELECT *,
       sum(value) over (ORDER BY DT ROWS BETWEEN 5 preceding AND CURRENT ROW) moving_sum,
       avg(value) over (ORDER BY DT ROWS BETWEEN 4 preceding AND CURRENT ROW) moving_avg1,
       avg(value) over (ORDER BY DT ROWS BETWEEN 5 preceding AND 1 preceding) moving_avg2,
       avg(value) over (ORDER BY DT ROWS BETWEEN 3 preceding AND 1 following) moving_avg3
FROM  test_moving_avg
ORDER BY DT
func someFunction(firstParameterName: Int, _ secondParameterName: Int) {
    // function body goes here
    // firstParameterName and secondParameterName refer to
    // the argument values for the first and second parameters
}
someFunction(1, 2)

排序函数在语法上要求OVER子句里必须含ORDER
BY,否则语法不经过,对于不想排序的情景能够如此变化;

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

 

相似意况下,第一个参数省略其外部参数名,第二个以及随后的参数使用其局部参数名作为外部参数名。所有参数必须有绝代的局部参数名。固然六个参数可以有一样的表面参数名,但不同的表面参数名能让你的代码更有可读性。

排序函数中,ROW_NUMBER()较为常用,可用于去重、分页、分组中甄选数据,生成数字帮助表等等;

概念一个输入输出参数时,在参数定义前加 inout
关键字。一个输入输出参数有传播函数的值,这一个值被函数修改,然后被传播函数,替换原来的值。想取得更多的关于输入输出参数的细节和有关的编译器优化,请查看输入输出参数一节。

SQL Server 2012开首,窗口聚合函数匡助ORDER
BY,以及ROWS/RAGNE选项,原本需要子查询来落实的急需,如: 移动平均
(moving averages), 总结聚合 (cumulative aggregates), 累计求和 (running
totals) 等,变得进一步便宜;

这些函数的序列是:() -> Void,或者叫“没有参数,并赶回 Void
类型的函数”。

SQL Server Windowing Functions: ROWS vs. RANGE

每个函数有个函数名,用来叙述函数执行的职责。要使用一个函数时,你用函数名“调用”,并传给它出色的输入值(称作实参,arguments)。一个函数的实参必须与函数参数表里参数的次第一致。

SELECT – OVER Clause (Transact-SQL)

注意
重返值可以被忽视,但定义了有重临值的函数必须再次回到一个值,固然在函数定义底部没有回到任何值,将造成编译错误(compile-time
error)。

 

函数类型(Function Types)
每个函数都有种特定的函数类型,由函数的参数类型和再次来到类型组成。

代码示例1:取当前行某列的前一个/下一个值

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(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!

一. 排序函数(Ranking
Function)

您现在得以用 chooseStepFunction(_:) 来获取三个函数其中的一个:

参考:

从下边这一个事例中,大家得以见到 someInt 和 anotherInt 的原始值在
swapTwoInts(a: b:) 函数中被涂改,虽然它们的概念在函数体外。

帮扶文档里的代码示例很全。

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

 

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

 

多重回回值函数(Functions with Multiple Return Values)

 

if let bounds = minMax([8, -6, 2, 109, 3, 71]) {
    print("min is \(bounds.min) and max is \(bounds.max)")
}
// prints "min is -6 and max is 109"

 

下面的那个事例中,定义了一个名为min马克斯(Max)(_:)的函数,效率是在一个Int数组中找出最小值与最大值。

从SQL Server 2005起,SQL Server起初匡助窗口函数 (Window
Function),以及到SQL Server
2012,窗口函数功用增强,近日结束匡助以下二种窗口函数:

前日,moveNearerToZero 指向了天经地义的函数,它可以被用来数到0:

函数是用来成功一定任务的单身的代码块。你给一个函数起一个适宜的名字,用来标识函数做什么,并且当函数需要进行的时候,这一个名字会被用于“调用”函数。

可变参数(Variadic Parameters)

无重返值函数(Functions Without Return Values)

该定义描述了函数做什么,它愿意接收什么和推行完毕时它回到的结果是何等项目。这样的概念使得函数可以在其余地点以一种清晰的法子被调用:

当调用领先一个参数的函数时,第一个参数后的参数按照其对应的参数名称标记,函数参数命名在函数参数名称(Function
Parameter Names)有更详实的描述。

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)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers

函数参数名称(Function Parameter Names)
函数参数都有一个外表参数名(external parameter
name)和一个局部参数名(local parameter
name)。外部参数名用于在函数调用时标注传递给函数的参数,局部参数名在函数的兑现内部使用。

先是个函数 printAndCount(_:),输出一个字符串并再次来到 Int
类型的字符数。第二个函数
printWithoutCounting调用了第一个函数,不过忽略了它的重返值。当第二个函数被调用时,消息依然会由第一个函数输出,可是再次来到值不会被用到。

函数可以没有重返值。下边是 sayHello(🙂 函数的另一个本子,叫
sayGoodbye(
:),那一个函数间接出口 String 值,而不是回去它:

一经函数重回的元组类型有可能所有元组都“没有值”,你能够采用可选的(Optional)
元组重临类型反映全体元组可以是nil的事实。你可以经过在元组类型的右括号后放置一个问号来定义一个可选元组,例如(Int,
Int)?或(String, Int, Bool)?

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

你能够用(Int, Int) ->
Int这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提供。

var mathFunction: (Int, Int) -> Int = addTwoInts
本条能够解读为:

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

默认参数值(Default Parameter Values)

func sayGoodbye(personName: String) {
    print("Goodbye, \(personName)!")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"

在 sayHello(_:) 的函数体中,先定义了一个新的名为 greeting 的 String
常量,同时,把对 personName 的问讯信息赋值给了 greeting 。然后用 return
关键字把这么些问候重返出去。一旦 return greeting
被调用,该函数截至它的施行并重返 greeting 的眼前值。

注意
严加上来说,尽管并未重返值被定义,sayGoodbye(_:)
函数如故重回了值。没有概念再次来到类型的函数会再次回到特殊的值,叫
Void。它实际是一个空的元组(tuple),没有任何因素,可以写成()。
被调用时,一个函数的重返值可以被忽视:

负有的那一个信息汇聚起来成为函数的定义,并以 func
作为前缀。指定函数再次回到类型时,用重返箭头
->(一个连字符后跟一个右尖括号)后跟回来类型的名目的措施来代表。

若果您不想为第二个及后续的参数设置外部参数名,用一个下划线(_)代替一个明明的参数名。

minMax(_:)的函数体中,在起初的时候设置多少个干活变量currentMin和current马克斯(Max)的值为数组中的第一个数。然后函数会遍历数组中剩下的值并检讨该值是否比currentMin和current马克斯更小或更大。最终数组中的最小值与最大值作为一个含有三个Int值的元组再次来到。

在底下例子中的函数叫做”sayHello(_:)”,之所以叫这么些名字,是因为这么些函数用一个人的名字当做输入,并回到给这个人的问候语。为了形成这多少个职责,你定义一个输入参数-一个号称
personName 的 String 值,和一个饱含给这厮问候语的 String
类型的再次回到值:

为每个参数指定外部参数名后,在您调用sayHello(to:and:)函数时多少个外表参数名都必须写出来。

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)
}
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // function body goes here
    // firstParameterName and secondParameterName refer to
    // the argument values for the first and second parameters
}
someFunction(1, secondParameterName: 2)

printMathResult(::🙂
函数的听从就是出口另一个恰如其分类型的数学函数的调用结果。它不关注传入函数是什么样兑现的,它只关注这么些流传的函数类型是不错的。这使得
printMathResult(
::🙂
能以一序列型安全(type-safe)的措施将一些功效转给调用者实现。

函数定义与调用(Defining and Calling Functions)
函数参数与返回值(Function Parameters and Return Values)
函数参数名称(Function Parameter Names)
函数类型(Function Types)
嵌套函数(Nested Functions)

可选元组重返类型(Optional Tuple Return Types)

为了安全地拍卖这些“空数组”问题,将min马克斯(Max)(_:)函数改写为使用可选元组再次回到类型,并且当数组为空时再次回到nil:

因为元组的成员值已被取名,因而得以经过点语法来搜寻找到的最小值与最大值:

有同样匹配类型的不比函数能够被赋值给同一个变量,就像非函数类型的变量一样:

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    return backwards ? stepBackward : stepForward
}
func sayHelloWorld() -> String {
    return "hello, world"
}
print(sayHelloWorld())
// prints "hello, world"
func someFunction(parameterWithDefault: Int = 12) {
    // function body goes here
    // if no arguments are passed to the function call,
    // value of parameterWithDefault is 12
}
someFunction(6) // parameterWithDefault is 6
someFunction() // parameterWithDefault is 12

函数可以没有参数。下边这些函数就是一个无参函数,当被调用时,它回到固定的
String 信息:

本条例子定义了 printMathResult(::_:) 函数,它有两个参数:第一个参数叫
mathFunction,类型是(Int, Int) ->
Int,你可以流传任何这系列型的函数;第二个和第几个参数叫 a 和
b,它们的项目都是 Int,这六个值作为已提交的函数的输入值。

注意
输入输出参数不可能有默认值,而且可变参数不可能用 inout 标记。
下面是例证,swapTwoInts(a: b:) 函数,有多个分级名为 a 和 b
的输入输出参数:

minMax(_:)函数再次回到一个暗含六个Int值的元组,这个值被标记为min和max,以便查询函数的归来值时可以通过名字访问它们。

func printAndCount(stringToPrint: String) -> Int {
    print(stringToPrint)
    return stringToPrint.characters.count
}
func printWithoutCounting(stringToPrint: String) {
    printAndCount(stringToPrint)
}
printAndCount("hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting("hello, world")
// prints "hello, world" but does not return a value

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

点名外部参数名(Specifying External Parameter Names)

addTwoInts 和 mathFunction 有同样的连串,所以这个赋值过程在 斯维夫特(Swift)类型检查中是允许的。

您可以用多少个 Int 型的变量来调用 swapTwoInts(a: b:)
。需要小心的是,someInt 和 anotherInt 在传出 swapTwoInts(a: b:)
函数前,都加了 & 的前缀:

以此函数用一个姓名和是否早已打过招呼作为输入,并赶回对这厮的适合问候语:

函数类型作为重返类型(Function Types as Return Types)

[The Swift Programming Language 中文版]
本页包含内容:

需要留意的是,元组的积极分子不需要在元组从函数中回到时命名,因为它们的名字已经在函数重临类型中指定了。

无参函数(Functions Without Parameters)

注意
一个函数最七只可以有一个可变参数。
万一函数有一个或五个带默认值的参数,而且还有一个可变参数,那么把可变参数放在参数表的末梢。

“定义一个号称 mathFunction 的变量,类型是‘一个有几个 Int
型的参数并回到一个 Int 型的值的函数’,并让这多少个新变量指向 addTwoInts
函数”。

调用 sayHello(🙂 函数时,在圆括号中传给它一个 String 类型的实参,例如
sayHello(“安娜(Anna)”)。因为这一个函数再次回到一个 String 类型的值,sayHello
可以被含有在 print(
:separator:terminator:)
的调用中,用来输出这个函数的重回值,正如下面所示。

函数参数与重临值(Function Parameters and Return Values)
函数参数与重临值在 斯维夫特(Swift)(Swift)中颇为灵活。你可以定义任何类型的函数,包括从只带一个未名参数的简练函数到复杂的含有表明性参数名和不同参数选项的繁杂函数。

您可以用再次回到嵌套函数的措施重写 chooseStepFunction(_:) 函数:

输入输出参数(In-Out Parameters)

print(sayHello("Anna"))
// prints "Hello, Anna!"
print(sayHello("Brian"))
// prints "Hello, Brian!"

这多少个事例中定义了两个简单的数学函数:addTwoInts 和
multiplyTwoInts。这六个函数都领受四个 Int 值, 重回一个Int值。

上面的那多少个函数用来测算一组自由长度数字的算术平均数(arithmetic mean):

您通过在括号内传递一个String参数值和一个标识为alreadyGreeted的Bool值,使用逗号分隔来调用sayHello(_:alreadyGreeted:)函数。

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

固然这么些函数没有参数,可是定义中在函数名后要么需要一对圆括号。当被调用时,也需要在函数名后写一对圆括号。

func sayHello(personName: String) -> String {
    let greeting = "Hello, " + personName + "!"
    return greeting
}
func sayHello(to person: String, and anotherPerson: String) -> String {
    return "Hello \(person) and \(anotherPerson)!"
}
print(sayHello(to: "Bill", and: "Ted"))
// prints "Hello Bill and Ted!"

多参数函数 (Functions With Multiple Parameters)

函数的概念与调用(Defining and Calling Functions)
当您定义一个函数时,你可以定义一个或多少个知名字和体系的值,作为函数的输入(称为参数,parameters),也得以定义某序列型的值作为函数执行完毕的出口(称为再次回到类型,return
type)。

为了简化这多少个函数的概念,可以将问候音信的创制和再次回到写成一句:

就像其他品类一样,当赋值一个函数给常量或变量时,你可以让 斯威夫特(Swift)(Swift)来估计其函数类型:

例如:

拔取外部函数名可以使函数以一种更具有表明性的好像句子的艺术调用,并使函数体意图清晰,更具可读性。

下边是另一个例子,一个从未有过参数,也未尝重返值的函数:

注意
将包含默认值的参数放在函数参数列表的末梢。那样能够确保在函数调用时,非默认参数的顺序是如出一辙的,同时使得一样的函数在不同情形下调用时显得越来越显明。

后天,你可以用 mathFunction 来调用被赋值的函数了:

注意
可选元组类型如(Int, Int)?与元组包含可选类型如(Int?,
Int?)是例外的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
前面的minMax(:)函数再次回到了一个暗含多少个Int值的元组。不过函数不会对传播的数组执行其它安全检查,尽管array参数是一个空数组,如上定义的minMax(:)在盘算访问array[0]时会触发一个周转时不当。

var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function

函数参数默认是常量。试图在函数体中改变参数值将会导致编译错误。这意味着你不可能错误地转移参数值。倘若您想要一个函数可以修改参数的值,并且想要在那么些改动在函数调用截止后还是存在,那么就应有把这些参数定义为输入输出参数(In-Out
Parameters)。

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

大意外部参数名(Omitting External Parameter Names)

以此 swapTwoInts(a: b:) 函数简单地交流 a 与 b 的值。该函数先将 a
的值存到一个临时常量 temporaryA 中,然后将 b 的值赋给 a,最终将
temporaryA 赋值给 b。

func sayHello(personName: String, alreadyGreeted: Bool) -> String {
    if alreadyGreeted {
        return sayHelloAgain(personName)
    } else {
        return sayHello(personName)
    }
}
print(sayHello("Tim", alreadyGreeted: true))
// prints "Hello again, Tim!"
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int

可变参数的传入值在函数体中变为此类型的一个数组。例如,一个叫做 numbers
的 Double… 型可变参数,在函数体内能够视作一个叫 numbers 的 [Double]
型的数组常量。

下边的这一个事例中定义了两个简易函数,分别是 stepForward
和stepBackward。stepForward 函数重返一个比输入值大一的值。stepBackward
函数重返一个比输入值小一的值。这六个函数的序列都是 (Int) -> Int:

斯威夫特(Swift)(Swift)统一的函数语法充分灵活,可以用来表示另外函数,包括从最简单易行的远非参数名字的
C 风格函数,到复杂的带一些和外部参数名的 Objective-C
风格函数。参数可以提供默认值,以简化函数调用。参数也可以既当做传入参数,也作为传出参数,也就是说,一旦函数执行完毕,传入的参数值可以被涂改。

嵌套函数(Nested Functions)
这章中你所看到的兼具函数都叫全局函数(global
functions),它们定义在全局域中。你也可以把函数定义在此外函数体中,称作嵌套函数(nested
functions)。

func someFunction(externalParameterName localParameterName: Int) {
    // function body goes here, and can use localParameterName
    // to refer to the argument value for that parameter
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"
func stepForward(input: Int) -> Int {
    return input + 1
}
func stepBackward(input: Int) -> Int {
    return input - 1
}

默认情状下,嵌套函数是对外界不可见的,然而可以被它们的外侧函数(enclosing
function)调用。一个外场函数也得以回到它的某一个嵌套函数,使得这一个函数可以在其余域中被选拔。

函数类型作为参数类型(Function Types as Parameter Types)

这三个函数的档次是 (Int, Int) -> Int,可以解读为“那多少个函数类型有两个Int 型的参数并赶回一个 Int 型的值。”。

func addTwoInts(a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
    return a * b
}
func sayHelloAgain(personName: String) -> String {
    return "Hello again, " + personName + "!"
}
print(sayHelloAgain("Anna"))
// prints "Hello again, Anna!"

留下评论

网站地图xml地图