Newbie help

A

Ali Koubeissi

Hey, I've started with Ruby two days ago, and I have some questions.

1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won’t be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

kitty_toys =
[:shape => 'sock', :fabric => 'cashmere'] +
[:shape => 'mouse', :fabric => 'calico'] +
[:shape => 'eggroll', :fabric => 'chenille']
kitty_toys.sort_by { |toy| toy[:fabric] }

Why is he using symbols? I just couldn't understand ;(.

2- Why does a block has to be on the same line when passing argument?
Like in the previous example: kitty_toys.sort_by { |toy| toy[:fabric] }.
If I tried to move the block down, it won't work. Also, if someone could
explain how does the argument get passed to the block. I mean, based on
what?

3- How does a Ruby file compile? Like in Java, your code gets compiled
into bytecode, and then delivered to the JVM. Are there any similarities
in Ruby?

I'm currently reading Programming Ruby 2nd Edition, and this website:
http://poignantguide.net/ruby/chapter-1.html . Any recommendations ?

Thanks in advance.
 
S

Summercool

Hey, I've started with Ruby two days ago, and I have some questions.
1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won't be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

you can think of symbol as string... except symbol is always identical
if it
has the same name... two strings "title" and "title" have different
values
(the pointer to the memory location)... and you need to see the
content to
tell what the value is.

i think you can think of it as:

when Ruby see a new symbol, it gives it an ID of 1
then next time it sees a different label, it gives it an ID of 2

so when a symbol is used as a hash key, it is just using "1" as the ID
instead of a string... which will save the time of processing the
string and
help the program run faster...

although internally, i wonder whether it is 1, 2, 3, 4, etc, or the
pointer
to the symbol object like 0x32fe117F which is still a unique ID....
 
J

Jeremy Woertink

Ali said:
Hey, I've started with Ruby two days ago, and I have some questions.

1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won’t be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

kitty_toys =
[:shape => 'sock', :fabric => 'cashmere'] +
[:shape => 'mouse', :fabric => 'calico'] +
[:shape => 'eggroll', :fabric => 'chenille']
kitty_toys.sort_by { |toy| toy[:fabric] }

Why is he using symbols? I just couldn't understand ;(.

2- Why does a block has to be on the same line when passing argument?
Like in the previous example: kitty_toys.sort_by { |toy| toy[:fabric] }.
If I tried to move the block down, it won't work. Also, if someone could
explain how does the argument get passed to the block. I mean, based on
what?

3- How does a Ruby file compile? Like in Java, your code gets compiled
into bytecode, and then delivered to the JVM. Are there any similarities
in Ruby?

I'm currently reading Programming Ruby 2nd Edition, and this website:
http://poignantguide.net/ruby/chapter-1.html . Any recommendations ?

Thanks in advance.

Welcome to ruby. First to start the question about Symbols. Well, they
are used in hashes a lot, you could very well do { 'shape' => 'sock' }
and it works the same, but just to be consistent you use the object as a
symbol and it's value as what ever else. There is a lot more to that,
and i'm sure someone else will reply to tell you that.
2. A block doesn't have to be on the same line.
kitty_toys.sort_by do |toy|
toy[:fabric]
end

notice it's on 3 lines, but with this small of a block it looks ugly.

The argument gets passed to the block by means of the "slide" or the
pipes. Not sure if that was the answer you were looking for, but there
you go.

3. Ruby compiles on runtime by the ruby interpreter. I don't really know
a whole lot about how all that works.

Hope that clears something up for ya.

~Jeremy
 
S

Summercool

Hey, I've started with Ruby two days ago, and I have some questions.

1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won't be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

here are two tests:

-------------- symbol_vs_string.rb
--------------------------------------

i = 0
n = 10000000
hash = {}

hash["foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar"] =
0

start_time = Time.now

while i < n
hash["foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar"]
+= 1
i += 1
end

finish_time = Time.now

puts
hash["foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar"]



puts
puts "It took #{finish_time - start_time} seconds to run. #{(n /
(finish_time - start_time)).to_i} iterations per second."



-------------- symbol_vs_string2.rb
--------------------------------------

i = 0
n = 10000000
hash = {}

hash[:foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar] =
0

start_time = Time.now

while i < n
hash[:foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar]
+= 1
i += 1
end

finish_time = Time.now

puts
hash[:foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar]



puts
puts "It took #{finish_time - start_time} seconds to run. #{(n /
(finish_time - start_time)).to_i} iterations per second."





C:\rails\depot>ruby symbol_vs_string.rb
10000000

It took 30.703 seconds to run. 325701 iterations per second.

C:\rails\depot>ruby symbol_vs_string2.rb
10000000

It took 11.984 seconds to run. 834445 iterations per second.

C:\rails\depot>ruby symbol_vs_string2.rb

It took 11.922 seconds to run. 838785 iterations per second.

C:\rails\depot>ruby symbol_vs_string.rb
10000000

It took 30.391 seconds to run. 329044 iterations per second.
 
J

John Joyce

Ali said:
Hey, I've started with Ruby two days ago, and I have some questions.

2- Why does a block has to be on the same line when passing argument?
Like in the previous example: kitty_toys.sort_by { |toy| toy
[:fabric] }.
If I tried to move the block down, it won't work. Also, if someone
could
explain how does the argument get passed to the block. I mean,
based on
what?
Welcome to ruby. First to start the question about Symbols. Well, they
are used in hashes a lot, you could very well do { 'shape' => 'sock' }
and it works the same, but just to be consistent you use the object
as a
symbol and it's value as what ever else. There is a lot more to that,
and i'm sure someone else will reply to tell you that.
2. A block doesn't have to be on the same line.
kitty_toys.sort_by do |toy|
toy[:fabric]
end

notice it's on 3 lines, but with this small of a block it looks ugly.

The argument gets passed to the block by means of the "slide" or the
pipes. Not sure if that was the answer you were looking for, but there
you go.

To give further detail a block has two possible delimiter pairs { }
or do end
As far as the interpreter is concerned they're same.
Two things to remember:
1. Single or multi-line blocks all have to begin with the delimiter
on the same line as the method the block belongs to.
an_object.a_method {
is the same as
an_object.a_method do

The ending } or end can be on any following line.

2. By convention (but not enforced by the interpreter) { } is used
for single line blocks (i.e. Ruby one-liners)
and do end is used for multi-line blocks.

Ruby is nice to you by often making parentheses optional (except
where things get fuzzy and difficult to guess easily)
and semicolon statement endings optional (unless you want to squeeze
some statements together on a single line.
 
7

7stud --

Hi,

Ali said:
Hey, I've started with Ruby two days ago, and I have some questions.

1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won’t be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

kitty_toys =
[:shape => 'sock', :fabric => 'cashmere'] +
[:shape => 'mouse', :fabric => 'calico'] +
[:shape => 'eggroll', :fabric => 'chenille']
kitty_toys.sort_by { |toy| toy[:fabric] }

Why is he using symbols? I just couldn't understand ;(.

It might save memory and make the program run faster.

I'm also new to Ruby, so I'll post my understanding of symbols so
far--at the very least it should provide the experts with some easy
weekend target practice. If you search on google, you'll find that
explaining symbols has been hotly debated in the past, so I am under no
illusion that this is the correct or only interpretation.
1- What's the use of Symbols? I've read that symbols are (Symbols are
lightweight strings. Usually, symbols are used in situations where you
need a string but you won’t be printing it to the screen.), however I
cannot understand how to use them, and so I tried to read some examples
and I got this:

kitty_toys =
[:shape => 'sock', :fabric => 'cashmere'] +
[:shape => 'mouse', :fabric => 'calico'] +
[:shape => 'eggroll', :fabric => 'chenille']
kitty_toys.sort_by { |toy| toy[:fabric] }

Why is he using symbols? I just couldn't understand ;(.

In java, if you write:

String s1 = "hello world";
String s2 = "hello";
String s3 = "world";
s2 += s3;

if(s1 == s2)
{
System.out.println("yes");
}
else
{
System.out.println("no");
}

the output will be 'no'. Why? Because in java, the == operator tests
whether two objects are the same object--not whether their values are
identical. However, if you write this:

String s1 = "hello";
String s2 = "hello";

if(s1 == s2) //checks whether s1 and s2 refer to the same string
object
{
System.out.println("yes");
}

the output will be 'yes'. Java does not create a second string object
when you assign a string literal that already exists in memory to
another String variable. Instead, both String variables will refer to
the same String object. That saves memory and can speed up execution.

On the other hand, Ruby creates new string objects for every string
literal that you assign to a variable:

s1 = "hello"
s2 = "hello"

puts s1.object_id
puts s2.object_id

--output:--
76810
76800

Note that in ruby you have to look at the object id's to determine
whether two objects are the same, because in ruby the == operator
compares the values of two string objects--not the string objects
themselves. That's different than the way Java's == operator works.
The == operator in ruby is equivalent to the equals() method in java.

Since ruby does the opposite with duplicate strings as Java, the
opposite conclusion might be true: ruby's string handling hogs memory
and slows down execution.

Enter symbols:

s1 = :hello
s2 = :hello
s3 = :hello

puts s1.object_id
puts s2.object_id
puts s3.object_id

--output:--
2545934
2545934
2545934

puts s1.to_s
puts s2.to_s
puts s3.to_s

--output:--
hello
hello
hello

I think this is what it looks like:


"hello"
^
|
|
symbol_obj
id:2545934
^ ^ ^
| | |
s1 s2 s3


I found the description here helpful:

http://moonbase.rydia.net/mental/blog/programming/ruby-symbols-explained

-----
For every unique string value, there is a unique symbol object.

Testing two symbol values for equality (or non-equality) is faster than
testing two string values for equality, because Ruby only needs to do a
single test[ruby compares the symbol id's]. Checking two strings for
equality is more complicated; every individual character in the string
has to be checked until a difference is found.

As noted above, each unique string value has an associated symbol. This
means that checking whether two symbols have the same string value or
not is as simple as checking whether they are the same object or not.

One comparison:

:Worcestershire == :Worcestershire
Easy peasy. They’re the same object, so they’re equal.

Sixteen comparisons:

"Worcestershire" == "Worcestershire"

With strings, Ruby has to dig into the objects to check their contents.
Since in this case they’re different string objects with the same
length, it’s got to check all fourteen characters in each string to make
sure that they really are equal.
-----

Finally, remember that symbols are not string objects, so string methods
do not work on symbols:

s1 = "hello"
s1.upcase!
puts s1

--output:--
HELLO

s2 = :hello
s2.upcase!
puts s2

--output:--
undefined method `upcase!' for :hello:Symbol (NoMethodError)

However, you can always get the string that a symbol refers to and call
string functions on the string:

s2 = :hello
s3 = s2.to_s
s3.upcase!

puts s3

--output:--
HELLO

For a final twist, there is method called send(), which is a method of
Object. send() takes an argument that is a symbol. The symbol argument
should refer to a string, and that string should be the name of a
method. send() then executes the method:

def show(x)
puts x
end

send:)show, 10)

The method name 'send' comports with the ruby terminology that you are
sending messages to objects when you write something like:

my_string.upcase!

In ruby, that code is described as sending the upcase! message to the
the object my_string, which causes the upcase! method in the string
class to execute.

All languages I've studied have a way to call a method when you have the
method name as a string, e.g. the user entered a method name and you
need to call that method. In Java, you do that with reflection and a
few contortions. Because a symbol refers to a string, it's not much of
a stretch to think that you should be able to execute a function when
you have a symbol: the symbol can be used to get the string. In fact,
it appears that send() will also accept a string as an argument,
although that isn't documented:

def show(x)
puts x
end

send("show", 10)


Knowing when to use symbols to optimize your code will hopefully come
with experience. See these articles as well,

The Ruby_Newbie Guide to Symbols:
http://www.troubleshooters.com/codecorn/ruby/symbols.htm

13 ways to look at a Ruby symbol:
http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

2- Why does a block has to be on the same line when passing argument?
Like in the previous example: kitty_toys.sort_by { |toy| toy[:fabric] }.
If I tried to move the block down, it won't work.

The file that contains your program is just a text file. ruby has to
interpret the text in the file and make sense of it. In order for ruby
to make sense of the text, you have to follow certain syntax rules.
Apparently, a syntax rule in ruby is that a brace enclosed block has to
be on the same line as the method call so that ruby knows it is
associated with the method call. Of course, you can always use the "do"
form for lengthy blocks:


kitty_toys.sort_by do |toy|
toy[:fabric]

#200 lines of other code here

end
Also, if someone could
explain how does the argument get passed to the block. I mean, based on
what?

You can think of a block as a second method. The first method specified
before the block, e.g. sort_by in your example, calls the second
method(the block). However, only a method that is written to call a
second method can have a block. Methods that call a second method(the
block) need to be defined with a yield statement(or the equivalent).
Here is an example of a method I made up that can call another method
that is a block:

def func
arr = [3, 6, 9, 12]
count = 0

while count <= 3
yield arr[count]
count += 1
end

end

In fact, calling that method without a block will produce an error. A
yield statement is similar to a normal method call: the yield statement
sends the value specified after 'yield' to the block, e.g arr[count] in
func. The yielded value then gets assigned to the block parameter
variable. Subsequently, the block can do whatever it wants with the
value. Execution in func halts at the point of the yield statement
until the block finishes executing, at which point execution continues
in the func. Since func has a repeating while loop, the block is called
repeatedly with different values. Here is an example of calling func
with a block:


def func
arr = [3, 6, 9, 12]
count = 0

while count <= 3
yield arr[count]
count += 1
end

end


func {|i| puts i * 2}

--output:--
6
12
18
24



Here is another example:

def func
yield
yield
yield
end


func {puts "hello"}

Since func doesn't yield any values(there are no values specified after
the word 'yield'), the block doesn't need to be defined with a parameter
variable to catch the values. In fact, you can't define a block with a
parameter variable if no values are going to be sent to the
block--you'll get an error that says the block was expecting one
argument and got zero.

If it helps you to understand, you can also do the equivalent(nearly)
using a Proc object. A Proc object represents a method. Proc objects
allow you to explicitly send methods as arguments to other methods,
rather than doing so implicitly with a block:

def func(proc_obj)
arr = [3, 6, 9, 12]
count = 0

while count <= 3
proc_obj.call(arr[count])
count += 1
end
end

p = Proc.new {|i| puts i * 2}
func(p)

--output:--
6
12
18
24

3- How does a Ruby file compile? Like in Java, your code gets compiled
into bytecode, and then delivered to the JVM. Are there any similarities
in Ruby?

Uhmmm...I don't think that's quite the way it works in java. In java,
you compile your program into byte code *before* executing it. Byte
code consists of instructions for the java jvm. After compiling, you
execute your program, which sends the byte code instructions to your
platform specific jvm installed on your computer. The jvm then converts
the byte code into machine instructions that your specific os can
understand.

I'm not quite sure about the nitty gritty details in Ruby, but when you
execute a Ruby program, full compilation is done before execution can
begin. From what I've read, Ruby is much slower than Java, and it's
also slower than just about any other comparable language, e.g Perl,
Python, PHP, etc. It's significantly slower than Java because it has to
do a full compilation before executing the code, and Ruby is a
dynamically typed language(i.e. variables don't have types and can be
assigned any type). Dynamically typed languages cannot be optimized as
much as statically typed languages like Java.

I'm currently reading Programming Ruby 2nd Edition,

Me too. :)
 
7

7stud --

7stud said:
The symbol argument
should refer to a string, and that string should be the name of a
method. send() then executes the method:

After editing that sentence a couple of times, I completely changed the
meaning into something quite confusing. A symbol *always* refers to a
string. That should read:

The symbol argument should refer to a string that is the name of a
method. To create that symbol you take the method name and put a ":" in
front of it.

I hope that helps.
 
7

7stud --

7stud said:
In java, if you write:

String s1 = "hello world";
String s2 = "hello";
String s3 = "world";
s2 += s3;

if(s1 == s2)
{
System.out.println("yes");
}
else
{
System.out.println("no");
}

the output will be 'no'. Why?

lol, Ok, let's try a fair comparison:

String s1 = "hello world";
String s2 = "hello ";
String s3 = "world";
s2 += s3;

if(s1 == s2)
{
System.out.println("yes");
}
else
{
System.out.println("no");
}

Still, the output is "no".
 
D

dblack

Hi --

After editing that sentence a couple of times, I completely changed the
meaning into something quite confusing. A symbol *always* refers to a
string. That should read:

I'm not sure I'd put it that way. A symbol, like a string, can always
be represented by characters, but I don't think a symbol actually
refers to a string, any more than the string refers to the symbol. But
I may be misunderstanding what you mean.
The symbol argument should refer to a string that is the name of a
method. To create that symbol you take the method name and put a ":" in
front of it.

send takes a string too:

obj.send("some_method")

so if you've got the name of a method as a string in a variable, you
can just use that directly.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
C

Chad Perrin

As I understand it, there's generally less processing time involved in
resolving symbols than strings, but if you have a very long-running
program that performs some very similar actions involving symbols over
and over again you might end up consuming a lot of RAM because symbols
never really go away throughout the run of the program. There may be a
way to get the interpreter to clear the hash table that stores symbols,
but I don't really know what it is off the top of my head. If there's
such a thing, it probably involves scoping rules in Ruby, and maybe a
little luck.

To give further detail a block has two possible delimiter pairs { }
or do end
As far as the interpreter is concerned they're same.

Again, if I recall correctly, that's not strictly true -- but the only
difference as far as I'm aware is precedence. I seem to recall that
braces have a higher precedence than do...end. This should only really
come into play when you are doing some fancy stuff on the line where the
do or open-brace appears, before the beginning of the block, I think.

Keep in mind I'm not Matz, Why, or the Pragmatic Programmer guys. I'm
not what I'd call a Ruby "expert". I may have inadvertently
misrepresented some feature of the language. Despite a growing
preference for Ruby in most cases, I still have more experience with
Perl, and know that language better. Take what I say with a grain of
"maybe he doesn't know what he's talking about" when I start talking
about the quirks and gotchas of working with Ruby.
 
G

Gaspard Bucher

I just did a stupid test :

[
["string last char", 'jdhduiehspdshfgie494hfps9e4',
'jdhduiehspdshfgie494hfps9e2'],
["symbol last char", :'jdhduiehspdshfgie494hfps9e4',
:'jdhduiehspdshfgie494hfps9e2'],
["string first char", 'jdhduiehspdshfgie494hfps9e4',
'jdhduiehspdshfgie494hfps9e2'],
["symbol first char", :'jdhduiehspdshfgie494hfps9e4',
:'kdhduiehspdshfgie494hfps9e4'],
["string same ", 'jdhduiehspdshfgie494hfps9e4',
'jdhduiehspdshfgie494hfps9e4'],
["symbol same ", :'jdhduiehspdshfgie494hfps9e4',
:'jdhduiehspdshfgie494hfps9e4'],
].each do |m,a,b|
t = Time.now
x = 0
y = 0
1_000_000.times do
if a == b
x += 1
else
y += 1
end
end
puts "#{m}: #{(Time.now - t).to_f} (#{x},#{y})"
end

Here are the results. You gain 10% speed by using symbols in such a situation.
string last char: 2.782326 (0,1000000)
symbol last char: 2.42484 (0,1000000)
string first char: 2.650707 (0,1000000)
symbol first char: 2.470714 (0,1000000)
string same : 2.737924 (1000000,0)
symbol same : 2.401426 (1000000,0)
 
C

Chad Perrin

Here are the results. You gain 10% speed by using symbols in such a situation.

In short, then, it looks like I was right: all else being equal, symbols
are a little faster than strings, but don't (generally) leave the hash
table that stores them so too many symbols may undesirably increase
memory usage.
 
7

7stud --

unknown said:
I'm not sure I'd put it that way. A symbol, like a string, can always
be represented by characters, but I don't think a symbol actually
refers to a string, any more than the string refers to the symbol. But
I may be misunderstanding what you mean.

Then where is the error in this diagram:

"hello"
^
|
|
symbol_obj
id:2545934
^ ^ ^
| | |
s1 s2 s3
 
7

7stud --

7stud said:
Then where is the error in this diagram:

"hello"
^
|
|
symbol_obj
id:2545934
^ ^ ^
| | |
s1 s2 s3

Oops. I should have included these statements:

s1 = :hello
s2 = :hello
s3 = :hello
 
D

David A. Black

Hi --

Then where is the error in this diagram:


s1 = :hello
s2 = :hello
s3 = :hello

"hello"
^
|
|
symbol_obj
id:2545934
^ ^ ^
| | |
s1 s2 s3

If the top arrow means that the symbol :hello contains a reference to
a string "hello", in the same way that s1-3 are bound to references to
:hello, then I would say that's the error. A symbol can be converted
to a string, such that the string represents the same sequence of
characters as the symbol; but the symbol is not a reference to a
string object.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

David A. Black

7

7stud --

David said:
Hi --



If the top arrow means that the symbol :hello contains a reference to
a string "hello", in the same way that s1-3 are bound to references to
:hello, then I would say that's the error.

Yes, the arrows stand for references.
A symbol can be converted
to a string, such that the string represents the same sequence of
characters as the symbol; but the symbol is not a reference to a
string object.

Interesting and puzzling. The symbol object has no member variable that
is a pointer to a string? As a consequence, the string object might
never exist in memory?
 
R

Rick DeNatale

Yes, the arrows stand for references.


Interesting and puzzling. The symbol object has no member variable that
is a pointer to a string? As a consequence, the string object might
never exist in memory?

The exact situation is implementation dependent and the implementation
of symbols in Ruby has changed over time.

In general the interpreter/vm needs to be able to obtain the string
representation of a symbol, and also obtain/create a symbol from an
arbitrary string. There are several ways to achieve these
requirements.

I guess that it's literally true that in a minimal program like

:symbol

A string object "Symbol" might never exist in memory, but SOME
representation of that sequence of characters almost certainly does.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,001
Messages
2,570,254
Members
46,850
Latest member
VMRKlaus8

Latest Threads

Top