Project

General

Profile

Actions

Feature #512

closed

String#% behavior

Added by febuiles (Federico Builes) over 15 years ago. Updated about 12 years ago.

Status:
Rejected
Target version:
[ruby-core:18405]

Description

=begin
Right now String#% is calling #to_ary on the its arguments for every case. Should it call it on cases where it only receives one argument?

Example:

 "%c" % 65   # the call's not really necessary but it's done here.

We'd like to have this clarified for Rubyspec and for Rubinius.
Thanks
=end

Actions #1

Updated by nobu (Nobuyoshi Nakada) over 15 years ago

=begin
Sorry but I can't get your point.
String#% always can receive only one argument.
=end

Actions #2

Updated by rue (Eero Saynatkari) over 15 years ago

=begin
The potential issue is that String#% always calls #to_ary when available, even if the format string only has one substitution. In the case of "%c" % obj, #to_ary should not be called but for "%c %s" % obj it should. Would that be sensible behaviour?
=end

Actions #3

Updated by nobu (Nobuyoshi Nakada) over 15 years ago

=begin
It's an implementation detail.
I don't think it should be a part of the spec.
=end

Actions #4

Updated by larsch (Lars Christensen) over 15 years ago

=begin
> It's an implementation detail.
> I don't think it should be a part of the spec.

Somewhat contrived, but still a surprise to me:

class A
  def to_s; "Hello"; end
  def to_ary; ["Goodbye"]; end
end

puts sprintf("%s", A.new)  # => Hello
puts "%s" % A.new          # => Goodbye

On Ruby 1.8.6-p111, this prints "Hello" two times instead.

Lars

=end

Actions #5

Updated by rue (Eero Saynatkari) over 15 years ago

=begin
Nakada said: "It's an implementation detail"

I would disagree it is an implementation detail for the reason that Lars posted an example about and the inverse of the example is also true, if someone expects to have #to_ary called but it is not. I think perhaps we see the problem from different aspects. Am I correct in assuming that your point is that String#% always expects an Array argument (whether true Array or #to_ary)?

I suppose a third option would be to specify that the more specific conversion is attempted first (e.g. #to_s(tr) for %s, #to_i(nt) for %c etc.) and if it does not exist, #to_ary is attempted. To me it is more logical to never convert to Array when only one value is asked for to begin with.

My preference is only calling #to_ary when multiple substitutions exist, but it does not really matter which option is chosen. I do think it must be specified to behave one way or the other, even if it is the current implementation.

(In my opinion, any use of #to_ary, #to_int, etc. or even #to_a, #to_i can never be an implementation detail because it affects user code.)
=end

Actions #6

Updated by rabarca (Rolando Abarca) over 15 years ago

=begin
On 28-08-2008, at 10:50, Eero Saynatkari wrote:

Issue #512 has been updated by Eero Saynatkari.

Nakada said: "It's an implementation detail"

I would disagree it is an implementation detail for the reason that
Lars posted an example about and the inverse of the example is also
true, if someone expects to have #to_ary called but it is not. I
think perhaps we see the problem from different aspects. Am I
correct in assuming that your point is that String#% always expects
an Array argument (whether true Array or #to_ary)?

I suppose a third option would be to specify that the more specific
conversion is attempted first (e.g. #to_s(tr) for %s, #to_i(nt) for
%c etc.) and if it does not exist, #to_ary is attempted. To me it is
more logical to never convert to Array when only one value is asked
for to begin with.

My preference is only calling #to_ary when multiple substitutions
exist, but it does not really matter which option is chosen. I do
think it must be specified to behave one way or the other, even if
it is the current implementation.

(In my opinion, any use of #to_ary, #to_int, etc. or even #to_a,
#to_i can never be an implementation detail because it affects user
code.)

IMHO, String#% should always expect an array as the right part. Having
it to expect an object and calling #to_ary on that object is not
desirable and ambiguous. It might also lead to some sort (speculating
here) of performance penalty since it must check the number of needed
arguments before checking if the right part should be array or not. I
would expect:

"%d" % [1]

to work, and

"%d" % 1

to fail with ArgumentError or something like that. I think (again,
IMHO) that this might lead to a simpler and more efficient
implementation.
regards,

Rolando Abarca M.

=end

Actions #7

Updated by rue (Eero Saynatkari) over 15 years ago

=begin
Well, we get into the semantics of #to_ary there. My view is that an object responding to #to_ary means that the object is an Array for all intents and purposes. #to_a, on the other hand, is only an Array representation of the object. I assume that is the reason for the current implementation.
=end

Actions #8

Updated by shyouhei (Shyouhei Urabe) about 15 years ago

  • Assignee set to matz (Yukihiro Matsumoto)

=begin

=end

Actions #9

Updated by znz (Kazuhiro NISHIYAMA) about 14 years ago

  • Category set to core
  • Target version set to 2.0.0

=begin

=end

Actions #10

Updated by shyouhei (Shyouhei Urabe) over 13 years ago

  • Status changed from Open to Assigned

=begin

=end

Updated by mame (Yusuke Endoh) about 12 years ago

  • Status changed from Assigned to Rejected

Hello,

I'm rejecting this feature ticket because no progress has been made
for a long time. See [ruby-core:42391].

The following is just my personal comment.

An implementation detail is an implementation detail, even if it
affects user code.

class A
def to_s; "Hello"; end
def to_ary; ["Goodbye"]; end
end

puts sprintf("%s", A.new) #=> Hello
puts "%s" % A.new #=> Goodbye

This comparison does not make sense because this compares different
things.

puts sprintf("%s", A.new) #=> Hello
puts "%s" % [A.new] #=> Hello

There is nothing strange.
Do you complain the following behavior, too?

sprintf("%d %d", 1, 2) #=> "1 2"
"%d %d".%(1, 2) #=> wrong number of arguments(2 for 1)

--
Yusuke Endoh

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0