仓库源文站点原文

https://zhuanlan.zhihu.com/p/711324572

上文

从仓颉编程语言开发指南的“基础 I/O 操作”一节找到例程:

import std.console.*

main() {
    let txt = Console.stdIn.readln()
    println(txt ?? "")
}

运行无误,想看看是否支持 py 的 input 那样的提示符:let txt = Console.stdIn.readln("请输入:")

报错:

error: extra argument given for parameter list '()' in call
 ==> tests/input.cj:4:35:
  | 
4 |     let txt = Console.stdIn.readln("请输入:")
  |                                   ^^^^^^^^^^^^ expected 0 arguments, found 1
  | 
note: found candidate
  ==> (package std.console)console_reader.cj:59:17:

看来此api不支持,注意到 note 部分似乎建议另一个 api,但看不到具体使用方法很可惜,要是能直接提供api文档链接就好了。

回头看之前用 Random 取得随机数后与整数比较时的note:

error: invalid binary operator '>' on type 'Int64' and 'Class-Random'
 ==> tests/hi.cj:6:14:
  | 
6 |   if (猜的 > 想的) {
  |            ^ 
  | 
  # note: you may want to implement 'operator func >(right: Class-Random)' for type 'Int64'

针对性建议很实用,也很有改进空间,实际上反映了语言设计者对于常见应用场景的理解。如果结合对代码语义的分析和编写意图的推测就更好了。比如这里可以建议如何将随机数转换为整数。

将输入部分加入之前代码,从‘表达式’一节找到循环语法:

import std.console.*
import std.random.*
import std.math.*

main() {
  let 想的 = abs(Random().nextInt64()%50)

  while(true) {
    let 猜的 = Console.stdIn.readln()
    if (猜的 > 想的) {
      println("大了")
    } else if (猜的 < 想的) {
      println("小了")
    } else {
      println("${猜的} 中了!")
      break
    }
  }
}

意料中报错:

error: invalid binary operator '>' on type 'Enum-Option<Struct-String>' and 'Int64'
  ==> tests/hi.cj:10:16:
   | 
10 |     if (猜的 > 想的) {
   |              ^ 
   | 
   # note: you may want to implement 'operator func >(right: Int64)' for type 'Enum-Option<Struct-String>'

如何把字符串转为整数?

接下来就是各种尝试把字符串转换为整数:let txt = Console.stdIn.readInt64()

报错:

error: 'readInt64' is not a member of class 'ConsoleReader'
 ==> tests/input.cj:5:29:
  | 
5 |     let txt = Console.stdIn.readInt64()
  |                             ^^^^^^^^^ 
  |

let txt = Console.stdIn.readln().toInt()

error: 'toInt' is not a member of enum 'Option<Struct-String>'
 ==> tests/input.cj:5:38:
  | 
5 |     let txt = Console.stdIn.readln().toInt()
  |                                      ^^^^^

文档中有json转整数,试试:

let txt = Console.stdIn.readln()
let i = Int64.deserialize(txt)

报错:

error: mismatched types
 ==> tests/input.cj:7:31:
  | 
7 |     let i = Int64.deserialize(txt)
  |                               ^^^ expected 'Class-DataModel', found 'Enum-Option<Struct-String>'

像py那样强制转:let i = Int64(txt)

error: the expression for numeric type conversion must have a numeric type
 ==> tests/input.cj:7:19:
  | 
7 |     let i = Int64(txt)

有parse方法吗?let i = Int64.parse(txt)

error: undeclared identifier 'parse'
 ==> tests/input.cj:7:19:
  | 
7 |     let i = Int64.parse(txt)
  |                   ^^^^^

似乎还没见过编译器可以根据多次尝试来猜测用户意图并提出对应建议。

字符串比较

先试试字符串比较吧。虽然和整数比较不尽相同,比如 "20" < "3"。

强制转换还是不行:

error: undeclared identifier 'string'
 ==> tests/hi.cj:6:16:
  | 
6 |   let 想的 = string(abs(Random().nextInt64()%50))

文档里似乎看到过 toString:let 想的 = abs(Random().nextInt64()%50).toString()。终于过了:

error: invalid binary operator '>' on type 'Enum-Option<Struct-String>' and 'Struct-String'
  ==> tests/hi.cj:10:16:
   | 
10 |     if (猜的 > 想的) {
   |              ^ 
   | 
   # note: you may want to implement 'operator func >(right: Struct-String)' for type 'Enum-Option<Struct-String>'

看起来是option需要转换为普通字符串,记得一开始例程里这句:println(txt ?? "")

于是改成:let 猜的 = Console.stdIn.readln() ?? ""

终于:

import std.console.*
import std.random.*
import std.math.*

main() {
  let 想的 = abs(Random().nextInt64()%50).toString()

  while(true) {
    let 猜的 = Console.stdIn.readln() ?? ""
    if (猜的 > 想的) {
      println("大了")
    } else if (猜的 < 想的) {
      println("小了")
    } else {
      println("${猜的} 中了!")
      break
    }
  }
}

运行如下:

25
小了
37
大了
29
小了
35
大了
34
大了
32
32 中了!

还剩字符串转整数,待续。