What is this syntax is called? - ruby

What is the _char variable attached to the end of the .each method called?
variable.to_s.each_char do |char|
I am new to Ruby and I saw this for the first time and I don't know what its called (or what it does or how it works). Can someone please point me in the right direction?

It is a different method named each_char, not a special syntax.

In current versions of Ruby there is no String#each method. String#each_char is for enumerating characters of a string (though they are themselves strings). String#chars is the same as String#each_char.

Related

ruby equal sign in method call

Hi there fellow rubyists!
I've just came across a weird syntax in method call:
Foo.bar 'first_arg', more1='other', more2='another'
but when I test it out 'other' is always assigned to the second argument, never mind the word before equal sign. What is this? Why is this in ruby? I'm familiar with ruby 2.0 key-arguments, but this seems to have nothing to do with that.
This has nothing to do with key arguments.
This is just a shortcut of assigning and passing variables to the method.
Foo.bar 'first_arg', more1='other', more2='another'
Can be rewritten as
more1='other'
more2='another'
Foo.bar('first_arg', more1, more2)
'other' is assigned to the variable more1 and the resulting expression is always 'other' so that value is passed to the bar method. So why do that? Well, probably more1 and more2 are used after that call. I don't like it but that's it.

what is a variable/object/thing starting with a # in ruby

I am new to Ruby, so go easy :).
Anyway, I am trying to work out some stuff in the chef-provisioning-aws gem. One thing in particular is that there is an object called:
new_resource.driver.ec2_client
When I do an inspect on that object it returns exactly this:
#<Aws::EC2::Client>
So, my question is: what is this? What sort of "thing" in Ruby starts with a pound sign (hash) and has <...> in it?
Much appreciated.
The output of Ruby's inspect method is roughly like this unless you override it:
"#<#{self.class}:0x#{self.object_id.to_s(16)}"
So in other words: "#<ClassName:0xobject_id in hex>".
class Foo ; end
Foo.new.inspect
#=> "#<Foo:0x007ffe0eeea520>"
It seems that for Aws::EC2::Client it was overriden and does not include the object id.
It's the default implementation of the inspect method (although then the object ID should be included). It may be useful in some situations to implement your own method, so you can get an instant overview of what you want to know about this object. The # is just a random character and has no further meaning here.

What is the difference between these two method parameter definitions?

I'm starting to learn Ruby. I read that arguments where passed by reference to a method,
however I don't understand the difference between these two methods.
def print(text)
puts text
end
and
def print(*text)
puts text
end
Using a * means that we are passing a pointer like in C?
The *text is what's called the splat operator in Ruby. It basically means if you pass multiple arguments to the second print they will get slurped into the single text variable.
See The Splat Operator in Ruby
The * before a parameter name in a Ruby parameter list is used for variable length arguments, so they are similar to the ... in C/C++ for varargs.
def vlaFunc(*args)
puts args
end
vlaFunc(1,2,3)
# output is [1,2,3]
There are no pointers in Ruby, * in this context is generally referred to as the "splat" operator:
http://4loc.wordpress.com/2009/01/16/the-splat-operator-in-ruby/
http://theplana.wordpress.com/2007/03/03/ruby-idioms-the-splat-operator/
In this case the method can take an arbitrary number of arguments, which will be available in the array text.
First you have two nice methods started there. But I would say try to avoid using puts inside them. You don't need it anyway. A method will always yield the last statement evaluated. something = text would get the job done. And I don't need to answer now about the differences.
Your first two replies are very good there. But you may want to try something like this
j = *[] #=> nil in 1.8 but [] in 1.9
It's been the new kid on the block for a time now. Guess what it does?

How can I splattify an anonymous object so I can use &method on it?

I'm wanting to use the &method(:method_name) idiom when there's more than one object required by method_name. Can I do this under Ruby 1.9?
For example, if I've got
def move_file(old_filename, new_filename)
STDERR.puts "Moving #{old_filename.inspect} to #{new_filename.inspect}"
# Implementation for careful moving goes here
end
old_filenames = ["foo.txt", "bar.txt", "hoge.ja.txt"]
new_filenames = ["foo_20110915.txt", "bar_20110915.txt", "hoge_20110915.ja.txt"]
the code
old_filenames.zip(new_filenames).each(&method(:move_file))
works under Ruby 1.8, but not under Ruby 1.9. Under Ruby 1.9, it's trying to do move_file(["foo.txt", "foo_20110915.txt"]) instead of move_file("foo.txt", "foo_20110915.txt").
How do I splattify it so it has the correct arity?
Workarounds I'm aware of:
Replace def move_file(old_filename, new_filename) with def move_file(*arguments)
Replace each(&method(:move_file)) with
each{|old_filename, new_filename| move_file(old_filename, new_filename)}
Instead
each{|old_filename, new_filename| move_file(old_filename, new_filename)}
you should be able to do
each{|pair| move_file(*pair)}
But I don't know how you'd pull off blockless variant (I needed it couple of times as well). I guess &-shorthand was made to make the syntax simpler, and is not meant to be clogged much (whether it will be passed an array as an array, or splatted, for example). :)
How do I splattify it so it has the correct arity?
I don't think there is a way to do this while being compatible to both Ruby versions. What you could do is wrap it into a lambda
move_from_to = Proc.new {|*both| move_files(*both) }
The thing is - block and proc arity is something that got addressed in Ruby 1.9 so there might be a difference in behavior there. Also see prc.lambda? here http://www.ruby-doc.org/core/classes/Proc.html for info on what it does to the arity.
This question is also related to what you want to do (the solution there is to resplat and unsplat manually): Inconsistency of arity between Hash.each and lambdas

ruby 1.9: how do I get a byte-index-based slice of a String?

I'm working with UTF-8 strings. I need to get a slice using byte-based indexes, not char-based.
I found references on the web to String#subseq, which is supposed to be like String#[], but for bytes. Alas, it seems not to have made it to 1.9.1.
Now, why would I want to do that? There's a chance I'll end up with an invalid string should I slice in the middle of a multi-byte char. This sounds like a terrible idea.
Well, I'm working with StringScanner, and it turns out its internal pointers are byte-based. I accept other options here.
Here's what I'm working with right now, but it's rather verbose:
s.dup.force_encoding("ASCII-8BIT")[ix...pos].force_encoding("UTF-8")
Both ix and pos come from StringScanner, so are byte-based.
You can do this too: s.bytes.to_a[ix...pos].join(""), but that looks even more esoteric to me.
If you're calling the line several times, a nicer way to do it could be this:
class String
def byteslice(*args)
self.dup.force_encoding("ASCII-8BIT").slice(*args).force_encoding("UTF-8")
end
end
s.byteslice(ix...pos)
Doesn't String#bytes do what you want? It returns an enumerator to the bytes in a string (as numbers, since they might not be valid characters, as you pointed out)
str.bytes.to_a.slice(...)
Use this monkeypatch until String#byteslice() is added to Ruby 1.9.
class String
unless method_defined? :byteslice
##
# Does the same thing as String#slice but
# operates on bytes instead of characters.
#
def byteslice(*args)
unpack('C*').slice(*args).pack('C*')
end
end
end

Resources