Print method

Hello everyone. I’m a newbie with a question whose answer is probably
obvious, but I’m too thickheaded to figure it out, so here goes…

We can say “cba”.reverse or x.reverse and get “cba”. Also x.upcase or
“abc”.upcase and get “ABC”.

So it’s pretty clear that x and “abc” are objects, because we’re able to
use methods to send messages to them.

But when I do x.print or “abc”.print it throws an error. I have to use
print x or print “abc”, which seems to violate the “least surprise”
principle and causes sleep deprivation in clueless newbies like me.
Also,
things like print x.upcase.reverse just drive me up a wall. Why not
x.upcase.reverse.print?

Can anyone help?

Because print is not a object from the String class. So I’m going to do
what you want(save the following code as string_print.rb):

Ruby has open classes so I can open a already existing class, like of

String, and declare methods to it
class String
def print
puts self
eld
end

“abcd”.reverse.print

I hope you enjoyed.

Woops, typo.

Ruby has open classes so I can open a already existing class, like of

String, and declare methods to it
class String
def print
puts self
end
end

“abcd”.reverse.print

I hope you enjoyed.

On Wed, Aug 15, 2012 at 11:28 AM, Thiago M. [email protected]
wrote:

Because print is not a object from the String class. So I’m going to do what
you want(save the following code as string_print.rb):

No; it’s a method from Object (mixed in from Kernel, I believe). It’s
a private method, so you can’t use dot notation on it; the actual
receiver is the “main”/“toplevel” object, which happens to be an
Object.

I’m not sure what languages actually have a print-type method defined
on instances like that, but there must be some. Languages like Java
and Smalltalk define their text output methods on instances of IO
streams; you can actually do that in Ruby too, using something like
$stdout.print foo. But I guess printing values is so common that
Matz decided to basically follow the example of Perl and other
languages for which output is done with something appearing more like
a command or statement than a method.

Eric C. wrote in post #1072456:

Languages like Java
and Smalltalk define their text output methods on instances of IO
streams; you can actually do that in Ruby too, using something like
$stdout.print foo.

The OO conundrum again - function acting on two objects, which object
class does the function belong in? It could be either.

If it were string.print and you wanted to send to a different stream,
you would need to do something like

“hello”.print($stdout)

which would work fine - Reia works this way http://reia-lang.org/

However I can think of one good reason for doing it the Ruby way round.
print/puts expects a string, and it will call to_s automatically on the
argument if it is not.

“foo.print” would fail on any object which doesn’t have a print method -
or there would have to be a print method in the top-level Object which
does to_s.print. The latter would mix a public ‘print’ method into every
object - and also risks infinite recursion if to_s doesn’t actually
return a string.

Having a public to_s method is more generally useful than a public print
method, I think.

Regards,

Brian.

On Wed, Aug 15, 2012 at 4:48 PM, Henry M. [email protected]
wrote:

I know it’s a common example in OOD text books, that an object has a print
method (or draw or display), but that design is wrong. […] Ruby has done
the correct thing.

Oh has it now?

1.8.7 :001 > “Hello world!”.display
Hello world!
=> nil

On 16/08/2012, at 4:17 AM, Fred McArthur wrote:

But when I do x.print or “abc”.print it throws an error. I have to use
print x or print “abc”, which seems to violate the “least surprise”
principle and causes sleep deprivation in clueless newbies like me.
Also,
things like print x.upcase.reverse just drive me up a wall. Why not
x.upcase.reverse.print?

I know it’s a common example in OOD text books, that an object has a
print method (or draw or display), but that design is wrong.
“abc”.print makes the assumption that String has knowledge of where and
how it will be ‘printed’. String’s print implementation will have be
able to print to all known output devices. If another output device is
invented String will have to be updated or it won’t be able to print to
it.

Sure you could do “abc”.print( device) but that will put unnecessary
restrictions on the devices interface.

The correct way to do this is have each device know which types it can
print and how to print them.

$stdout.puts “abc”

The MVC pattern works this way. Ruby has done the correct thing.

Henry

Thanks for responding. I’ll have to think it over before really grasping
why it’s done the way it’s done. The example for extending class String
works well enough.

But why it’s not done that way in the first place still escapes me. For
instance, I understand the statement:

“foo.print” would fail on any object which doesn’t have a print

method

But so would reverse, upcase, downcase and all the other methods that
ARE done with dotted notation. Also if print is a private method, then
why aren’t the others? I gather it has a lot to do with selection of
output devices, but isn’t the idea of OO based in part on polymorphism,
therefore able to handle that (I’m taking a wild shot here)?

(No doubt I’ll get it when I reread the responses again.)

Lots to think about here. Thanks for everyone’s input!

Am 17.08.2012 06:23, schrieb Fred McArthur:

“abcd”.print # This works

1.print # This causes a Fixnum error

Of course, since there is no print method in the Fixnum class.
You would have to monkey patch that, too.

because “print/puts expects a string,and it will call to_s automatically
on the argument if it is not.”

Only the print method from the kernel will do that,
but 1.print tries to invoke the print method from Fixnum.

You would have to define a print method for all the classes
that you want to work with.

What’s nice about this is that it’s automatic. No need to convert a non
display number to display type in order to print it. Saves a lot of
work.

Please keep in mind that too much monkey patching might be
counterproductive or even dangerous. In your case it does
not save you any work, rather the contrary.
And locating errors might get more difficult.

I would highly recommend to simply stick with:

print ‘abc’
print 1
puts 'result: ’ << (1+2).to_s
puts “result: #{1+2}”

(There is no need to reinvent the language.)

Fred McArthur wrote in post #1072622:

But why it’s not done that way in the first place still escapes me. For
instance, I understand the statement:

“foo.print” would fail on any object which doesn’t have a print

method

But so would reverse, upcase, downcase and all the other methods that
ARE done with dotted notation. Also if print is a private method, then
why aren’t the others? I gather it has a lot to do with selection of
output devices, but isn’t the idea of OO based in part on polymorphism,
therefore able to handle that (I’m taking a wild shot here)?

With polymorphism you probably mean that the method acts differently
depending on the output device. The problem with this is that you
certainly don’t want to hardcode the output logic for some devices into
your method. This wouldn’t make any sense (as Henry already said).

So the method would have to delegate the call to the output object. In
other words, you need two different methods:

IO#print(String) --> the actual output logic
String#show(IO) --> for printing a string-like object on a device

This actually makes a lot of sense. And as you’ve already seen, that’s
pretty much what Ruby does with “print” and “display”.

The only criticism I can think of is that the top level “print” should
be removed. This would force you to either write $stdout.print(“Hallo”)
or “Hallo”.display instead of using this pseudo-imperative style.

So initially I said that Thiago M.'s class String extension worked,
and it does to a point. But not for numbers, at least not without
further mods.

class String
def print
puts self
end
end

“abcd”.print # This works

1.print # This causes a Fixnum error

because “print/puts expects a string,and it will call to_s automatically
on the argument if it is not.”

What’s nice about the standard “print” is that conversion is automatic.
No need to convert a non display number to display type in order to
print it. Saves a lot of work.

and then there’s this:
“Hello world!”.display # This works fine!