Is there a ruby equivalent to the Scala Option? - ruby

How do I model an optional value in ruby? Scala has Option[], which is what I'm looking for in ruby.

There's no equivalent in the standard library. You have to define your own. See this article.

I'm not a Ruby expert, but I don't think there is an Option equivalent. As Ruby is object oriented, nothing stops you from writing your own implementation, but it won't be as useful as in a statically typed language, where the compiler forces you to do a proper check for the empty option, which is one of the main points for using this construct. Of course there are other advantages, like the possibility to chain Option values in several ways.

Have you checked out the Rumonade gem? It gives you an Option class modeled on scala.
require 'rumonade'
[nil, 1, 123].map { |v| Option(v) }
=> [None, #<Rumonade::Some:0x7f2589297768 #value=1>, #<Rumonade::Some:0x7f2589297740 #value=123>]
[nil, 1, 123].map { |v| Option(v).map { |n| n.to_s }.select { |s| s.size > 2 } }.flatten
=> ["123"]

There is an example of a Maybe class in nkpart's adt library under examples/common_adts.rb. There are also other example ADTs and the library makes it easier to define your own.

I have just pushed a gem called nil_be_gone that gives you an Optional that you can wrap objects with. It implements method_missing to check whether the value of the Optional is nil and if so simply return another Optional wrapped nil value, otherwise it calls the method on the object and wraps it again.
nil_be_gone implements bind as and_then which allows you to chain operations on Optional types, it's return methods which retrieves the value from Optional is value and the unit operation which wraps an object in the monad is defined by self.from_value.

I don't know Scala, so I can't assert that's your answer:
In ruby, when you call a method, you can define a default value for a param:
def foo(i_am_mandatory, i_am_optionnal = :banga)
puts i_am_optionnal
end
foo(:pouet, :plip)
=> :plip
foo(:pouet)
=> :banga
In that example, you can omit i_am_optionnal, which has a default value.
HTH.

Related

Omitting an argument for a method in a block

I wonder, is it possible to do something similar in Ruby to what I can do in Scala or other languages:
someCollection.foreach(x => println(x)) // a full version
someCollection.foreach(println) // a short version
In Ruby I can do:
some_array.each { |x| puts x }
So how can I do this?
some_array.each { puts }
UPDATE:
I'm not talking about puts in particular, it just picked it for example. There might be some_other_method which takes one parameter.
some_array.map { some_other_method }
some_array.map(some_other_method) # ???
def some_other_method a
# ... doing something with a
end
If you look up the rules for implicit η-expansion in the SLS (§6.26.5), it should be immediately obvious that it relies crucially on static type information and thus cannot possibly work in Ruby.
You can, however, explicitly obtain a Method object via reflection. Method objects respond to to_proc and like any object that responds to to_proc can thus be passed as if they were blocks using the unary prefix & operator:
some_array.each(&method(:puts))
Not quite like that, unfortunately. You can send a method name to be called on each object, e.g.:
some_array.each &:print_myself
Which is equivalent to:
some_array.each {|x| x.print_myself}
But I don't know of a clean (read: built-in) way to do what you're asking for. (Edit: #Jörg's answer does this, though it doesn't really save you any typing. There is no automatic partial function application in Ruby)

Advantages/disadvantages to using struct as a parameter while defining new API

The APIs that I am writing are for a Ruby class that inherits from ActiveRecord. I am trying to write static methods to avoid leaking the ActiveRecord instance. All the APIs now need tuple to uniquely identify a database row.
Is it a good idea to have APIs of the form:
API1(abc, def, ....)
API2(abc, def, ....)
and so on
or should I define a struct with fields to help with future changes?
Any other ideas are greatly welcome!
Using a struct would be strange in Ruby, a Hash would be normal:
def self.api1(options)
# Look at options[:abc], options[:def], ...
end
And then it could be called using named arguments like this:
C.api1 :abc => 'abc', :def => '...'
Easy to extend, common Ruby practice, and easy to make certain parameters optional.
To continue what mu is describing, a common Ruby idiom you'll see it to have a method set itself some default options and then merge into that hash the options that the method received. This way you can be sure that some minimum list of options always exist:
def self.api1(options={})
default_options = { :foo => 'bar', :baz => nil }
options = default_options.merge options
# Now include your code and you can assume that options[:foo] and options[:bar] are there
end
This comes in handy when your method, for example, outputs the value of :baz. Now you don't need to check that it exists first, you can just output it knowing that it would always exist.

How to intercept the call to constructor of class Hash?

I want to execute a function when a constructor of class Hash is called or when a Hash object is initialized. I have implemented my objective using
class Hash
def initialize
p "Constructor call"
end
end
The code above works fine when a Hash object is initialized as follows:
a = Hash.new(:a1 => "Hi")
However, when I use the following code:
a = {:a1 => "Hi"}
Then, it fails or the constructor is not called. So, how to intercept the call made in the second code snippet?
Thanks in advance.
I'm afraid you can't in MRI, but could probably manage something in Rubinius / JRuby.
Unfortunately, just like in almost every other language, you cannot override literals in Ruby. You'll have to use one of the few languages that allow this, like Ioke:
cell(:{}) = method(+x, "Literal {} called with #{x inspect}" println)
{ :a1 => "Hi" }
;; Literal {} called with [:a1 => "Hi"]
(In fact, Ioke is the only language I can think of right now which allows literal overloading / overriding. I suppose Ioke's cousin Seph will support it, and a couple of years of ago there was some discussion about allowing it in Newspeak, but that's about it.)

Is everything an object in ruby?

Is everything in ruby an object? Does this include Fixnums?
Depends on what you mean by "everything". Fixnums are, as the others have demonstrated. Classes also are, as instances of class Class. Methods, operators and blocks aren't, but can be wrapped by objects (Proc). Simple assignment is not, and can't. Statements like while also aren't and can't. Comments obviously also fall in the latter group.
Most things that actually matter, i.e. that you would wish to manipulate, are objects (or can be wrapped in objects).
Yes. Fixnum is a class, which inherits from Integer, which inherits from Numeric, which finally inherits from Object.
Or, why don't you just ask it? :)
1.is_a? Object # => true
1.class # => Fixnum
Fixnum.is_a? Object # => true
Reading the Ruby info and documentation on the website is a good idea too.
Practically everything in Ruby is an Object, with the exception of control structures. Whether or not under the covers a method, code block or operator is or isn't an Object, they are represented as Objects and can be thought of as such.
Take a code block for example:
def what_is(&block)
puts block.class
puts block.is_a? Object
end
> what_is {}
Proc
true
=> nil
Or for a Method:
class A
def i_am_method
"Call me sometime..."
end
end
> m = A.new.method(:i_am_method)
> m.class
Method
> m.is_a? Object
true
> m.call
"Call me sometime..."
And operators (like +, -, [], <<) are implemented as methods:
class String
def +
"I'm just a method!"
end
end
For people coming into programming for the first time, what this means in a practical sense is that all the rules that you can apply to one kind of Object can be extended to others. You can think of a String, Array, Class, File or any Class that you define as behaving in much the same way. This is one of the reasons why Ruby is easier to pick up and work with than some other languages.
Yes everything is an object in ruby, and that includes Fixnum
Ruby doen't have any primitives (like int, char etc in java), so every value (anything that can sit on the right of an assignment statement) is an object. However, control statements, methods, and other features of the language syntax aren't.
Yup.
> Fixnum.is_a?(Object) #=> true
To see the chain of inheritance:
> pp Fixnum.ancestors
[Fixnum,
Integer,
Precision,
Numeric,
Comparable,
Object,
...
Kernel]
=> nil

Changing default Ruby arguments

I want to change the default arguments passed to a Ruby function. For example, instead of each time writing
[1,2,3].do_stuff(:option => ' my option ')
I want to modify the defaults so that I can write
[1,2,3].do_stuff
What is the simplest, cleanest, most Ruby-like way of changing default parameters?
>> [1, 2, 3].do_stuff
=> Result I get
>> [1, 2, 3].do_stuff :an_option => a_value
=> Result I really want, but don't want to specify the argument
I like to use super for this. It allows us to add some functionality to the method apart from just changing default arguments:
class Array
def do_stuff(options = {})
# Verify if caller has not passed the option
options[:argument_i_want_to_change] = default_value_i_want unless options.has_key? :argument_i_want_to_change
# call super
super
end
end
Result:
>> [1, 2, 3].do_stuff
=> Result that I really want
UPDATE: Removed reverse_merge! dependency. (Now looking for a better alternatives to using []= method)
(moved from your original question)
I assume you are talking about a method Array#do_stuff that already exists, but you want to modify it slightly (in your case by changing a default parameter).
A post here gives a nice way of doing it. It doesn't suffer from the same problems as the alias technique, as there isn't a leftover "old" method.
Here how you could use that technique with your example problem (tested with ruby 1.9)
class Array
old_do_stuff = instance_method(:do_stuff)
define_method(:do_stuff) { |options = {}|
options[:option] ||= " option "
old_do_stuff.bind(self).call(options)
}
end
You might also want read up on UnboundMethod if the above code is confusing. Note that old_do_stuff goes out of scope after the end statement, so it isn't a problem for future uses of Array.
Are you wanting a solution for code you didn't write yourself? There are two options I'm aware of.
Code you wrote yourself:
def some_method_you_wrote(options)
becomes:
def some_method_you_wrote(options = { :option1 => 'value' })
(Swanand's answer is nice too)
For code you didn't write, look into aliasing methods. (Rails provides something called alias_method_chain for this purpose, IIRC.)

Resources