不同于Rust和Kotlin,在Ruby中,-1.abs()等于1而不是-1。
Ruby
irb(main):001:0> -1.abs()
=> 1
irb(main):002:0> (-1).abs()
=> 1
irb(main):003:0> - 1.abs()
=> -1
irb(main):004:0> (- 1).abs()
=> 1
irb(main):005:0> -(1.abs())
=> -1
Rust
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2ce19310eee9a5a18189bfd202b816b2
fn main() {
println!("{}", -1.0_f64.abs());
println!("{}", (-1.0_f64).abs());
}
// -1
// 1
Kotlin
// https://pl.kotl.in/c3QSHplKw
fun Int.abs(): Int {
return kotlin.math.abs(this)
}
fun main() {
println(-1.abs())
println((-1).abs())
}
// -1
// 1
这是因为,Ruby会将 -1 整体视作一个 Token,而不是两个:一元运算符-与整数。
// https://github.com/ruby/ruby/blob/master/parse.y#L11202
static enum yytokentype
parser_yylex(struct parser_params *p)
{
...
switch (c = nextc(p)) {
...
case '-':
c = nextc(p);
...
if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p, '-'))) {
SET_LEX_STATE(EXPR_BEG);
pushback(p, c);
if (c != -1 && ISDIGIT(c)) {
return tUMINUS_NUM; // <--⚠️
}
return tUMINUS;
}
由此可见,Lexer读到-后,会再往后看1个字符(通过nextc(p)),然后根据这个字符c是否为数字(ISDIGIT(c)),返回不同的Token。
但一旦-和整数之间有空格,-还是单独的一个Token,所以- 1.abs()等于-1。
参考:stackoverflow.com/questions/5…