Stories

Detail Return Return

從負數絕對值的計算來看Ruby的一個“奇葩”行為 - Stories Detail

計算一個數的絕對值是非常基礎的操作,幾乎所有主流的編程語言都內置了相應的函數或方法。

PHPPythonSQL 等語言中,直接調用 abs() 函數即可,例如 abs(-1)。到了 JavaC# 這類面向對象的語言中,abs() 通常是 Math 類的靜態方法,調用時要加上前綴 Math.,即 Math.abs(-1)

Go 語言就要稍微麻煩一點了,因為 math 包中的 Abs() 函數僅支持 float64 類型的參數,如果要計算整數的絕對值,就不得不先手寫一個 func abs(x int)。常刷 LeetCode 的同學對此一定深有體會——在寫實際算法之前,先要定義好 min()max()abs() 等輔助函數,都快形成肌肉記憶了吧。

本文的主角 Ruby 則更加特別,竟支持 -1.abs() 這樣的寫法。也就是説,整數(字面量)可以直接“點”一個 abs() 方法,這與大多數語言的風格都不同。

puts -1.abs()

可這也算不上 Ruby 的“奇葩”之處吧。因為在 Rust、C#、Kotlin 等語言中,類似 -1.abs() 的寫法並不稀奇。這些語言都提供了某種機制,使整數可以直接調用方法。

例如,在 C# 中,可以通過 擴展方法 (extension methods)實現類似的效果:

using System;

public static class IntExtensions {
  public static int Abs(this int value) => Math.Abs(value);
}

class Program {
  static void Main() {
    Console.WriteLine(-1.Abs());
  }
}

Rust 則乾脆直接支持 Ruby 的這種寫法,只不過要先將 -1 通過 _f64 後綴轉換為 float64 類型:

fn main() {
    println!("{}", -1_f64.abs());
}

那為什麼還説 Ruby “奇葩” 呢?請思考一下,-1.abs() 的結果應該是多少?

  • 是 -1 的絕對值嗎,即 (-1).abs() == 1
  • 還是 1 的絕對值的相反數,即 -(1.abs()) == -1

在 Rust、C#、Kotlin、Swift 等一眾語言中,-1.abs() 的結果都是 -1。而在 Ruby 中,-1.abs() 的結果是 1。表面上看,Ruby 反倒是“奇葩”的那個,但如果從直覺出發,Ruby 的行為比 Rust、C# 這些語言更貼近人們的理解吧

從左往右讀,-1.abs() 就是“負 1 的絕對值”,結果自然應該是 1。而 Rust 等語言的計算順序卻如同 “先計算 1.abs(),然後才想起來前面還一個負號呢,再取相反數”,得到 -1

那 Ruby 到底是”眾人皆醉我獨醒“,還是“旁人清醒獨我迷”呢?

其實,“奇葩”的 Ruby 沒有錯,Rust、C# 陣營也沒有錯。這並不是對錯的問題,而是不同語言(的設計者)對於 運算符優先級 的不同選擇: -(負號)和 .(方法調用)誰的優先級更高?

我們都熟悉 “先乘除,後加減”的數學運算優先級,但在編程語言的規範和設計中,.- 誰先執行並沒有公認的標準,語言的設計者會根據自己的理念做出選擇。

Ruby 的創造者 松本行弘(Matz) 曾提到:“Ruby 的設計原則之一是讓編程更快樂。

相比於 因為不瞭解 .- 的優先級而踩坑,排查半天,本以為發現了什麼“驚天 Bug”而沾沾自喜,最後卻一盆涼水澆下來,發現只是少加了個括號——還不如 Ruby 這種更符合直覺的“奇葩”行為更讓人快樂。

畢竟,直覺和可讀性也是編程體驗的重要部分。Ruby 選擇的方式可能小眾,但卻更符合人們的思維習慣。


如果習慣了 Rust、C# 陣營的解析方式,可能會覺得 Ruby “奇葩”;但對於 Ruby 的開發者而言,可能又會覺得 -1.abs() == -1 才不合理。

沒有絕對的對錯,只有不同的選擇。

user avatar ting_61d6d9790dee8 Avatar k21vin Avatar histry Avatar xingzoudedahuoji Avatar huidadebianpao Avatar f702 Avatar weidejianpan Avatar wodekouwei Avatar qcloudcommunity Avatar aibruce Avatar lixifan Avatar jueqiangdeshitou_ Avatar
Favorites 15 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.