HarmonyOS鸿蒙Next中我是仓颉初学者,有大神帮我分析错误原因,这到底是为什么

HarmonyOS鸿蒙Next中我是仓颉初学者,有大神帮我分析错误原因,这到底是为什么 cke_388.png

cke_822.png

这段代码有错误 ,而下面的两段代码就没错误

cke_7276.png


更多关于HarmonyOS鸿蒙Next中我是仓颉初学者,有大神帮我分析错误原因,这到底是为什么的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

先检查文件夹名大小写,仓颉默认大小写敏感。 环境配好。命令行(Windows 用PowerShell),在src路径下执行:

cjc --compile-macro my_macros/*.cj

看生成xxx.my_macros.cjo和lib-macro_xxx.my_macros.dll吗,或者报什么错。 如果生成OK,在执行

cjc main.cj -o main

看生成xxx.cjo和main吗。 都生成成功就没问题,就检查vscode的sdk或插件配置。

更多关于HarmonyOS鸿蒙Next中我是仓颉初学者,有大神帮我分析错误原因,这到底是为什么的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


非常感谢您的回复

看了你发的三张图,我感觉问题不在宏定义本身,而是在仓颉宏系统(Macro)对 Token 拼接和表达式优先级的处理机制上。

你的宏定义:

public macro Square(input:Tokens):Tokens{
    input + Token(MUL) + input
}

等价于把:

@Square(x)

展开成:

x * x

第一种情况为什么报错

你写的是:

square = @Square(1+2)

宏展开后实际上变成:

1 + 2 * 1 + 2

注意!

宏只是简单的 Token 替换:

input => 1+2

所以:

input * input

变成:

1+2*1+2

而不是:

(1+2)*(1+2)

这时候会出现什么问题

仓颉宏系统在展开时要求:

input + Token(MUL) + input

最终能形成合法 AST。

但:

1+2*1+2

在 Token 级展开过程中会发生:

1
+
2
*
1
+
2

编译器需要重新解析表达式。

而你这里的宏参数:

1+2

本身就是一个复合表达式。

仓颉当前版本对:

Tokens -> Tokens

这种裸拼接并不会自动补括号。

因此展开后得到的 Token 流并不符合宏系统预期。


为什么下面这个没问题

你写:

square=@Square(3)

展开:

3*3

完全合法。


为什么这个也没问题

你写:

square=@Square((1+2))

展开:

(1+2)*(1+2)

这里:

input

本身已经带括号。

所以 Token 流变成:

(
1
+
2
)
*
(
1
+
2
)

编译器能正确构建 AST。


本质原因

这是经典的:

宏参数缺少 Parenthesization(括号保护)

问题。

C/C++ 宏里也有同样的坑:

#define SQUARE(x) x*x

SQUARE(1+2)

展开:

1+2*1+2

结果是:

5

而不是:

9

所以正确写法总是:

#define SQUARE(x) ((x)*(x))

仓颉宏里推荐这样写

如果仓颉版本支持构造括号 Token,可以写成:

public macro Square(input: Tokens): Tokens {
    Token(LPAREN)
    + input
    + Token(RPAREN)
    + Token(MUL)
    + Token(LPAREN)
    + input
    + Token(RPAREN)
}

最终展开:

(1+2)*(1+2)

为什么第三张图没有报错

我注意到第三张图目录里多了:

main.cj.macrocall

说明宏已经成功展开。

而第一张图编辑器里的红线其实发生在:

@Square(1+2)

宏展开阶段。

也就是说:

Token拼接成功
↓
语法树构建失败
↓
编辑器报错

而:

@Square((1+2))

则:

Token拼接成功
↓
AST构建成功
↓
编译通过

结论:

你的宏没有语法错误,问题出在宏参数是复合表达式时,宏展开不会自动加括号

因此:

@Square(3)

✅ 正常

@Square((1+2))

✅ 正常

@Square(1+2)

❌ 展开后变成裸 Token 流,导致解析失败(或产生非预期表达式)

这是宏系统设计导致的行为,不是你代码写错了。建议在宏定义内部给参数补括号,或者调用时统一写成:

@Square((表达式))

这样最安全。

非常感谢您

你不得发是什么错误吗?这直接简单粗暴的看源码,有点搞啊

会不会是一开始导包没成功

仓颉初学者常见错误原因:语法结构不符(如主函数 main() 定义错误)、类型声明不匹配、未正确导入标准库(如 std.base.*)或路径问题、循环/分支控制语句格式错误。请提供具体错误日志和代码片段,否则无法定位。

从截图错误信息看,通常是因为类型声明方式错误。仓颉要求变量声明使用let 变量名: 类型 = 值,而你在错误代码中可能用了类似var x = 10int x = 10这种其他语言习惯的写法,导致解析失败。正确代码应该使用了let或明确了类型后置。另外,函数定义中参数类型也需放在冒号后,比如func foo(x: Int): String,如果写成func foo(int x)就会报错。对照你下面正确的代码,就是把这两种语法对齐了。

回到顶部