继续 Mojo 的类型系统,今天说说字符串。
String
除了数值类型外,另一个常用的类型就是 String 了。
s = String("Mojo")
print(s)
for index in range(len(s)) :
print(s[index])
bytes = s.as_bytes()
for b in bytes:
print(b[])
输出:
Mojo
M
o
j
o
77
111
106
111
字符串里的下标 s[index] 都是按照字节的。其实可以 s._buffer 来看到:
print(Python.type(s._buffer))
会提示:
can not be converted from 'List[SIMD[si8, 1]]' to 'PythonObject'
内部就是个signed int 8 的串。内部字符是按照 UTF8 存储的,汉字就是3个字节,emoji是4个字节。

对比python中,字符串里的下标都是按照字符的(对比上图,切片的下标是不一样的):

Mojo 里面的对象,类型确定后,就不能再改变了,例如:
s = String("Mojo")
print(Python.type(s), s)
s = 100
print(Python.type(s), s)
print(s[0])
会输出:
<class 'str'> Mojo
<class 'str'> 100
1
s 的类型还是String的,s = 100 应该是做了隐式转换转成String然后赋值进去了。
针对 String 类型,也定义了一些常用的方法,例如:lower, uppder, strip, find, rfind,, startswith, endswith 等等,也没有太多特殊的东西。
StringLiteral
另外一种字符串类型是 StringLiteral (字符串字面量)
s = "Mojo"
这种方式定义出来的就是 StringLiteral,可以看做是指向一个字符串内存缓冲区的指针,可以给它赋其它的字符串值,但不能更改其类型,目前也不提供下标等等操作,因此下面的操作都是非法的:
s = "Mojo"
print(s[0]) # invalid
s = "Python" # OK
s = 100 # invalid
s = String("Rust") # invalid
print(s[0]) 会提示:
error: 'StringLiteral' is not subscriptable, it does not implement the __getitem__/__setitem__ or __refitem__ methods
s=100 会提示:
error: cannot implicitly convert 'IntLiteral' value to 'StringLiteral' in assignment
s=String() 会提示:
error: cannot implicitly convert 'String' value to 'StringLiteral' in assignment
试到此处,感觉 Mojo 的成熟度还不是很高啊,有许多地方感觉和直觉不太符合,但也不知道是设计如此、是bug、还是尚未实现。