Forum: Ruby Confusion with empty block printing

Posted by Love U Ruby (my-ruby)
on 2013-03-11 16:29
When I typed the below in my IRB:

{}.class
#=> Hash  #<~~ I got this one.

print {}.class
#NilClass

Why the above showing `NilClass` instead of `Hash`, but the below are
not?

print [].class
#Array=> nil
print (1..2).class
#Range=> nil
print 2.class
#Fixnum=> nil
Posted by Hans Mackowiak (hanmac)
on 2013-03-11 16:32
because
print {}.class

is parsed as (print() {}).class

where {} is the closure block and not a Hash
Posted by Love U Ruby (my-ruby)
on 2013-03-11 16:41
Hans Mackowiak wrote in post #1101101:

Can you give me a bit knowledge about `closure block` concept. I didn't 
here about it.

> where {} is the closure block and not a Hash
Posted by Hans Mackowiak (hanmac)
on 2013-03-11 16:57
i mean the blocks you used in http://www.ruby-forum.com/topic/4411871

print thinks you want to call it with a block not with a hash


normally ruby functions when you add a block to them they ignored them 
silency
Posted by Love U Ruby (my-ruby)
on 2013-03-11 18:28
Hans Mackowiak wrote in post #1101107:


> normally ruby functions when you add a block to them they ignored them
> silency

I am thinking when IRB sees that `print {}.class`, Is there any chance 
to treat it as (print {}).class #=> NilClass ?
Posted by Matthew Kerwin (mattyk)
on 2013-03-11 21:35
(Received via mailing list)
On 12 March 2013 03:29, Love U Ruby <lists@ruby-forum.com> wrote:

> Hans Mackowiak wrote in post #1101107:
>
>
> > normally ruby functions when you add a block to them they ignored them
> > silency
>
> I am thinking when IRB sees that `print {}.class`, Is there any chance
> to treat it as (print {}).class #=> NilClass ?
>

I'm pretty sure you want:   print( {}.class )
But that's not what you asked for.

This is pretty simple syntax stuff.
Posted by Love U Ruby (my-ruby)
on 2013-03-12 05:17
Matthew Kerwin wrote in post #1101134:

> I'm pretty sure you want:   print( {}.class )
> But that's not what you asked for.
>
> This is pretty simple syntax stuff.

See when typed in IRB the below it gives

{}.class
#=> Hash

And Hans said IRB treat `print {}.class` as `(print {}).class` which 
causes the output as `Nilclass`.

But I was thinking (print {}).class also results `NilClass`. So which is 
the one IRB actually recognized to give the output `NilClass`.
Posted by Love U Ruby (my-ruby)
on 2013-03-12 05:41
here I am making my confusions are more specific:

>> print(1..2).class
1..2=> NilClass
>> print (1..2).class
Range=> nil

Why the below 2 produces different output? How does `IRB` read the 
above?

>> print[].class
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):5
        from C:/Ruby193/bin/irb:12:in `<main>'
>> print [].class
Array=> nil

How does `IRB` read the above?

>> print{}.class
=> NilClass
>> print {}.class
=> NilClass

Why here both lines giving the same outputs unlike the above 2 ?
Posted by Garthy D (Guest)
on 2013-03-12 05:59
(Received via mailing list)
Please elaborate on the ways you have attempted to solve this problem
yourself, as a basic courtesy to others on this list.

http://www.catb.org/esr/faqs/smart-questions.html#beprecise

Specifically: "Describe the diagnostic steps you took to try and pin
down the problem yourself before you asked the question."
Posted by Nolic (Guest)
on 2013-03-12 06:28
(Received via mailing list)
You are messing up your code because you did not use parentheses,
leaving to ruby the task to guess what you wanted to do.

On Tue, Mar 12, 2013 at 01:41:09PM +0900, Love U Ruby wrote:
> here I am making my confusions are more specific:
>
> >> print(1..2).class
> 1..2=> NilClass
> >> print (1..2).class
> Range=> nil
(print(1..2)).class
1..2=> NilClass

print ((1..2).class)
Range=> nil

>
> How does `IRB` read the above?

(print[]).class
NoMethodError: undefined method `[]' for nil:NilClass

print ([].class)
Array=> nil

Think about what's going on when you are using or not a space character
>
> >> print{}.class
> => NilClass
> >> print {}.class
> => NilClass

This one is a bit tricker but as you are already be told, the {} is 
taken
as a block and not as a Hash. So both are interpreted in the same way.

(print{}).class
=> NilClass
(print {}).class
=> NilClass

Fortunately you won't have to do this often, won't you ?
Anyway what you probably wanted to do is this:

print({}.class)
Hash=> nil
Posted by Matthew Kerwin (mattyk)
on 2013-03-12 07:40
(Received via mailing list)
Stop using irb. Write a .rb file and run it. Then you will (hopefully) 
see
that:

1. print needs a "\n" to push output to the next line

    print 'h'
    print 'i'
    print "p\ncat"

2. anything that starts with"#=>" isn't _real_ output; it's stuff irb 
does

    x = 3  # no output

2b) those things are the _VALUE OF THE PREVIOUS EXPRESSION_

    puts '#=> ' + x.inspect

3. `print` has a _value_ of nil

    x = print('')  # x is now nil
    puts '#=> ' + x.inspect  # see?

3b) `foo.class` has a value of the object that foo is a new one of

    foo = Object.new
    foo2 = foo.class.new

4. these are the same:

    print {}

    print do
    end

4b) print {}  outputs nothing, and still has a value of nil
4c) nil.class has a value of NilClass

Sent from my phone, so excuse the typos.
Posted by Love U Ruby (my-ruby)
on 2013-03-12 08:54
First of all thanks to all guys who has shown interest in my post.

Keeping in mind @Matthew's instructions I did the below. Hope now I am 
able to clear my question once again to all the Experts out there.

C:\>irb --simple-prompt --noecho
>> {}.class
>> [].class
>> (1..2).class
>> puts (1..2).class
Range
>> puts [].class
Array
>> puts {}.class
>> print {}.class
>> p {}.class

Very strange behaviour `{}.class` is showing with every printing 
statement. But which is not the case with `[]` and `(1..2)`. Now to see 
the class `{}` I am requiring to add `()`. ~~~ actually my question was 
why I need to do add `()` that with `{}` only, which is not needed with 
`[]` and `(1..3)` ?

>> puts ({}.class)
Hash
>> p ({}.class)
Hash
>> print ({}.class)
Hash>>

Please let me know if you have any confusion to understand.
Posted by Hans Mackowiak (hanmac)
on 2013-03-12 09:00
BECAUSE { } are used for hashes AND blocks ... in this context you use 
it as a block, not as a Hash ...

thats why

>>puts {:e=>4}

raises an SYNTAXERROR
Posted by Love U Ruby (my-ruby)
on 2013-03-12 09:07
Humm,

Only within the `()` it is understood by IRB that i am feeding it a 
Hash, otherwise error.

>> puts {:a => 4}
SyntaxError: (irb):17: syntax error, unexpected tASSOC, expecting '}'
puts {:a => 4}
           ^
        from C:/Ruby193/bin/irb:12:in `<main>'
>> puts {:a => 4}.class
SyntaxError: (irb):18: syntax error, unexpected tASSOC, expecting '}'
puts {:a => 4}.class
           ^
        from C:/Ruby193/bin/irb:12:in `<main>'
============================
>> puts ({:a => 4}.class)
Hash
============================

Strange it is. would not it?
Posted by Matthew Kerwin (mattyk)
on 2013-03-12 09:35
(Received via mailing list)
Note that one of my points was that the following are the same:

    print {}

    print do
    end

See also:

    5.times { }

    5.times do
    end

But this is different:

    print nil, {}

Also, ruby method calls have optional parentheses:

    3.inspect
    3.inspect()

    foo
    foo()

    print 'x'
    print( 'x' )

The interpreter always reads curlies {} as a block unless it makes no 
sense
to do so. Parens and commas make it clear it's a variable (and thus a 
Hash).

Sent from my phone, so excuse the typos.
Posted by Love U Ruby (my-ruby)
on 2013-03-12 09:42
Thanks for your re-explanation @Matthew and @Hans. This is how IRB works 
I understood.

>> print nil, {}
{}>>
?> ^C
>> print nil, {}.class
Hash>>

Now this thread can be closed.

Thanks to all guys who helped me to understand this `micro concept`. :)
Posted by unknown (Guest)
on 2013-03-12 13:09
(Received via mailing list)
Am 12.03.2013 08:55, schrieb Love U Ruby:
> Please let me know if you have any confusion to understand.

Among the repliers there hasn't been any confusion at all.

You're question had been answered in the very first reply
(and additionally several times in later posts) so please
don't ask the same question five times but instead try to
read the answers more carefully.

To clarify (hopefully) even more: this has _nothing_ to do with IRB.
It's the Ruby _parser_ that needs and follows rules on how to
treat ambiguous expressions (like any parser does).

A different example:  2 + 3 * 4

This is parsed as 2 + (3 * 4) according to the rules for
operator precedence. If you want to enforce a different
interpretation of this expression, you need to make that clear
to the parser by adding some parentheses, e.g.  (2 + 3) * 4

Same for your question: if you want {} to be interpreted as
a hash you need to make that clear to the parser.
Posted by Love U Ruby (my-ruby)
on 2013-03-12 13:20
unknown wrote in post #1101202:

Thank you very much to you for your effort to explain me the topic in 
different way.

> A different example:  2 + 3 * 4
>
> This is parsed as 2 + (3 * 4) according to the rules for
> operator precedence. If you want to enforce a different
> interpretation of this expression, you need to make that clear
> to the parser by adding some parentheses, e.g.  (2 + 3) * 4
>
> Same for your question: if you want {} to be interpreted as
> a hash you need to make that clear to the parser.

The whole topic is understood by me.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.