Chaining methods in Ruby, and injecting a block into the chain - ruby

Consider the following Ruby expression:
y=x.a.b.c.d.e.f
Of course, x is an object and a to f are methods defined for a class which matches the return value of the previous method in the chain. Now say that I want to replace the invocation of method c by a custom block, i.e. I would like to achieve the effect of
temp=x.a.b
temp1=.... (calculate something based on the value of temp)
y=temp1.d.e.f
but with using method chaining.
It is of course trivial to define a suitable method to achieve this:
class Object
def pass
yield(self)
end
end
which would allow me to write something like
y=x.a.b.pass {|the_b| .....}.d.e.f
Now to my question:
Given that Ruby already has a method for a similar problem (Object#tap), I wonder why it does not have a method similar to the Object#pass which I just explained. I suspect, that either
(a) Ruby already offers a feature like this, and I'm just to stupid to find it, or
(b) What I want to achieve would be considered bad programming style (but then, why?)
Is (a) or (b) correct, or did I miss something here?

(a) Yes. Ruby already has that. It is called yield_self.
(b) No. It is not a bad style.

Related

Is there a way to use a dynamic function name in Elixir from string interpolation like in Ruby?

I want to be able to construct a function call from a string in elixir. Is this possible? The equivalent ruby method call would be:
"uppercase".send("u#{:pcase}")
Although the answer by #fhdhsni is perfectly correct, I’d add some nitpicking clarification.
The exact equivalent of Kernel#send from ruby in elixir is impossible, because Kernel#send allows to call private methods on the receiver. In elixir, private functions do not ever exist in the compiled code.
If you meant Kernel#public_send, it might be achieved with Kernel.apply/3, as mentioned by #fhdhsni. The only correction is since the atom table is not garbage collected, and one surely wants to call an indeed existing function, it should be done with String.to_existing_atom/1.
apply(
String,
String.to_existing_atom("u#{:pcase}"),
["uppercase"]
)
Also, one might use macros during the compilation stage to generate respective clauses when the list of functions to call is predictable (when it’s not, the code already smells.)
defmodule Helper do
Enum.each(~w|upcase|a, fn fname ->
def unquote(fname)(param),
do: String.unquote(fname)(param)
# or
# defdelegate unquote(fname)(param), to: String
end)
end
Helper.upcase("uppercase")
#⇒ "UPPERCASE"
In Elixir module and function names are atoms. You can use apply to call them dynamically.
apply(String, String.to_atom("u#{:pcase}"), ["uppercase"]) # "UPPERCASE"
Depending on your use case it might not be a good idea to create atoms dynamically (since the atom table is not garbage collected).

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.

Ruby (try_if)_respond_to. Does it exist?

I'm trying to find a shorthand method for doing the following:
if row.respond_to?(:to_varbind_list)
result << row.to_varbind_list.to_hash
else
result << row.to_hash
end
And achieve it with something like this
row.try_if_respond_to(:to_varbind_list).to_hash
Basically row tries to call a method on itself, if that method doesn't exist then just return itself.
Maybe by overriding the Object class or something similar. I'm assuming it's pretty simple how to create my own.
Does Ruby already provide something that does this?
No, ruby does not provide something like this. Also, the Rails try method does not do what you want, since it returns either nil or the method result, but never the original object.
I would say such a method would lead to ambivalent and rather unreadable code since the object that gets the message would be ambivalent. You can surely roll your own, but I find your original code is to the point. If you want to make it shorter in terms of code lines, use ternary operators:
result << (row.respond_to?(:to_varbind_list) ? row.to_varbind_list : row).to_hash

rb_str_modify() equivalent in the Ruby language

I was trying to add a method to the String class. This method should mutate the current string (of course it would be possible to write a not mutating version but I'd prefer the mutating one). I had no idea how to do this and after some googling I found the method rb_str_modify which makes a given string mutable. That's exactly what I need but I couldn't find an equivalent in the Ruby language. Did I miss something or is there really no possibility in the language itself?
Reopening Classes
All classes in Ruby are open for extension so you can simply do this ...
Class String
def my_new_method(args)
# Some sort of modification to self
self.replace "SOME CALCULATED VALUE"
end
end
... somewhere in your code. I've modified string a few times in different applications - usually I just put the modifications into one particular module, making it easy to reuse them or remove them as required.
Modifying individual objects
Modifying a class in its entirety is dangerous as it's very difficult to identify all of the consequences - I once broke Merb by modifying a method in the String class. It's much safer to modify particular objects. This is easy in Ruby - you use the extend keyword. You define a module, add your function and then modify the target object. This example ...
module Humor
def tickle
"hee, hee!"
end
end
a = "Grouchy"
a.extend Humor
a.tickle » "hee, hee!"
is taken from the Pickaxe book
Chris

Ruby method, Proc, and block confusion

I have a couple questions about Ruby's methods, procedures, and blocks that strike me as rather odd. They're not so much about syntax or function as the logic behind the decisions made.
Question 1:
Why is it that blocks can be passed to methods (e.g. each) but they cannot be assigned to a variable?
I know you can pass them around in procedures, i.e. p = Proc.new {...} (accessed with &p), but it doesn't make much sense to make the programmer go through these means.
Question 2:
Why is there a differentiation between methods and procedures?
For instance, I can accomplish the task of defining a function and calling that function in the following two ways:
def square(x)
x**2
end
square(3)
=> 9
or
square = lambda {|x| x**2}
square.call(3)
=> 9
Why the differentiation? In Python for example both defining a function in the standard way and by square = lambda x: x**2 accomplish the same task of creating the function and assigning it to square.
Question 1: Blocks are not objects, they are syntactic structures; this is why they cannot be assigned to a variable. This is a privilege reserved for objects.
Question 2: Methods are not objects, so they cannot receive messages. Inversely, procs and lambdas are objects, so they cannot be invoked like methods, but must receive a message that tells them to return a value on the basis of the parameters passed with the message.
Procs and Lambdas are objects, so they can receive the call message and be assigned to names. To summarize, it is being an object that makes procs and lambdas behave in ways you find odd. Methods and blocks are not objects and don't share that behavior.
To some extent at least, methods are objects:
class ABC
def some_method
end
end
ABC.instance_method(:some_method) #=> #<UnboundMethod: ABC#some_method>
Further to that, there is a built-in class: Method, as documented here.
See also this: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
Haphazardly <bseg>, it does rather seem to bear out the everything-is-an-object thing. In this particular case, it just appears to take a little more digging to see.
(I really must make an effort to understand this better: I'm starting to think it's fundamental to getting a deeper understanding.)
Methods are methods — that is, they're actions that an object can take in response to messages. They are not functions.
Blocks are closures — they're functions that close over the enclosing scope. They don't conceptually "belong to" a given object.
In some languages, methods are merely functions that are members of an object, but Ruby does not view them this way. Separating a method from its owning object is more akin to surgery than simple assignment. Ruby takes its object-orientation model from Smalltalk, the granddaddy of modern OO.

Resources