# BOO大全/函式

### 函式

Boo 的函式以 def 关键字定义，而回传值则以 return 表示传回。

```def sqr(x as double):
return x*x
```

```double sqr(double x) {
return x*x;
}
```

```>>> res
(20, 2.4)
>>> def Fun(x as (double)):
... 	x[0] = 1.0
...
>>> Fun(res)
>>> res
(1, 2.4)
```

```def yes():
print "yes was entered"

def no():
print "no was entered"

line = prompt("enter yes or no:")
if line == "yes":
fn = yes
else:
fn = no
fn()
```

#### 递回函式

Boo 的递回函式比较特别的是，他们通常需要明确地指定回传型别，因为这很难由型别推导中得到。下面是一个很经典的阶乘递回函式：

```def fact(n as int) as int:
if n < 2:
return 1
else:
return n*fact(n-1)
```

fact 并不是个很有用或很有效率的函式，但它却很适合用来表达我想说的。

```import System.IO
def FilesInFolder(path as string, mask as string) as List:
files = [file for file in Directory.GetFiles(path,mask)]
for dir in Directory.GetDirectories(path):
return files

res = FilesInFolder(Directory.GetCurrentDirectory(),"*.boo")
print join(res,'\n')
```

```def Reverse(ls as List) as List:
if len(ls) < 2:
return ls[:]
else:
return Reverse(ls[1:])+ls[0:1]
```

#### Boo并不是Python

Boo 使用 Python 的语法，同时加入许多很酷的 Python 特性，像字串与阵列的slicing、串列...等等。但是它是个非常不同的语言，就像 Java 明显地是以C++语法为基础但却不是 C++ 一样。所以语法本身并不重要，它只是语言的表面。Python 是个动态型别的语言，Boo 则全然是个静态型别的语言 (但是，请参考 DuckTyping，只是在很多地方使用了型别推导来避免明确地指定型别。

#### 函式多载

```def Square(n as int):
return n*n

def Square(x as double):
return x*x

assert Square(10).GetType() == int
assert Square(2.3).GetType() == double
```

```def DrawBox(pos as Point, size as Size, colour as Color):
....

def DrawBox(pos as Point, size as Size):
DrawBox(pos,size,Color.Black)

def DrawBox(pos as Point):
DrawBox(pos,Size(1,1),Color.Black)
```
```與這很接近的，Boo 可以讓你在建構物件時就指定公開屬性的值，例如：btn = Button(Text : "Hello", Location : Position(100,100))
```

```>>> def f(x as single):
... 	return x
...
>>> def f(i as int):
... 	return i
...
>>> f(2.3)
-----^
ERROR: Ambiguous reference 'f': Input43Module.f(System.Single), Input44Module.f(System.Int32).
```

#### 传递多个值

```>>> def Max(*x as (double)):
... 	ret = double.MinValue
... 	for val in x:
... 		ret = System.Math.Max(ret,val)
... 	return ret
...
>>> Max(2.4,2,4,5,4)
5
>>> arr = (1.0,5,6,4,2)
>>> Max(*arr)
6
```

```import System
def PrintNumbers(s as string, *numbers as (double)):
Console.Write("{0}: ",s)
for x in numbers:
Console.Write("{0} ",x)
Console.WriteLine()

PrintNumbers("Some numbers",2,3,6,2,1)
```

#### 回传多个值

```def Modifies(ref a as int, ref x as double):
a = 20
x = 2.4

k = 1
z = 1.2
Modifies(k,z)
print k,z
```

```20 2.4
```

```>>> def ReturnsTwo():
... 	return (20,2.4)
...
>>> res = ReturnsTwo()
>>> res
(20, 2.4)
>>> x1,x2 = ReturnsTwo()
>>> print x1,x2
20 2.4
```

```>>> def ReturnsAMixedBag():
... 	return ("a string",20,2.4)
...
>>> s,i1,x1 = ReturnsAMixedBag()
```

#### 匿名函式

• 你不用取名字
• closures 包含当前的状态

```line = prompt("enter yes or no:")
if line == "yes":
fn = def():
print "yes was entered"
else:
fn = def():
print "no was entered"

fn()
```

closures 跟一般函数一样也可以有引数：

```if argv[0] == "sqr":
fn = def(x as double):
return x*x
elif argv[0] == "cube":
fn = def(x as double):
return x*x*x
```

```getline = def():
while line = getline():
print line
```

```getline = { System.Console.In.ReadLine() }
while line = getline():
print line
```

map 内建函式可以将序列里的每个元素传入指定的函式来进行处理。下面就是将序列里每个元素都作平方的例子：

```def sqr(x as double):
return x*x

iter = map(range(0,10),sqr)
print join(iter)
```

```iter = map(range(0,10)) def(x as double):
return x*x
for n in iter:
print n
```

```iter = map(range(0,10),{x as double | x*x})
for n in iter:
print n
```

closure 可以存取范围外的任何变数。

```list = [1,2,3,4,5]
sum = 0.0
l2 = map(list) def(i as int):
sum += i
return sum
print join(l2)
```

```1 3 6 10 15
```

#### callable型别

```callable DoubleFun(x as double) as double

def Dump(fn as DoubleFun):
for i in range(0,10):
print i,fn(i)

Dump(System.Math.Sin)
```

```def isqr(i as int):
return i*i

Dump(isqr)
```

```def dbl(s as string):
return s+s
Dump(dbl)
*** Dump(DoubleFun) is not compatible with the argument list
*** '(callable(System.String) as System.String)'
```

```btn.Click += def(o as object, e as EventArgs):
print "I was clicked"
```

```btn.Click += def():
print "That's better!"
```

#### ICallable界面

```class Fred(ICallable):
def Call(args as (object)) as object:
return (args[0] as string) + (args[1] as string)

f = Fred()
assert f('one','two') == 'onetwo'
```