Ruby, Source Code of Splat? - ruby

Someone asked about the splat operator yesterday, and I wanted to see the source code... would that be written in C or in Ruby? Where would it be found?

Some quick Google searching turned up that it's implemented in eval.c. You can find references to "splat" in a few places in the file, but I'm not familiar enough with the inner workings of Ruby to make any sense of it.

The splat operator is poorly documented in the core Ruby documentation as of Ruby 2.4. It's a core feature of the language, though, and the source code for the splat operator can be found in vm_eval.c under rb_yield_splat(VALUE values).
The unit test for rb_yield_splat makes it clearer what is happening:
it "yields with passed array's contents" do
ret = nil
#s.rb_yield_splat([1, 2]) { |x, y| ret = x + y }
ret.should == 3
end

Related

Ruby: Reference the currently executing block

Is there any way to reference the currently executing block in Ruby for one-off recursion? For example, to perform a "deep" merge on Hashes:
hash1.merge(hash2) do |k,o,v|
(o.is_a?(Hash) && v.is_a?(Hash)) ? o.merge(v, &CURRENT_BLOCK) : v
end
I know that I could just define the block externally and reference it, I am just wondering whether it is possible to do it in-place.
I think you're looking for some sort of Y combinator in Ruby. I don't believe this is possible to do in Ruby with ordinary blocks, but you can do something similar with lambdas:
lambda { |x| p x += 1; redo }[0]
Alternatively, you could implement a Y combinator generator using methods or lambdas, as shown on this RosettaCode page.

When, if ever, to use the Ruby keyword "for"

I personally like to iterate using the for keyword in Ruby since it reads very clean, from my eye. I generally assume that for may be an alias to Enumerable#each, but I do not know whether is is correct. In the most basic example:
for i in (1..10)
puts i
end
behaves the same as
(1..10).each do |i|
puts i
end
just without creating a new variable scope. Moreover, ruby-doc says
The for loop is rarely used in modern ruby programs.
which makes me feel there is a specific, technical reason against the usage. Does it matter that there's no new variable scope? In what way?
behaves the same as
This is incorrect. for is built on top of each, but it is semantically distinct:
array = %w(a b c d)
array.each { |character| }
defined? character # nil
for character in array; end
defined? character # "local-variable"
The for keyword doesn't introduce a new scope. Any variables introduced inside the block remain visible outside of it; as if it was written inline.
You should take this fact into account when you decide which form to use.

trying to find documentation on ruby's trailing if usage

I'm working in the RSpec book (page 121) and am being presented with a bit of code that is apparently self evident and clear. It's not self evident for me, and I'm hoping someone can help me understand.
I'm coming to ruby from c# so please use small words :)
Here's the original code
def total_match_count
count = 0
secret = #secret.split('')
#guess.split('').map do |n|
if secret.include?(n)
secret.delete_at(secret.index(n))
count += 1
end
end
count
end
here's the refactor
def total_match_count
secret = #secret.split('')
#guess.split('').inject(0) do |count, n|
count + (delete_first(secret, n) ? 1 : 0)
end
end
def delete_first(code, n)
code.delete_at(code.index(n)) if code.index(n)
end
Again, this is supposed to be so obvious as to need no comment.
I'm not understanding the trailing "if code.index(n)" bit and I can't find any documentation on using the keywords "ruby trailing if"
Obviously I'm missing something basic.
Ruby Post-Conditions as Syntactic Sugar
In Ruby, almost everything is an expression, and keywords like if and unless can be used as expression modifiers that follow an expression. Some languages refer to these as post-conditions, but the general idea is that:
if 1 == 1
puts true
end
is intended to be equivalent to:
puts true if 1 == 1
The post-condition can sometimes make the intent of the code clearer, or create a more natural flow. The parser differentiates between the :if and :if_mod tokens that internally represent the "normal" if-statement and its matching post-condition, but from a programmer's perspective the post-conditions are (or should be) largely syntactic sugar to make certain expressions easier or cleaner to read and write.
You don't ever need post-conditions in Ruby, but you will often find them in idiomatic Ruby code. If you don't grok them, or don't find that they improve the readability of your code, then feel free to ignore them until and unless they seem useful to you.
This:
code.delete_at(code.index(n)) if code.index(n)
is the same as this:
if code.index(n)
code.delete_at(code.index(n))
end
Some people think the one-liner is easier to read. It's a matter of style--when lines become long, the "trailing if" can be a gotcha, as you might not think to read to the end of the line to realize it has a condition attached. Use judiciously.
Ruby also has unless, which can be used in the "trailing" form too:
do_stuff unless no_on_second_thought

Defining a new logical operator in Ruby

Very much an idle day-dream this but is it possible with some neat meta-programming trick to define a new logical operator in Ruby? I'd like to define a but operator.
For example, if I want to do something if x but not y is true I have to write something like:
if x and not y
But I would like to write
if x but not y
It should work exactly the same as and but would be down to the programmer to use sensibly to increase the legibility of code.
Without editing the Ruby parser and sources and compiling a new version of Ruby, you can't. If you want, you can use this ugly syntax:
class Object
def but(other)
self and other
end
end
x.but (not y)
Note that you can't remove the parentheses or the space in this snippet. It will also shadow the functionality of the code to someone else reading your code. Don't do it.
If you really want to do this, try editing parse.y and recompiling Ruby. That's where Ruby's syntax is defined.
As others have already pointed out, you cannot define your own operators in Ruby. The set of operators is predefined and fixed. All you can do is influence the semantics of some of the existing operators (namely the ones that get translated into message sends) by responding to the appropriate messages.
But of course, you can implement a but method quite easily:
class Object
def but
self && yield
end
end
Object.new.but { not true }

Does using curly braces go against the "Ruby way"?

I've been using Ruby for about two weeks, and I've not been programming for too terribly long, but I'm coming at the language from a C-style background (C++, C#, etc). Anyway - a good friend and mentor of mine was looking at some Ruby that I'd written the other day, and he told me that he'd smack me if he caught me using curly braces in Ruby again.
Well, I just found out about Builder yesterday, via this About.com article, and the example that they have posted uses curly braces. Is there a different way to do this, or do you have to use curly braces with Builder?
This may seem like a minor point, but I'm new to Ruby, and I don't want to let myself develop any bad habits. What do you guys think?
While some people go with "braces for one-liners, do-end for multi-liners", I personally find the following rule the most logical:
use do-end when your block has side-effects (typically, with each and related methods) and
use braces when your block is without side-effects (map, inject and alike)
This logic goes well with method chaining issue that Matt wrote about.
One benefit of this approach is that it is going to make you think about side-effects every time you write a block, and they are very important, although sometimes overlooked by coders with no functional programming background.
Another way to put it, without involving side-effects terminology would be:
use do-end for blocks that perform
use { and } for blocks that return
Here are couple of articles with more info:
http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc
http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace
Idiomatic ruby is
method_name {|param| param.do_something} # squigglies for one liners
# do/end for multi-line
method_name do |param|
param.do_something
end
One reason for this is for chaining, foo.map {|f| f.num}.reduce(0) {|memo, i| memo + i} looks nicer then hanging a method call off of an end like
foo.map do |f|
f.num
end.reduce(0) do |memo, i|
memo + i
end
There is just something strange about calling a method off of end, even though syntactically the two are equivalent.
The usual convention is { ... } blocks for one-liners and do ... end for multi-liners. I generally follow this convention but should I ever be king I think I would use do .. end more often.
An occasional issue with {} is that {} binds more tightly than do end so the only way to write a poetry-mode block for a method that also has parameters is to use do end, otherwise the block will be part of the parameter and will not be not passed directly to the method.
def f x
yield x
end
f 123 do |n| p n end # works
f 123 { |n| p n } # does not work
f(123) { |n| p n } # works, of course
Of course, if you wanted to attach a block to a parameter in poetry mode, then you win with {} followed by do end.
def g ; p ['g', yield] end
def f x; p ['f', yield] end
f g { 2 } do 3 end
["g", 2]
["f", 3]
Finally, and contrary to some of the advice you have received here, a ; is not needed before end.
"The Ruby way" doesn't advocate any specific style. If they didn't want you to have the option to use curly braces, it wouldn't be in the language. That said, conform to your team's coding style (if you're working with a team).
Most Ruby code I've seen uses end in place of curly braces, but I don't use Ruby so I can't say for sure that this is the preferred style. Ruby has more than one way of doing things -- you can use whichever way pleases you (within reason).

Resources