String#+

Hello,

This is a small thing, but one that has ever-so-slightly annoyed me for
quite some time now. Instead of generating a TypeError on non-string input,
why not just call to_s on it? Isn’t that always what you want? Even as a
newbie, all those years ago, I still felt like there was this inconsistency:

print ‘hi’,5 # No problem.
print “hi#{5}”# All good.
print ‘hi’+5 # TypeError!

I always assumed there was some good reason for it (even if it was a bit
confusing, and probably the source of fully half of my newbie mistakes, and
which requires a disproportionate amount of my tutorial to explain…).
However, if there is a good reason for it, I still don’t see what it is.
(Mind you, I wouldn’t be surprised if there was one, but at this point I’d
also be surprised if there wasn’t one.)

You might be saying to yourself, "Why doesn’t he just use substitution?"
Well, frankly, I don’t know how everyone else uses substitution all the
time! I think it’s ugly and avoid it whenever I can. (Pretty much, I only
use it for heredocs.) Since nearly all newbies agree with me and nearly all
experienced rubyists disagree with me on that point, perhaps I’m still
clinging to my inner newbie self. :slight_smile:

In any case, how 'bout it? Let’s save newbies lots of needless TypeErrors
(“cannot convert fixnum into string?? geez, even I can do that…”), and
save me lots of needless ".to_s"s.

Chris

Hi,

This is a small thing, but one that has ever-so-slightly annoyed me for
quite some time now. Instead of generating a TypeError on non-string input,
why not just call to_s on it?

Since + serves both addition (numbers) and concatenation (strings), it
is very wise to raise error early. Wrap with String() or add .to_s
explicitly if you’re sure. It used to work as you expected, but we
regretted and changed the behavior for programming safety. TypeError
annoys, but is better than running silently with garbage result.

We are not programming in Perl. We care about type (or class) of
objects, even though we don’t care about type of variables.

						matz.
···

In message “String#+” on 03/02/01, “Chris Pine” nemo@hellotree.com writes:

> I always assumed there was some good reason for it (even if it was a bit > confusing, and probably the source of fully half of my newbie mistakes, and > which requires a disproportionate amount of my tutorial to explain...). > However, if there is a good reason for it, I still don't see what it is. > (Mind you, I wouldn't be surprised if there was one, but at this point I'd > also be surprised if there wasn't one.)

there is a good reason IMHO!

here is a real eg. i encountered :

in ruby 1.6.8

class CGI
class Session
def = key, value

@db[ key ] = value.to_s

end
end
end

now, ONLY strings can be stored as keys or values of sessions. no big deal
you say? well, say you wanted to write CGI::Session::Pstore, which would
allow a session to cache arbitrary objects, not only strings like
CGI::Session::FileStore or CGI::Session::MemoryStore.

(actual code from ruby lib - which i had to modify)

class CGI
class Session
def =(key, val)
unless @write_lock
@write_lock = true
end
unless @data
@data = @dbman.restore
end
#@data[key] = String(val) # original code
@data[key] = val
end
end

now you move on and write CGI::Session::Pstore like

http://raa.ruby-lang.org/list.rhtml?name=cgi-sess-pstore

but you worry that, in the next release the ‘little modification’ you made to
CGI::Session will adversely affect CGI::Session::FileStore and
CGI::Session::MemoryStore.

as it stands - 1.8 does not cast it’s value to string, and so i will be able
to remove my hack into CGI::Session.

moral :

if you cast arguments inside a method you are preventing
subclassing/extension and promoting white-box programming.

this holds in all languages, for example, if you wrote a C function which did
this

int
function (x)
int x;
{
unsigned char uc = (unsigned char) x;

}

users of this method would be perplexed as to why the argument went in as an
int, and all values > 255 seem to be handled identically?! so you start
looking into the library code which breaks the whole ‘black-box’ idea libraies
should manifest, etc., etc, down a road fraught with peril…

-a

···

On Sat, 1 Feb 2003, Chris Pine wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

In my opinion it is good as it is because it isnt that much work for the
Programmer, but it is for the Interpreter if u do what u want to do because
how can he be sure that it is puts string+string what u want ??? Then alot of
other rules must be changed because a fixnum objekt is different to a
stringobjekt and so u try to create a exception of the basic rules of Ruby.
That is not good ! Keep our Language clean, thats one of the Keys i like
Ruby, no exceptions, no excuses !

mfg. Jonas

···

Am Freitag, 31. Januar 2003 16:51 schrieb Chris Pine:

In any case, how 'bout it? Let’s save newbies lots of needless TypeErrors
(“cannot convert fixnum into string?? geez, even I can do that…”), and
save me lots of needless ".to_s"s.

Chris

What would you have Ruby do with this?

    print 5+' times'

Should Fixnum convert itself to a String if the right-hand argument is a
string? (In which case, String is somehow 'superior' to Fixnum, and a
whole hierarchy needs to be decided upon).

Or should it convert its right-hand argument to a Fixnum? Which probably
isn't what you want in this particular case, but might be in the different
case of

   a='10'
   print 5+a

If the interpreter tries to DWIM it's unlikely to get it right, so better
not even to try.

   print 5.to_s + ' times' # that's what I mean
   print 5 + a.to_i # that's what I mean

Regards,

Brian.

···

On Sat, Feb 01, 2003 at 12:51:35AM +0900, Chris Pine wrote:

This is a small thing, but one that has ever-so-slightly annoyed me for
quite some time now. Instead of generating a TypeError on non-string input,
why not just call to_s on it? Isn't that always what you want? Even as a
newbie, all those years ago, I still felt like there was this inconsistency:

  print 'hi',5 # No problem.
  print "hi#{5}"# All good.
  print 'hi'+5 # TypeError!

I always assumed there was some good reason for it (even if it was a bit
confusing, and probably the source of fully half of my newbie mistakes, and
which requires a disproportionate amount of my tutorial to explain...).
However, if there is a good reason for it, I still don't see what it is.

Hi Chris,

I didn’t have a real opinion on this before, and I couldn’t really be
bothered having one now, but I will say this. Given the variety of
replies here that support the current behaviour, maybe you need to
reconsider the appropriateness of the particular examples in your
tutorial.

Obviously, the “workaround” (print “hi” + 5.to_s) is unsuited for a
basic muckaround tutorial, as it is a bit messy. Since you want to
demonstrate Ruby’s ability to work with various objects, perhaps
emphasising the first one (print ‘hi’, 5) is the way to go. I see
nothing particularly wrong with this.

Perhaps the main message to come out of this is that although there is
much in Ruby that recommends it for teaching to utter newbies, that
was not in fact the driving principle behind the language. That may
or may not be reflected in that fact that I never chain arguments
with a ‘print’ statement, and extremely rarely even use ‘print’,
preferring ‘puts’. And yes, I lurve susbstitution :slight_smile:

(My point: the only time I would use ‘print’ is if I was writing a
tutorial :slight_smile:

Cheers,
Gavin

···

On Saturday, February 1, 2003, 2:51:35 AM, Chris wrote:

Hello,

print ‘hi’,5 # No problem.
print “hi#{5}”# All good.
print ‘hi’+5 # TypeError!

[…and Chris doesn’t like this ‘inconsitency’]

Hi,

···

----- Original Message -----
What would you have Ruby do with this?

print 5+' times'

TypeError.

In practice, I can’t remember this ever having been a problem (one way or
the other), so really any of the solutions you presented would be fine…
but the main issue, I think, is that anything can convert nicely into a
string, and often we want them to. The same is certainly not true for
integers.

In practice, the String#+ issue (i.e. me having to add “.to_s” somewhere)
seems to happen daily. (Like I said, it’s a small thing, but as the days
roll by, I thought I’d mention it.) My argument was a pragmatic one; but of
course, perhaps my own programming situations differ from others, so what I
find practical might in fact be peculiar. :slight_smile: Actually, I can’t remember
the last time I added two fixnums (outside of explaining it in my tutorial)!
Ironic, since I fancy myself more a mathematician than a programmer.

And I notice that you didn’t mention Array#+, probably because you didn’t
even think about it. I’m guessing that, in practice, you’d never have a
problem with that one, just as I’d never have a problem with Fixnum#+.

It just wouldn’t bother me if + wasn’t symmetric, but that’s just me.

Chris

Obviously, the “workaround” (print “hi” + 5.to_s) is unsuited for a
basic muckaround tutorial, as it is a bit messy. Since you want to
demonstrate Ruby’s ability to work with various objects, perhaps
emphasising the first one (print ‘hi’, 5) is the way to go. I see
nothing particularly wrong with this.

···

----- Original Message -----

Yes you do (as you mentioned later), and so do I: nobody uses print! Thus,
neither does my tutorial. Therefore, I cannot use (puts ‘hi’, 5) because
that outputs two lines. If I use puts, I have to use +.

----- Original Message -----
And yes, I lurve susbstitution :slight_smile:

Hmmm… perhaps you think I meant String#sub? (I don’t that I would have
been making sense if I had meant that, though. :slight_smile: What I meant was inline
substitution which does a to_s for you: “hi#{5}”

----- Original Message -----
Perhaps the main message to come out of this is that although there is
much in Ruby that recommends it for teaching to utter newbies, that
was not in fact the driving principle behind the language.

Nor was it the driving principle behind my request. (Mind you, I am
prefectly happy with matz’s answer.) If you’ll permit the somewhat silly
analogy: The fact that this feature would make Ruby easier to learn was a
small twig on the fire, as was each time it would have made my life one tiny
bit easier. The match was… well, I don’t know what the match was… I
guess I just got sick of that big stack of twigs and thought it would be
cool to finally burn it. :slight_smile: That’s why I only mentioned my tutorial
parenthetically, and why I almost didn’t put it in at all.

Of course ease of teaching was not the driving principle behind Ruby, but
surely you don’t think it a coincidence? No, it’s easy to teach because it
is easy to use, and that is one of the main driving principles behind
Ruby, and that’s why I brought it up; so it would be easier to use. (I was
generating SQL statements at the time.) But if matz says it was tried
before and was in fact harder to use, then that’s the best argument I ever
heard!

Personally, I hardly ever use numeric addition, so it would only make my
life easier. (BTW, I was only suggesting changes to String#+, not any other

  • methods, which would make + asymmetric in general, but that doesn’t bother
    me.) This is why I didn’t realize what a problem it would be for others.
    'Nuff said.

Chris