Mojo 被设为为 Python 的超集,因此语法上有很多和 Python 类似,但由于 Mojo 的设计理念中包括:高性能、强类型、内存安全等,因此 Mojo 也从 C++ 和 Rust 中汲取了很多元素。
Mojo 的函数
Mojo 的函数可以有两种形式: fn 和 def。
def是 Python 风格的,不需要类型声明,都是动态类型的。fn则是借鉴了 Rust 风格,需要类型声明,会强制执行类型检查和保证内存安全行为。
比如:def 不需要声明参数类型和返回类型:
def sayHello1(name):
return "Hello, " + name + "!"
而使用 fn 进行定义时,则需要指定参数类型和返回类型:
fn sayHello2(name: String) -> String:
return "Hello, " + name + "!"
因此如下面的程序:
def main():
ret1 = sayHello1("Alice")
print("sayHello1:", ret1)
ret2 = sayHello2("Bob")
print("sayHello2:", ret2)
这两句都是可以的。但是发现一个特别奇怪的问题,就是打印出来内容不一样,def 的版本多打印了单引号:
sayHello1: 'Hello, Alice!'
sayHello2: Hello, Bob!
def 和 fn 的字符串类型返回值为何不一样?
于是学习过程被打扰,希望先研究下这是为什么?
首先,为了避免自己安装版本问题,到 Mojo 的 Playground上运行了一下,结果是一样的。
然后试图打印 ret1 和 ret2 的类型,但 Mojo 中没有 Python 中的 type。
/home/mojotest/hello.mojo:14:8: error: use of unknown declaration 'type'
print(type(ret1))
^~~~
使用 Mojo 和 Python 互交互方式,使用Python里面的 type来打印。
from python import Python
...
print("ret1 type:", Python.type(ret1))
print("ret2 type:", Python.type(ret2))
第一句会报错:
/home/mojotest/hello.mojo:17:19: error: invalid call to 'type': argument #0 cannot be converted from 'object' to 'PythonObject'
print(Python.type(ret1))
~~~~~~~~~~~^~~~~~
第二句则打印了:
ret2 type: <class 'str'>
感觉 def 没有定义返回值类型的情况下,返回的是 Mojo native 的 ‘object’ 类型,但如果定义了 ‘String’ 返回值类型,则返回的是一个 ‘String’对象,可以通过 Python.type 打印出其类型。
将 sayHello 改写为也带返回值的:
def sayHello3(name) -> String:
return "Hello, " + name + "!"
此时输出,和 sayHello1 是一样的,但是由于输出类型指定为 String了,那么可以输出其类型:
sayHello3: 'Hello, Alice!'
ret3 type: <class 'str'>
将 sayHello 的参数也带上类型声明(其实和 fn sayHello2() 一样了):
def sayHello4(name: String) -> String:
return "Hello, " + name + "!"
此时输出:
sayHello4: Hello, Alice!
ret4 type: <class 'str'>
这就和 sayHello2 完全一样了,ret4 可以输出type了(也是一个class ‘str’ 的PythonObject了), 输出也不带单引号。
再试下只设置参数类型,不设置返回值类型的:
def sayHello5(name: String) :
return "Hello, " + name + "!"
直接报错:(后来搜到 github 上的 issue: modularml/mojo/issues/1548,是还没有实现这个功能)
/home/chenming/mojotest/hello.mojo:16:26: error: cannot implicitly convert 'String' value to 'object' in return value
return "Hello, " + name + "!"
~~~~~~~~~~~~~~~~~^~~~~
再试试是打印问题,还是就是字符串里面就带了单引号?
s1 = ret1 + ret2
print(s1)
输出:
'Hello, Alice!'Hello, Bob!
看上去字符串里面就是带着单引号的。
感觉弄明白了返回值类型的事情,但是为啥def 的字符串返回值带单引号,fn的不带,还是没有搞清楚,感觉是bug。