Feature #2571

文字列のハミング距離

Added by Kenta Murata about 2 years ago. Updated 10 months ago.

[ruby-dev:39975]
Status:Closed Start date:01/07/2010
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:core
Target version:1.9.2

Description

文字列のハミング距離を求めるメソッドが欲しかったため、String#hamming_distance を実装しました。
hamming_distance は長くて使いにくかったので、String#^ も定義しました。
文字数が異なる場合、および比較不可能なエンコーディングの場合は未定義とし nil を返します。

これが組み込みで使用できたら一番嬉しいのですが、採用していただく事は可能でしょうか?

0001-string.c-rb_str_hamming_distance-Init_String.patch (3.9 kB) Kenta Murata, 01/07/2010 05:06 pm

History

Updated by Kenta Murata about 2 years ago

このメソッドを Ruby で実装しようとすると、String#[] を使って比較することになると思います。
その場合、String#[] が呼び出される度に新たな文字列が生成されてしまい無駄なオブジェクトがいくつも生成されます。
文字列に対するハミング距離の解釈が変化することは殆ど無いでしょうから、
組み込みのメソッドとして実装されている方が一般的に嬉しいのではないでしょうか。

Updated by Yukihiro Matsumoto about 2 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:39975] [Feature #2571] 	文字列のハミング距離"
    on Thu, 7 Jan 2010 17:06:10 +0900, Kenta Murata <redmine@ruby-lang.org> writes:

|文字列のハミング距離を求めるメソッドが欲しかったため、String#hamming_distance を実装しました。
|hamming_distance は長くて使いにくかったので、String#^ も定義しました。
|文字数が異なる場合、および比較不可能なエンコーディングの場合は未定義とし nil を返します。
|
|これが組み込みで使用できたら一番嬉しいのですが、採用していただく事は可能でしょうか?

可能ですが、以下の点に留意して議論した上、ということになるで
しょうね。

  * String#^は意味が自明ではないので採用は難しい

  * hamming_distanceが拡張ライブラリではなく、組み込みである
    必然性、つまり応用範囲の広さについて説明が必要な気がする。

  * hamming_distanceがあれば、たとえば、Levenshtein distance
    を求めるメソッドが欲しい、とか無制限な拡張要求につながら
    ないか。

Updated by Yui NARUSE about 2 years ago

> このメソッドを Ruby で実装しようとすると、String#[] を使って比較することになると思います。

String#codepoints を使うという方法があります。
また、まつもとさんのご指摘の通り拡張ライブラリという方法もありますし、gemでもいいでしょう。

テキスト処理言語なのだから、textutils みたいなライブラリが添付されていてもいい気はしますが、
妥当に見えるユースケースがないと難しいのではないでしょうか。

Updated by Kenta Murata about 2 years ago

むらたです。

On 2010/01/07, at 17:35, Yukihiro Matsumoto wrote:

> まつもと ゆきひろです
> 
> In message "Re: [ruby-dev:39975] [Feature #2571] 	文字列のハミング距離"
>    on Thu, 7 Jan 2010 17:06:10 +0900, Kenta Murata <redmine@ruby-lang.org> writes:
> 
> |文字列のハミング距離を求めるメソッドが欲しかったため、String#hamming_distance を実装しました。
> |hamming_distance は長くて使いにくかったので、String#^ も定義しました。
> |文字数が異なる場合、および比較不可能なエンコーディングの場合は未定義とし nil を返します。
> |
> |これが組み込みで使用できたら一番嬉しいのですが、採用していただく事は可能でしょうか?
> 
> 可能ですが、以下の点に留意して議論した上、ということになるで
> しょうね。
> 
>  * String#^は意味が自明ではないので採用は難しい
> 
>  * hamming_distanceが拡張ライブラリではなく、組み込みである
>    必然性、つまり応用範囲の広さについて説明が必要な気がする。
> 
>  * hamming_distanceがあれば、たとえば、Levenshtein distance
>    を求めるメソッドが欲しい、とか無制限な拡張要求につながら
>    ないか。
> 

仰る通りで、実はこれから、編集距離も必要になることが分かっています。
また、「拡張ライブラリでいいじゃん」と言われると、なかなか反論できないですね。

改めて拡張ライブラリとして標準添付してもらえそうな道を考えてみようと思います。

ところで、拡張ライブラリにする際に、str_strlen を公開 API にしてもらいたいのですが、
それは可能でしょうか? rb_str_strlen になるのかな?

--
Kenta Murata
OpenPGP FP = FA26 35D7 4F98 3498 0810 E0D5 F213 966F E9EB 0BCC

本を書きました!!
『Ruby 逆引きレシピ』 http://www.amazon.co.jp/dp/4798119881/mrkn-22

E-mail: mrkn@mrkn.jp
twitter: http://twitter.com/mrkn/
blog: http://d.hatena.ne.jp/mrkn/

Updated by Yui NARUSE about 2 years ago

成瀬です。

(2010/01/11 15:35), Kenta Murata wrote:
> ところで、拡張ライブラリにする際に、str_strlen を公開 API にしてもらいたいのですが、
> それは可能でしょうか? rb_str_strlen になるのかな?

名前がちょっと悩む所なんですがとりあえず、

diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 14e23b8..5500a9e 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -662,6 +662,7 @@ VALUE rb_str_associated(VALUE);
 void rb_str_setter(VALUE, ID, VALUE*);
 VALUE rb_str_intern(VALUE);
 VALUE rb_sym_to_s(VALUE);
+log rb_str_strlen(VALUE, rb_encoding*);
 VALUE rb_str_length(VALUE);
 long rb_str_offset(VALUE, long);
 size_t rb_str_capacity(VALUE);
diff --git a/string.c b/string.c
index 2dcc330..6a7d625 100644
--- a/string.c
+++ b/string.c
@@ -1033,8 +1033,8 @@ count_utf8_lead_bytes_with_word(const VALUE *s)
 }
 #endif

-static long
-str_strlen(VALUE str, rb_encoding *enc)
+long
+rb_str_strlen(VALUE str, rb_encoding *enc)
 {
     const char *p, *e;
     long n;
@@ -1092,7 +1092,7 @@ rb_str_length(VALUE str)
 {
     long len;

-    len = str_strlen(str, STR_ENC_GET(str));
+    len = rb_str_strlen(str, STR_ENC_GET(str));
     return LONG2NUM(len);
 }

@@ -1573,11 +1573,11 @@ rb_str_substr(VALUE str, long beg, long len)
 	    goto sub;
 	}
 	else {
-	    beg += str_strlen(str, enc);
+	    beg += rb_str_strlen(str, enc);
 	    if (beg < 0) return Qnil;
 	}
     }
-    else if (beg > 0 && beg > str_strlen(str, enc)) {
+    else if (beg > 0 && beg > rb_str_strlen(str, enc)) {
 	return Qnil;
     }
     if (len == 0) {
@@ -2266,8 +2266,8 @@ rb_str_index(VALUE str, VALUE sub, long offset)
     if (is_broken_string(sub)) {
 	return -1;
     }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
+    len = rb_str_strlen(str, enc);
+    slen = rb_str_strlen(sub, enc);
     if (offset < 0) {
 	offset += len;
 	if (offset < 0) return -1;
@@ -2329,7 +2329,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
 	pos = 0;
     }
     if (pos < 0) {
-	pos += str_strlen(str, STR_ENC_GET(str));
+	pos += rb_str_strlen(str, STR_ENC_GET(str));
 	if (pos < 0) {
 	    if (TYPE(sub) == T_REGEXP) {
 		rb_backref_set(Qnil);
@@ -2340,7 +2340,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)

     switch (TYPE(sub)) {
       case T_REGEXP:
-	if (pos > str_strlen(str, STR_ENC_GET(str)))
+	if (pos > rb_str_strlen(str, STR_ENC_GET(str)))
 	    return Qnil;
 	pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
 			 rb_enc_check(str, sub), single_byte_optimizable(str));
@@ -2382,8 +2382,8 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
     if (is_broken_string(sub)) {
 	return -1;
     }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
+    len = rb_str_strlen(str, enc);
+    slen = rb_str_strlen(sub, enc);
     /* substring longer than string */
     if (len < slen) return -1;
     if (len - pos < slen) {
@@ -2433,7 +2433,7 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
     VALUE sub;
     VALUE vpos;
     rb_encoding *enc = STR_ENC_GET(str);
-    long pos, len = str_strlen(str, enc);
+    long pos, len = rb_str_strlen(str, enc);

     if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
 	pos = NUM2LONG(vpos);
@@ -2981,7 +2981,7 @@ rb_str_aref(VALUE str, VALUE indx)
 	    long beg, len;
 	    VALUE tmp;

-	    len = str_strlen(str, STR_ENC_GET(str));
+	    len = rb_str_strlen(str, STR_ENC_GET(str));
 	    switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
 	      case Qfalse:
 		break;
@@ -3136,7 +3136,7 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)

     StringValue(val);
     enc = rb_enc_check(str, val);
-    slen = str_strlen(str, enc);
+    slen = rb_str_strlen(str, enc);

     if (slen < beg) {
       out_of_range:
@@ -3232,14 +3232,14 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
 	    rb_raise(rb_eIndexError, "string not matched");
 	}
 	beg = rb_str_sublen(str, beg);
-	rb_str_splice(str, beg, str_strlen(indx, 0), val);
+	rb_str_splice(str, beg, rb_str_strlen(indx, 0), val);
 	return val;

       default:
 	/* check if indx is Range */
 	{
 	    long beg, len;
-	    if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, 0), 2)) {
+	    if (rb_range_beg_len(indx, &beg, &len, rb_str_strlen(str, 0), 2)) {
 		rb_str_splice(str, beg, len, val);
 		return val;
 	    }
@@ -6605,13 +6605,13 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
 	enc = rb_enc_check(str, pad);
 	f = RSTRING_PTR(pad);
 	flen = RSTRING_LEN(pad);
-	fclen = str_strlen(pad, enc);
+	fclen = rb_str_strlen(pad, enc);
 	singlebyte = single_byte_optimizable(pad);
 	if (flen == 0 || fclen == 0) {
 	    rb_raise(rb_eArgError, "zero width padding");
 	}
     }
-    len = str_strlen(str, enc);
+    len = rb_str_strlen(str, enc);
     if (width < 0 || len >= width) return rb_str_dup(str);
     n = width - len;
     llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
@@ -6829,7 +6829,7 @@ rb_str_rpartition(VALUE str, VALUE sep)
     }
     return rb_ary_new3(3, rb_str_substr(str, 0, pos),
 		          sep,
-		          rb_str_substr(str,pos+str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
+		          rb_str_substr(str,pos+rb_str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
 }

 /*

-- 
NARUSE, Yui  <naruse@airemix.jp>

Updated by Yukihiro Matsumoto about 2 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:40029] Re: [Feature #2571]  	文字列のハミング距離"
    on Mon, 11 Jan 2010 15:53:55 +0900, "NARUSE, Yui" <naruse@airemix.jp> writes:

|(2010/01/11 15:35), Kenta Murata wrote:
|> ところで、拡張ライブラリにする際に、str_strlen を公開 API にしてもらいたいのですが、
|> それは可能でしょうか? rb_str_strlen になるのかな?
|
|名前がちょっと悩む所なんですがとりあえず、

公開には賛成です。しかし、rb_str_strlen()とする時には、

  str_strlen(str, STR_ENC_GET(str))

を返す1引数の関数にするべきでは。VALUEを与えているのに
encodingも外から渡す必要はないでしょう。

Updated by Yui NARUSE about 2 years ago

成瀬です。

(2010/01/11 16:17), Yukihiro Matsumoto wrote:
> まつもと ゆきひろです
> 
> In message "Re: [ruby-dev:40029] Re: [Feature #2571]  	文字列のハミング距離"
>     on Mon, 11 Jan 2010 15:53:55 +0900, "NARUSE, Yui" <naruse@airemix.jp> writes:
> 
> |(2010/01/11 15:35), Kenta Murata wrote:
> |> ところで、拡張ライブラリにする際に、str_strlen を公開 API にしてもらいたいのですが、
> |> それは可能でしょうか? rb_str_strlen になるのかな?
> |
> |名前がちょっと悩む所なんですがとりあえず、
> 
> 公開には賛成です。しかし、rb_str_strlen()とする時には、
> 
>   str_strlen(str, STR_ENC_GET(str))
> 
> を返す1引数の関数にするべきでは。VALUEを与えているのに
> encodingも外から渡す必要はないでしょう。

確かに、修正しました。

diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 14e23b8..116afa5 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -662,6 +662,7 @@ VALUE rb_str_associated(VALUE);
 void rb_str_setter(VALUE, ID, VALUE*);
 VALUE rb_str_intern(VALUE);
 VALUE rb_sym_to_s(VALUE);
+long rb_str_strlen(VALUE);
 VALUE rb_str_length(VALUE);
 long rb_str_offset(VALUE, long);
 size_t rb_str_capacity(VALUE);
diff --git a/string.c b/string.c
index 2dcc330..a4a6122 100644
--- a/string.c
+++ b/string.c
@@ -1079,6 +1079,12 @@ str_strlen(VALUE str, rb_encoding *enc)
     return n;
 }

+long
+rb_str_strlen(VALUE str)
+{
+    return rb_str_strlen(str, STR_ENC_GET(str));
+}
+
 /*
  *  call-seq:
  *     str.length   => integer
@@ -1092,7 +1098,7 @@ rb_str_length(VALUE str)
 {
     long len;

-    len = str_strlen(str, STR_ENC_GET(str));
+    len = rb_str_strlen(str, STR_ENC_GET(str));
     return LONG2NUM(len);
 }

@@ -1573,11 +1579,11 @@ rb_str_substr(VALUE str, long beg, long len)
 	    goto sub;
 	}
 	else {
-	    beg += str_strlen(str, enc);
+	    beg += rb_str_strlen(str, enc);
 	    if (beg < 0) return Qnil;
 	}
     }
-    else if (beg > 0 && beg > str_strlen(str, enc)) {
+    else if (beg > 0 && beg > rb_str_strlen(str, enc)) {
 	return Qnil;
     }
     if (len == 0) {
@@ -2266,8 +2272,8 @@ rb_str_index(VALUE str, VALUE sub, long offset)
     if (is_broken_string(sub)) {
 	return -1;
     }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
+    len = rb_str_strlen(str, enc);
+    slen = rb_str_strlen(sub, enc);
     if (offset < 0) {
 	offset += len;
 	if (offset < 0) return -1;
@@ -2329,7 +2335,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
 	pos = 0;
     }
     if (pos < 0) {
-	pos += str_strlen(str, STR_ENC_GET(str));
+	pos += rb_str_strlen(str, STR_ENC_GET(str));
 	if (pos < 0) {
 	    if (TYPE(sub) == T_REGEXP) {
 		rb_backref_set(Qnil);
@@ -2340,7 +2346,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)

     switch (TYPE(sub)) {
       case T_REGEXP:
-	if (pos > str_strlen(str, STR_ENC_GET(str)))
+	if (pos > rb_str_strlen(str, STR_ENC_GET(str)))
 	    return Qnil;
 	pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
 			 rb_enc_check(str, sub), single_byte_optimizable(str));
@@ -2382,8 +2388,8 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
     if (is_broken_string(sub)) {
 	return -1;
     }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
+    len = rb_str_strlen(str, enc);
+    slen = rb_str_strlen(sub, enc);
     /* substring longer than string */
     if (len < slen) return -1;
     if (len - pos < slen) {
@@ -2433,7 +2439,7 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
     VALUE sub;
     VALUE vpos;
     rb_encoding *enc = STR_ENC_GET(str);
-    long pos, len = str_strlen(str, enc);
+    long pos, len = rb_str_strlen(str, enc);

     if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
 	pos = NUM2LONG(vpos);
@@ -2981,7 +2987,7 @@ rb_str_aref(VALUE str, VALUE indx)
 	    long beg, len;
 	    VALUE tmp;

-	    len = str_strlen(str, STR_ENC_GET(str));
+	    len = rb_str_strlen(str, STR_ENC_GET(str));
 	    switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
 	      case Qfalse:
 		break;
@@ -3136,7 +3142,7 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)

     StringValue(val);
     enc = rb_enc_check(str, val);
-    slen = str_strlen(str, enc);
+    slen = rb_str_strlen(str, enc);

     if (slen < beg) {
       out_of_range:
@@ -3232,14 +3238,14 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
 	    rb_raise(rb_eIndexError, "string not matched");
 	}
 	beg = rb_str_sublen(str, beg);
-	rb_str_splice(str, beg, str_strlen(indx, 0), val);
+	rb_str_splice(str, beg, rb_str_strlen(indx, 0), val);
 	return val;

       default:
 	/* check if indx is Range */
 	{
 	    long beg, len;
-	    if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, 0), 2)) {
+	    if (rb_range_beg_len(indx, &beg, &len, rb_str_strlen(str, 0), 2)) {
 		rb_str_splice(str, beg, len, val);
 		return val;
 	    }
@@ -6605,13 +6611,13 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
 	enc = rb_enc_check(str, pad);
 	f = RSTRING_PTR(pad);
 	flen = RSTRING_LEN(pad);
-	fclen = str_strlen(pad, enc);
+	fclen = rb_str_strlen(pad, enc);
 	singlebyte = single_byte_optimizable(pad);
 	if (flen == 0 || fclen == 0) {
 	    rb_raise(rb_eArgError, "zero width padding");
 	}
     }
-    len = str_strlen(str, enc);
+    len = rb_str_strlen(str, enc);
     if (width < 0 || len >= width) return rb_str_dup(str);
     n = width - len;
     llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
@@ -6829,7 +6835,7 @@ rb_str_rpartition(VALUE str, VALUE sep)
     }
     return rb_ary_new3(3, rb_str_substr(str, 0, pos),
 		          sep,
-		          rb_str_substr(str,pos+str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
+		          rb_str_substr(str,pos+rb_str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
 }

 /*

-- 
NARUSE, Yui  <naruse@airemix.jp>

Updated by Yui NARUSE about 2 years ago

成瀬です。

パッチが誤っていました、これだけですね。

diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 14e23b8..116afa5 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -662,6 +662,7 @@ VALUE rb_str_associated(VALUE);
 void rb_str_setter(VALUE, ID, VALUE*);
 VALUE rb_str_intern(VALUE);
 VALUE rb_sym_to_s(VALUE);
+long rb_str_strlen(VALUE);
 VALUE rb_str_length(VALUE);
 long rb_str_offset(VALUE, long);
 size_t rb_str_capacity(VALUE);
diff --git a/string.c b/string.c
index 2dcc330..78620b8 100644
--- a/string.c
+++ b/string.c
@@ -1079,6 +1079,12 @@ str_strlen(VALUE str, rb_encoding *enc)
     return n;
 }

+long
+rb_str_strlen(VALUE str)
+{
+    return str_strlen(str, STR_ENC_GET(str));
+}
+
 /*
  *  call-seq:
  *     str.length   => integer

(2010/01/11 16:27), NARUSE, Yui wrote:
> 成瀬です。
> 
> (2010/01/11 16:17), Yukihiro Matsumoto wrote:
>> まつもと ゆきひろです
>>
>> In message "Re: [ruby-dev:40029] Re: [Feature #2571]  	文字列のハミング距離"
>>     on Mon, 11 Jan 2010 15:53:55 +0900, "NARUSE, Yui" <naruse@airemix.jp> writes:
>>
>> |(2010/01/11 15:35), Kenta Murata wrote:
>> |> ところで、拡張ライブラリにする際に、str_strlen を公開 API にしてもらいたいのですが、
>> |> それは可能でしょうか? rb_str_strlen になるのかな?
>> |
>> |名前がちょっと悩む所なんですがとりあえず、
>>
>> 公開には賛成です。しかし、rb_str_strlen()とする時には、
>>
>>   str_strlen(str, STR_ENC_GET(str))
>>
>> を返す1引数の関数にするべきでは。VALUEを与えているのに
>> encodingも外から渡す必要はないでしょう。
> 
> 確かに、修正しました。
> 
> diff --git a/include/ruby/intern.h b/include/ruby/intern.h
> index 14e23b8..116afa5 100644
> --- a/include/ruby/intern.h
> +++ b/include/ruby/intern.h
> @@ -662,6 +662,7 @@ VALUE rb_str_associated(VALUE);
>  void rb_str_setter(VALUE, ID, VALUE*);
>  VALUE rb_str_intern(VALUE);
>  VALUE rb_sym_to_s(VALUE);
> +long rb_str_strlen(VALUE);
>  VALUE rb_str_length(VALUE);
>  long rb_str_offset(VALUE, long);
>  size_t rb_str_capacity(VALUE);
> diff --git a/string.c b/string.c
> index 2dcc330..a4a6122 100644
> --- a/string.c
> +++ b/string.c
> @@ -1079,6 +1079,12 @@ str_strlen(VALUE str, rb_encoding *enc)
>      return n;
>  }
>  
> +long
> +rb_str_strlen(VALUE str)
> +{
> +    return rb_str_strlen(str, STR_ENC_GET(str));
> +}
> +
>  /*
>   *  call-seq:
>   *     str.length   => integer
> @@ -1092,7 +1098,7 @@ rb_str_length(VALUE str)
>  {
>      long len;
>  
> -    len = str_strlen(str, STR_ENC_GET(str));
> +    len = rb_str_strlen(str, STR_ENC_GET(str));
>      return LONG2NUM(len);
>  }
>  
> @@ -1573,11 +1579,11 @@ rb_str_substr(VALUE str, long beg, long len)
>  	    goto sub;
>  	}
>  	else {
> -	    beg += str_strlen(str, enc);
> +	    beg += rb_str_strlen(str, enc);
>  	    if (beg < 0) return Qnil;
>  	}
>      }
> -    else if (beg > 0 && beg > str_strlen(str, enc)) {
> +    else if (beg > 0 && beg > rb_str_strlen(str, enc)) {
>  	return Qnil;
>      }
>      if (len == 0) {
> @@ -2266,8 +2272,8 @@ rb_str_index(VALUE str, VALUE sub, long offset)
>      if (is_broken_string(sub)) {
>  	return -1;
>      }
> -    len = str_strlen(str, enc);
> -    slen = str_strlen(sub, enc);
> +    len = rb_str_strlen(str, enc);
> +    slen = rb_str_strlen(sub, enc);
>      if (offset < 0) {
>  	offset += len;
>  	if (offset < 0) return -1;
> @@ -2329,7 +2335,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
>  	pos = 0;
>      }
>      if (pos < 0) {
> -	pos += str_strlen(str, STR_ENC_GET(str));
> +	pos += rb_str_strlen(str, STR_ENC_GET(str));
>  	if (pos < 0) {
>  	    if (TYPE(sub) == T_REGEXP) {
>  		rb_backref_set(Qnil);
> @@ -2340,7 +2346,7 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
>  
>      switch (TYPE(sub)) {
>        case T_REGEXP:
> -	if (pos > str_strlen(str, STR_ENC_GET(str)))
> +	if (pos > rb_str_strlen(str, STR_ENC_GET(str)))
>  	    return Qnil;
>  	pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
>  			 rb_enc_check(str, sub), single_byte_optimizable(str));
> @@ -2382,8 +2388,8 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
>      if (is_broken_string(sub)) {
>  	return -1;
>      }
> -    len = str_strlen(str, enc);
> -    slen = str_strlen(sub, enc);
> +    len = rb_str_strlen(str, enc);
> +    slen = rb_str_strlen(sub, enc);
>      /* substring longer than string */
>      if (len < slen) return -1;
>      if (len - pos < slen) {
> @@ -2433,7 +2439,7 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
>      VALUE sub;
>      VALUE vpos;
>      rb_encoding *enc = STR_ENC_GET(str);
> -    long pos, len = str_strlen(str, enc);
> +    long pos, len = rb_str_strlen(str, enc);
>  
>      if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
>  	pos = NUM2LONG(vpos);
> @@ -2981,7 +2987,7 @@ rb_str_aref(VALUE str, VALUE indx)
>  	    long beg, len;
>  	    VALUE tmp;
>  
> -	    len = str_strlen(str, STR_ENC_GET(str));
> +	    len = rb_str_strlen(str, STR_ENC_GET(str));
>  	    switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
>  	      case Qfalse:
>  		break;
> @@ -3136,7 +3142,7 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
>  
>      StringValue(val);
>      enc = rb_enc_check(str, val);
> -    slen = str_strlen(str, enc);
> +    slen = rb_str_strlen(str, enc);
>  
>      if (slen < beg) {
>        out_of_range:
> @@ -3232,14 +3238,14 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
>  	    rb_raise(rb_eIndexError, "string not matched");
>  	}
>  	beg = rb_str_sublen(str, beg);
> -	rb_str_splice(str, beg, str_strlen(indx, 0), val);
> +	rb_str_splice(str, beg, rb_str_strlen(indx, 0), val);
>  	return val;
>  
>        default:
>  	/* check if indx is Range */
>  	{
>  	    long beg, len;
> -	    if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, 0), 2)) {
> +	    if (rb_range_beg_len(indx, &beg, &len, rb_str_strlen(str, 0), 2)) {
>  		rb_str_splice(str, beg, len, val);
>  		return val;
>  	    }
> @@ -6605,13 +6611,13 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
>  	enc = rb_enc_check(str, pad);
>  	f = RSTRING_PTR(pad);
>  	flen = RSTRING_LEN(pad);
> -	fclen = str_strlen(pad, enc);
> +	fclen = rb_str_strlen(pad, enc);
>  	singlebyte = single_byte_optimizable(pad);
>  	if (flen == 0 || fclen == 0) {
>  	    rb_raise(rb_eArgError, "zero width padding");
>  	}
>      }
> -    len = str_strlen(str, enc);
> +    len = rb_str_strlen(str, enc);
>      if (width < 0 || len >= width) return rb_str_dup(str);
>      n = width - len;
>      llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
> @@ -6829,7 +6835,7 @@ rb_str_rpartition(VALUE str, VALUE sep)
>      }
>      return rb_ary_new3(3, rb_str_substr(str, 0, pos),
>  		          sep,
> -		          rb_str_substr(str,pos+str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
> +		          rb_str_substr(str,pos+rb_str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str)));
>  }
>  
>  /*
> 

-- 
NARUSE, Yui  <naruse@airemix.jp>

Updated by Yukihiro Matsumoto about 2 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:40033] Re: [Feature #2571]    	文字列のハミング距離"
    on Mon, 11 Jan 2010 16:32:21 +0900, "NARUSE, Yui" <naruse@airemix.jp> writes:

|パッチが誤っていました、これだけですね。

そうですね。コミットしてください。

Updated by Yukihiro Matsumoto about 2 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:40038] str_strlen() の公開名 (was Re:  Re: [Feature #2571] 文字列のハミング距離)"
    on Tue, 12 Jan 2010 01:14:08 +0900, Tadashi Saito <shiba@mail2.accsnet.ne.jp> writes:

|コミットされてしまったようですが、自分はあまりよい名前でないと思います。
|
|先ほど見たところによると、rb_str_length()という、rb_str_strlen()にとても良く似た
|関数が既に公開されているようでした。C APIユーザならば、このように名前や意味が似通った
|関数があれば、まずそれとの違いを意識したり、時には混同したりすることが予想できます。

まず、rb_str_lengthとrb_str_strlenの混同の可能性があることは、
ある程度認めます。しかし、代替である

|そういうことで自分は、rb_str_strlen()よりも、例えば
|・rb_str_length_long (型を名前に埋め込んでしまえば分かりやすいから)
|・rb_str_length_raw (VALUEに包まない「生」の値だから)
|・rb_str_length_direct (LONG2NUMという変換を通さない「直接」の結果だから)
|・rb_str_c_length (Cで直接扱える値が返るから)
|といったような「rb_str_length + α」の名前の方が望ましいと思いますが、どうで
|しょう。

はいずれも不必要に長いと感じます。ので、少なくともこれらへの
改名は賛成できません。

さらに言えば、strlenという「Cライブラリ関数の名前」は、これは
Cから直接呼び出される関数(であるからlongを返す)ことを想起させ
ます。それに間違えても、型チェックで引っかかるし。

静的型言語って素晴らしい(苦笑

Updated by Yui NARUSE about 2 years ago

成瀬です。

2010/1/12 Yukihiro Matsumoto <matz@ruby-lang.org>:
> まつもと ゆきひろです
>
> In message "Re: [ruby-dev:40038] str_strlen() の公開名 (was Re:  Re: [Feature #2571] 文字列のハミング距離)"
>    on Tue, 12 Jan 2010 01:14:08 +0900, Tadashi Saito <shiba@mail2.accsnet.ne.jp> writes:
>
> |コミットされてしまったようですが、自分はあまりよい名前でないと思います。
> |
> |先ほど見たところによると、rb_str_length()という、rb_str_strlen()にとても良く似た
> |関数が既に公開されているようでした。C APIユーザならば、このように名前や意味が似通った
> |関数があれば、まずそれとの違いを意識したり、時には混同したりすることが予想できます。
>
> まず、rb_str_lengthとrb_str_strlenの混同の可能性があることは、
> ある程度認めます。しかし、代替である

これに関しては libc の関数名なのでいいかなと思っています。

さておき、string や encoding 絡みの関数は rb_encoding* をとるんだか、かなり混乱したりはしました。
概ね、引数がVALUEか否か、戻り値がVALUEか否かで4通りになるので、
いい命名規則があればいいなぁと思ったりはします。
VALUE rbvv_str_length(VALUE);
long rbvc_str_length(VALUE);
などと妄想したりしつつ、これもなんかなぁ、とか。

-- 
NARUSE, Yui
naruse@airemix.jp

Updated by Yusuke Endoh almost 2 years ago

  • Status changed from Open to Closed
遠藤です。

本件は提案者の mrkn さんが一旦取り下げたようなので ([ruby-dev:40028]) 、
closed とします。

-- 
Yusuke Endoh <mame@tsg.ne.jp>

Also available in: Atom PDF