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?

···

--
Posted via http://www.ruby-forum.com/.

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.

···

On Wed, Aug 15, 2012 at 1:17 PM, Fred McArthur <lists@ruby-forum.com> wrote:

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?

--
Posted via http://www.ruby-forum.com/\.

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

···

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?

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!

···

--
Posted via http://www.ruby-forum.com/.

So initially I said that Thiago Massa'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 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.

and then there's this:
"Hello world!".display # This works fine!

···

--
Posted via http://www.ruby-forum.com/.

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 1:28 PM, Thiago Massa <thiagown@gmail.com> 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):

# 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.

On Wed, Aug 15, 2012 at 1:17 PM, Fred McArthur <lists@ruby-forum.com>wrote:

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?

--
Posted via http://www.ruby-forum.com/\.

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.

···

On Wed, Aug 15, 2012 at 11:28 AM, Thiago Massa <thiagown@gmail.com> wrote:

# 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.

On Wed, Aug 15, 2012 at 1:17 PM, Fred McArthur <lists@ruby-forum.com> wrote:

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?

--
Posted via http://www.ruby-forum.com/\.

Oh has it now?

1.8.7 :001 > "Hello world!".display
Hello world!
=> nil

···

On Wed, Aug 15, 2012 at 4:48 PM, Henry Maddocks <hmaddocks@me.com> 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.

--
Tony Arcieri

So initially I said that Thiago Massa'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

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.)

···

Am 17.08.2012 06:23, schrieb Fred McArthur:

--
<https://github.com/stomar/&gt;

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.

···

--
Posted via http://www.ruby-forum.com/\.

Eric Christopherson 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/&gt;

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.

···

--
Posted via http://www.ruby-forum.com/\.