[Feature:1.9] name referencing in sprintf

e$B1sF#$G$9!#e(B

1.9 e$B$G$O@55,I=8=$GL>A0$r;H$C$?;2>H$,$G$-$k$N$G!"e(Bsprintf e$B$G$be(B
e$BL>A0$r;H$C$?;2>H$,$G$-$k$HJXMx$8$c$J$$$G$7$g$&$+!#e(B

$ ./ruby -e ‘puts “%d : %f” % { :foo => 1, :bar => 2 }’
1 : 2.000000

$ ./ruby -e ‘printf("%d : %f\n", :foo => 1, :bar => 2)’
1 : 2.000000

e$B$"$^$j%F%9%H$7$F$$$^$;$s$,!"$?$?$-Bf$N<BAu$G$9!#e(B

Index: sprintf.c

— sprintf.c (revision 18638)
+++ sprintf.c (working copy)
@@ -103,18 +103,28 @@
} while (0)

#define GETARG() (nextvalue != Qundef ? nextvalue : \

  • posarg < 0 ? \
  • posarg == -1 ?
    (rb_raise(rb_eArgError, “unnumbered(%d) mixed with numbered”,
    nextarg), 0) : \
  • posarg == -2 ? \
  • (rb_raise(rb_eArgError, “unnumbered(%d) mixed with named”,
    nextarg), 0) :
    (posarg = nextarg++, GETNTHARG(posarg)))

#define GETPOSARG(n) (posarg > 0 ?
(rb_raise(rb_eArgError, “numbered(%d) after unnumbered(%d)”, n,
posarg), 0) : \

  • posarg == -2 ? \
  • (rb_raise(rb_eArgError, “numbered(%d) after named”, n), 0) :
    ((n < 1) ? (rb_raise(rb_eArgError, “invalid index - %d$”, n), 0) :

    (posarg = -1, GETNTHARG(n))))

#define GETNTHARG(nth)
((nth >= argc) ? (rb_raise(rb_eArgError, “too few arguments”), 0)
: argv[nth])

+#define GETNAMEARG(id) (posarg > 0 ? \

  • (rb_raise(rb_eArgError, “named after unnumbered(%d)”, posarg), 0) :
    \
  • posarg == -1 ? \
  • (rb_raise(rb_eArgError, “named after numbered”), 0) : \
  • rb_hash_aref(get_hash(&hash, argc, argv), id))

#define GETNUM(n, val)
for (; p < end && rb_enc_isdigit(*p, enc); p++) {
int next_n = 10 * n + (*p - ‘0’);
@@ -141,7 +151,22 @@
val = NUM2INT(tmp);
} while (0)

+static VALUE
+get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
+{

  • VALUE tmp;

  • if (*hash != Qundef) return *hash;

  • if (argc != 2) {

  • rb_raise(rb_eArgError, “one hash required”);

  • }

  • tmp = rb_check_convert_type(argv[1], T_HASH, “Hash”, “to_hash”);

  • if (NIL_P(tmp)) {

  • rb_raise(rb_eArgError, “one hash required”);

  • }

  • return (*hash = tmp);
    +}

/*

  • call-seq:
  • format(format_string [, arguments...] )   => string
    

@@ -412,6 +437,7 @@
VALUE nextvalue;
VALUE tmp;
VALUE str;

  • volatile VALUE hash = Qundef;

#define CHECK_FOR_WIDTH(f)
if ((f) & FWIDTH) {
@@ -513,6 +539,22 @@
flags |= FWIDTH;
goto retry;

  • case ‘<’:
  •  {
    
  • const char *start = p;
  • ID id;
  • for (; p < end && *p != ‘>’; ) {
  •    p += rb_enc_mbclen(p, end, enc);
    
  • }
  • if (p >= end) {
  •    rb_raise(rb_eArgError, "malformed name - unmatched 
    

parenthesis");

  • }
  • id = rb_intern3(start + 1, p - start - 1, enc);
  • nextvalue = GETNAMEARG(ID2SYM(id));
  • p++;
  • goto retry;
  •  }
    
  • case ‘*’:
    CHECK_FOR_WIDTH(flags);
    flags |= FWIDTH;

On Fri, 15 Aug 2008 13:08:12 +0900
In article [email protected]
[[ruby-dev:35851] [Feature:1.9] name referencing in sprintf]
“Yusuke ENDOH” [email protected] wrote:

1.9 e$B$G$O@55,I=8=$GL>A0$r;H$C$?;2>H$,$G$-$k$N$G!"e(Bsprintf e$B$G$be(B
e$BL>A0$r;H$C$?;2>H$,$G$-$k$HJXMx$8$c$J$$$G$7$g$&$+!#e(B

$ ./ruby -e ‘puts “%d : %f” % { :foo => 1, :bar => 2 }’

Ruby-GetText e$B$Ge(B %{foo}
e$B$H$$$&$N$r;H$C$F$$$k$N$G!“9g$o$;$F$”$k$H4r$7$$?Me(B
e$B$,B?$$$+$H!#=q<0;XDj$O$G$-$J$$$N$G$9$,!#e(B

{} e$B$O=q<0;XDjL5$7HG!"e(B<> e$B$OM-$jHGe(B e$B$K$9$k$H$+!)e(B

e$B$J$+$@$G$9!#e(B

At Fri, 15 Aug 2008 14:20:15 +0900,
Tietew wrote in [ruby-dev:35852]:

On Fri, 15 Aug 2008 13:08:12 +0900
In article [email protected]
[[ruby-dev:35851] [Feature:1.9] name referencing in sprintf]
“Yusuke ENDOH” [email protected] wrote:

1.9 e$B$G$O@55,I=8=$GL>A0$r;H$C$?;2>H$,$G$-$k$N$G!"e(Bsprintf e$B$G$be(B
e$BL>A0$r;H$C$?;2>H$,$G$-$k$HJXMx$8$c$J$$$G$7$g$&$+!#e(B

$ ./ruby -e ‘puts “%d : %f” % { :foo => 1, :bar => 2 }’

[ruby-dev:16351]e$B$G$Oe(BPythone$B$HF1$8$/e(B %(foo)d
e$B$H$7$F$$$^$7$?!#e(B

Ruby-GetText e$B$Ge(B %{foo} e$B$H$$$&$N$r;H$C$F$$$k$N$G!“9g$o$;$F$”$k$H4r$7$$?Me(B
e$B$,B?$$$+$H!#=q<0;XDj$O$G$-$J$$$N$G$9$,!#e(B

{} e$B$O=q<0;XDjL5$7HG!"e(B<> e$B$OM-$jHGe(B e$B$K$9$k$H$+!)e(B

Ruby-GetTexte$B$N<BAu$r3NG’$7$F$$$J$$$N$G$9$,!“e(B%{}e$B0J30$N$b$N$,$”$Ce(B
e$B$F$bBg>fIW$J$N$G$7$g$&$+!#e(B

On Fri, 15 Aug 2008 16:28:56 +0900
In article [email protected]
[[ruby-dev:35853] Re: [Feature:1.9] name referencing in sprintf]
Nobuyoshi N. [email protected] wrote:

Ruby-GetText e$B$Ge(B %{foo} e$B$H$$$&$N$r;H$C$F$$$k$N$G!“9g$o$;$F$”$k$H4r$7$$?Me(B
e$B$,B?$$$+$H!#=q<0;XDj$O$G$-$J$$$N$G$9$,!#e(B

{} e$B$O=q<0;XDjL5$7HG!"e(B<> e$B$OM-$jHGe(B e$B$K$9$k$H$+!)e(B

Ruby-GetTexte$B$N<BAu$r3NG’$7$F$$$J$$$N$G$9$,!“e(B%{}e$B0J30$N$b$N$,$”$Ce(B
e$B$F$bBg>fIW$J$N$G$7$g$&$+!#e(B

Ruby-GetText e$B$Oe(B String#% e$B$@$1$r=q$-49$($F$$$F!“1&JU$,e(B Hash
e$B$@$C$?$ie(B %{…}
e$B$rCV49$7!”$5$b$J$1$l$P85$N$b$N$r8F$s$G$$$^$9!#e(B

e$B$3$&$$$&$U$&$K$J$j$^$9e(B:
“%d %{foo}” % { :foo => ‘bar’ } # => “%d bar”
“%d %{foo}” % 123 # => “123 %{foo}”

e$B@>;3OB9-$G$9!#e(B

At Fri, 15 Aug 2008 13:08:12 +0900,
Yusuke ENDOH wrote:

e$B$"$^$j%F%9%H$7$F$$$^$;$s$,!"$?$?$-Bf$N<BAu$G$9!#e(B

e$B@55,I=8=$NNc$r=P$9$N$J$i!"e(BHashe$B8BDj$G$O$J$/e(B[]e$B%a%=%C%I$r8F$s$@J}$,e(B
e$BJXMx$J$N$G$O$J$$$G$7$g$&$+!#e(B

e$B%A%1%C%He(B #442 e$B$,99?7$5$l$^$7$?!#e(B (by Yukihiro M.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r19641.

http://redmine.ruby-lang.org/issues/show/442