BOO入门/函数
内建函数
编辑前面几个章节已经提过也使用过了部分函数:range()、print() 和 join()。这些都是 Boo 所内建的函数,这里列出所有 Boo 提供的内建函数:
名称 | 描述 | 范例 |
---|---|---|
将物件输出到标准输出。这与 System.Console.WriteLine 相同。 | print("hey") | |
gets | 从标准输入取得字串,与 System.Console.ReadLine() 相同。 | input = gets() |
prompt | 询问使用者特定问题并从标准输入取得字串。 | input = prompt("How are you? ") |
join | 遍访 IEnumerable 物件并将所有元素放到一个字串里。 | join([1, 2, 3, 4, 5]) == "1 2 3 4 5" |
map | 对 IEnumerable 物件里的全部元素执行同一函数,然后将结果放到一个新的 IEnumerable 物件之后回传。 | for i in map([1, 2, 3, 4, 5], { x | return x*x } ): print i(译注,例子与原文不同,这里使用 closure (类似 C# 的 anonymous method),并加上循环印出结果。 ) |
array | 用来建立一个空阵列或是将 IEnumerable 和 ICollection 物件转换为阵列。 | array(int, [1, 2, 3, 4, 5]) == (1, 2, 3, 4, 5) |
matrix | 建立多维阵列。请参考 Multidimensional Arrays 。(译注:原文找不到此节。) | matrix(int, 2, 2) |
iterator | 从物件取得一个 IEnumerable | List(iterator('abcde')) == ['a', 'b', 'c', 'd', 'e'] |
shellp | 启始一个程序,并回传 Process 物件。 | process = shellp("MyProgram.exe", "") |
shell | 执行应用程序,并将应用程序输出到标准输出的结果放到字串里面回传。 | input = shell("MyProgram.exe", "") // 译注:原文为 "echo hi there" ,经测试,不管是在 Windows 或 Linux 都无法执行 |
shellm | 在新的 AppDomain 里执行特定 managed 应用程序,同样,会把应用程序输出到标准输出的结果放到字串里面回传。 | input = shellm("MyProgram.exe", (,)) |
enumerate | 从 IEnumerator 物件建立新的 IEnumerator,但是会变成类似 (index, value) 的形式。 | array( enumerate( range(5,8) ) ) == ((0, 5), (1, 6), (2, 7)) (译注:原文用 List,这里改用 array,因为用 List 会传回 object,不容易看出结果。) |
range | 回传包含整数串列的 IEnumerable 物件。 | List(range(5)) == [0, 1, 2, 3, 4] |
reversed | 回传 IEnumerable,但里面成员的顺序会变成相反。 | List(reverse(range(5))) == [4, 3, 2, 1, 0] |
zip | 会回传一个经过混搭多个 IEnumerables 物件的 IEnumerable 物件。 | array(zip([1, 2, 3], [4, 5, 6])) == ((1, 4), (2, 5), (3, 6)) (译注:原文为 List([1,2,3],[4,5,6]),应为 zip 才对,此处已修正) 或看这个例子:array(zip(['a','b','c'],[4,5,6],['aa','bb','cc']))==(('a', 4, 'aa'), ('b', 5, 'bb'), ('c', 6, 'cc')) |
cat | 串接多个 IEnumerable 物件。 | List(cat(range(3), range(3, 6)) == [0, 1, 2, 3, 4, 5] |
这些函数你都应该要知道,因为他们非常有用,能让写程式变得更简单。
定义自己的函数
编辑定义自己的函数非常简单:
// 宣告函數
def Hello():
return "Hello, World!"
print Hello()
输出结果
Hello, World!
如果你不懂的话,下面会一步步地解说:
- def Hello():
- def 表示你要开始宣告一个函数,def 表示 define。
- Hello 是函数的名称。你可以取任何你想要的名字,但这名字里不能有空白,也不能以数字开头。
- () 表示函数要使用的引数。这里不使用任何引数,所以里面是空的。
- return "Hello, World!"
- return 是个关键字,这让函数知道该回传些什么给呼叫这个函数的地方。
- "Hello, World!" 是个字串,也就是 return 要回传的东西。
- print Hello()
- print ,我们之前提过了,就是印出变数的内容。
- Hello() 呼叫 Hello 函数,并且不带引数。
如同变数一样,函数回传值的型别也会被自动推断并决定。所以,
def Hello():
return "Hello, World!"
Hello() 将永远回传字串,所以 Boo 将会推断字串是他的回传型别。也就是跟下面的程式码一样:
def Hello() as string:
return "Hello, World!"
如果 Boo 无法推断回传型别,它会假设为 object。如果没有回传值,那么回传型别会是 void,void 表示不回传值。要定义一个无回传值的函数,就不要在函数里面使用 return,或就写 return 就好。如果函数里面有好几个 return,而回传值的型别又不同的时候,回传型别将会是最接近的原型,通常是 object,但并非绝对。
译注:"回传型别将会是最接近的原型"的意思是,如果回传的值刚好都继承同一个父类别时,回传型别将会被推断为它们的父类别。但因为 .Net 里面所有型别都兼容于 object,所以才说,"通常是 object"。另外,说兼容的原因是,像 int、bool, decimal 等等其实都是 struct,并不继承 object。
引数
编辑引数非常有用,这允许函数可以依据输入来做出不同的事情。
// 引數範例
def Hello(name as string):
return "Hello, ${name}!"
print Hello("Monkey")
输出结果
Hello, Monkey!
这里同样提供步骤的说明:
- def Hello(name as string):
- def 表示开始宣告函数。
- Hello 是函数的名称。你可以用任何你可以想到的名字,但是不能有空白,也不能以数字开头。
- (name as string) 这表示函数要使用的引数。这个函数将会使用一个引数:name。当呼叫此函数时,name 必须是个字串,否则你会得到一个编译错误 - "The best overload for the method Hello is not compatible with the argument list '(The,Types, of, The, Parameters, Entered)'."
- return "Hello, ${name}!"
- return 是个关键字,表示离开函数,并且可以传回一个值给呼叫者(当然也可以不传回值)。
- "Hello, ${name}!" 使用了字串插值将 name 的值直接放到字串里面去。
- print Hello("Monkey")
- print 正如之前提到的,就是将物件印出的 macro。
- Hello("Monkey") 将 ("Monkey") 当作引数传入并呼叫 Hello 函数。
函数的多载
编辑当函数被以不同引数宣告了数次时,函数多载就发生了。
// overloading example
def Hello():
return "Hello, World!"
def Hello(name as string):
return "Hello, ${name}!"
def Hello(num as int):
return "Hello, Number ${num}!"
def Hello(name as string, other as string):
return "Hello, ${name} and ${other}!"
print Hello()
print Hello("Monkey")
print Hello(2)
print Hello("Cat", "Dog")
输出结果
Hello, World! Hello, Monkey! Hello, Number 2! Hello, Cat and Dog!
不定个数的引数
编辑要传递不定数目的引数时,可以这么作:
// 不定引數的範例
def Test(*args as (object)):
return args.Length
print Test("hey", "there")
print Test(1, 2, 3, 4, 5)
print Test("test")
a = (5, 8, 1)
print Test(*a)
输出结果
2 5 1 3
在函数对引数的宣告加上 * 是让函数知道引数的数目将不固定,如果要直接把容器变数当作引数传递时,得在呼叫函数时加上 *,以表示要把指定容器变数里的元素当作引数传递到函数里面去。以上面的例子来说,也就是把 a 里面的三个元素当作引数传递到函数里面去。 如果有一定需要(也就是必要)的引数的话,请宣告在不定引数的前面,可千万别放到不定引数后面去了。
练习
编辑- 写个函数,让它能在传入值为偶数时,印些好的字眼﹔在传入值为奇数时,印些不好的字眼。