Feature #5861

String#version_compare

Added by Yui NARUSE over 3 years ago. Updated over 3 years ago.

[ruby-dev:45110]
Status:Rejected
Priority:Normal
Assignee:Yukihiro Matsumoto

Description

バージョン番号っぽい文字列を比較するメソッド、String#version_compare を追加しませんか。
"2.6.18".version_compare("2.6.3") #=> 1
などと使います。

詳細な仕様は Gauche の gauche.version モジュールの version-compare 関数の仕様を丸パクリするのが良いと思います。
提案している名前も Gauche そのままです。
http://practical-scheme.net/gauche/man/gauche-refj_103.html

それなりにユースケースはある…というか今まさにテストを書いていて、
Linux カーネルのバージョン番号を欲しくなったのですが、いかがでしょうか。

History

#1 Updated by Motohiro KOSAKI over 3 years ago

バージョン番号っぽい文字列を比較するメソッド、String#version_compare を追加しませんか。
"2.6.18".version_compare("2.6.3") #=> 1
などと使います。

詳細な仕様は Gauche の gauche.version モジュールの version-compare 関数の仕様を丸パクリするのが良いと思います。
提案している名前も Gauche そのままです。
http://practical-scheme.net/gauche/man/gauche-refj_103.html

それなりにユースケースはある…というか今まさにテストを書いていて、
Linux カーネルのバージョン番号を欲しくなったのですが、いかがでしょうか。

うーん。正直ぴんときません。まずさきほどなるせさんがコミットされた
r34232ですが、バージョンの比較処理は1行で書けています

Index: test/socket/test_socket.rb

--- test/socket/test_socket.rb (revision 34231)
+++ test/socket/test_socket.rb (revision 34232)
@@ -322,6 +322,12 @@
}

   ip_addrs.each {|ai|
  • if /linux/ =~ RUBY_PLATFORM && ai.ip_address.include?('%') &&
  • (uname -r[/[0-9.]+/].split('.').map(&:to_i) <=> [2,6,18]) <= 0
  • # Cent OS 5.6 (2.6.18-238.19.1.el5xen) doesn't correctly work
  • # sendmsg with pktinfo for link-local ipv6 addresses
  • next
  • end

それに加えて、(なるせさん自身も指摘されているように)バージョン番号に規則性などないので
意図通り動かないケースが絶対でてきてバグ対応がめんどくさそうです。また、rubyのintreeでは
テストケースぐらいしかユーザがいなさそうなので、それだったら正規表現で適当に誤魔化しても
十分という気がします。

また、Linux固有の話の話として、RHEL6の2.6.32ではバグるけど、Ubuntuの2.6.32ではバグらないとか
xenカーネルでのみトラブルがおきるといった例外はいくらでも思いつき、結局、主要ユースケースが
バグ回避のワークアラウンドのような例外系である限りに置いてなんでもできる正規表現最強はゆるがないんじゃないかという感触でいます。

なにか見落としていたらご指摘よろしくお願いいたします

#2 Updated by Nobuyoshi Nakada over 3 years ago

Yui NARUSE wrote:

バージョン番号っぽい文字列を比較するメソッド、String#version_compare を追加しませんか。
"2.6.18".version_compare("2.6.3") #=> 1
などと使います。

Gem::Version.new("2.6.18")<=>Gem::Version.new("2.6.3") でいいんじゃないでしょうか。

#3 Updated by Yui NARUSE over 3 years ago

(2012/01/08 10:30), KOSAKI Motohiro wrote:

うーん。正直ぴんときません。まずさきほどなるせさんがコミットされた
r34232ですが、バージョンの比較処理は1行で書けています

  • (uname -r[/[0-9.]+/].split('.').map(&:to_i) <=> [2,6,18]) <= 0

この方法がイマイチなのは以下の 2 点ですね。
* split でたくさん String ができる
* バージョン比較という意図がわかりづらい

それに加えて、(なるせさん自身も指摘されているように)バージョン番号に規則性などないので
意図通り動かないケースが絶対でてきてバグ対応がめんどくさそうです。また、rubyのintreeでは
テストケースぐらいしかユーザがいなさそうなので、それだったら正規表現で適当に誤魔化しても
十分という気がします。

指摘しているのはわたしではなく、gauche の仕様を決めた人かマニュアルを書いた人ですね、
たぶん shiro さん?
gauche 側にとっては仕様かどうかの決定は難しい問題ですが、わたしの提案では
「gauche 仕様の丸パクリ」としているので、バグかどうかの判断は明快です。

正規表現だと "2.6.13" <=> "2.6.4" の時に面倒になります。
(ようするに Ruby と違って可変長の場合)
また、OpenSSL のようにアルファベットを使う流儀も悩ましい。

また、Linux固有の話の話として、RHEL6の2.6.32ではバグるけど、Ubuntuの2.6.32ではバグらないとか
xenカーネルでのみトラブルがおきるといった例外はいくらでも思いつき、結局、主要ユースケースが
バグ回避のワークアラウンドのような例外系である限りに置いてなんでもできる正規表現最強はゆるがないんじゃないかという感触でいます。

正規表現だと桁またいだ瞬間一気に複雑化しますからねぇ。

#4 Updated by Yukihiro Matsumoto over 3 years ago

  • Status changed from Assigned to Rejected

Stringクラスのメソッドにする必然性はないように思います。バージョン的比較というのはそこまで一般的ではないような。
不満があれば、理由を添えて再オープンしてください。

Matz.

Also available in: Atom PDF