Can named parameters have aliases? - ruby

I'm writing a method which will assess statistical information relative to distributional parameters:
def munch(data:, mean:, standard_deviation:)
# munch the data
end
However, standard_deviation is quite a mouthful, and is known by other names (e.g., sigma, sd) which may be more memorable or convenient for end-users. I could add more parameters to the method and then manually check that one and only one of the alternative names is used, but that's tedious and ugly. Is there some way to say that sd and sigma are aliases for standard_deviation so that the following would work?
result1 = munch(data: my_data, mean: 20.0, standard_deviation: 3.0)
result2 = munch(data: my_data, mean: 20.0, sd: 3.0)
p result1 == result2 # => true

If you don't want to type too much, and really want to sanity-check, something like this might work?
def alias_param(opts, *keys, **args)
supplied = opts.select { |k, _| keys.include?(k) }
if supplied.size > 1
raise ArgumentError, "Multiple aliases supplied: #{supplied.keys.inspect}"
elsif supplied.size < 1
raise ArgumentError, "Missing argument: one of #{keys.inspect}"
end
opts.values.first
end
def fn(data:, mean:, **opts)
sd = alias_param(opts, :sd, :sigma, :standard_deviation)
end
fn(data: 1, mean:3)

To directly answer your question, no, at least not in the automatic way I believe you mean by your comments.
There is no built-in mechanism to define multiple names for one option, and have Ruby automatically return the same value no matter which of those options you reference. By your comment, I assume this is the intended behavior, something akin to an alias keyword, and then having the ability to call either by old or new name.
Your only real option is to parse the options manually, which typically shouldn't add too much boring boiler-plate code:
def blending(**options)
#mode = options[:mode] || options[:blend_mode]
#function = options[:function] || options[:blend_function]
end
There is nothing similar to alias_option :mode, :blend_mode that will allow you to simply use one of those names and get the value no matter which the method was invoked with. No matter which way you do this, there will be some manual checking to be done.

Based on Amadan's answer, here's what I ended up going with.
def check4aliases(opts, *keys)
supplied = opts.select { |k, _| keys.include?(k) }
return supplied.values.first if supplied.size == 1
msg = supplied.empty? ?
"Missing parameter: #{keys.first}" : "Use only one of #{keys.join(', ')}"
raise ArgumentError, msg
end
def munch(data:, **opts)
parameters = {
mu: check4aliases(opts, :mean, :mu),
sd: check4aliases(opts, :standard_deviation, :sd, :sigma)
}
# do actual work with data, mu, and sd
end
test_cases = [
{mean: 3, sd: 7},
{mu: 5, sigma: 4},
{mean: 3, mu: 3, sd: 7, sigma: 7, standard_deviation: 7},
{mean: 3, sd: 7, sigma: 8},
{mean: 3},
]
test_cases.each do |parms|
begin
p munch(data: 1, **parms)
rescue ArgumentError => msg
puts msg
end
end
which produces:
{:mu=>3, :sd=>7}
{:mu=>5, :sd=>4}
Use only one of mean, mu
Use only one of standard_deviation, sd, sigma
Missing parameter: standard_deviation
I still wish aliasing was an option, but this is usable.

Related

Is there a rule for what goes between the | x | in a block function?

I'm currently studying blocks, and noticed that depending on what's being carried out, the symbol between the 'goalposts' seems to change, is this purely for readability purposes and one could just as easily make every goalpost contain |i|, or is there a rule behind what must go here?
Code examples below.
[ 1, 3, 5, 7, 9 ].each {|i| puts i }
f = File.open("testfile")
f.each do |line|
puts line end
f.close
What you call "symbol between the 'goalposts'" is more commonly called a "parameter" in programming.
A "parameter" is kind of like a "hole" or "placeholder" in the definition of a procedure / function / method / block / subroutine / whatever you want to call it. You can give it any name you want (as long as it is a valid identifier for a parameter, of course). You can use this name inside the body of your procedure / function / method / block / subroutine, without knowing what its exact value at runtime will be.
When you then execute the procedure / function / method / block / subroutine, the caller can pass what is called an "argument", i.e. a specific value to fill this "hole". This "argument" will then be "bound" to the parameter. This means that for this particular execution of the procedure / function / method / block / subroutine, when you reference the parameter, it will have this particular value.
So, for example, if you have something like this:
def add(first_parameter, second_parameter)
first_parameter + second_parameter
end
add(23, 42)
Then first_parameter and second_parameter are the parameters of the add method, and 23 and 42 are the arguments passed to this particular execution of add.
Similarly, when you have
def block_executor
yield 23, 42
end
block_executor do |first_parameter, second_parameter|
first_parameter + second_parameter
end
Then first_parameter and second_parameter are the parameters of the block, and 23 and 42 are the arguments passed to this particular execution of the block.
Technically, you can name it anything you like as it's the variable name you will be using in the block -- i.e between the { & }.
But you should name this variable something with meaning to make your code more readable and easier to understand.
In the example above, num or number would be preferable to i.
line makes sense because that's how a file is read, line by line.
As it is a simple variable, you can name it in the way that best suits you.
But try to name it in a more semantic way, this to help the future you or another developer to improve the reading of your code.
If you look at here, you will find some tips for the kind of situations that your asking for.
Here is a style guide provided by Rubocop, which will help you with many of these doubts.
Rubocop Style Guide
The list between the pipe characters (|...|) is known as the block parameters and largely follow the same rules as for method parameters and local variables:
The identifier can contain _ and alphanumerical characters.
The identifier may not begin with a number.
You can use a crazy number of UTF-8 characters like like Ö, ¤ or 的. For example π = Math::PI. If its a good idea is debateable.
The identifier cannot contain reserved characters like !, ? +, -, :.
You cannot use the same identifier twice in the parameters list.
A block can have any number of positional parameters:
... do |a, b, c|
end
Unlike with methods and lambdas Ruby doesn't enforce that a block is called with the correct number of arguments.
You can use defaults:
def foo
yield
end
foo do |x = 1|
x
end
# 1
You can use splats to slurp a variable number of arguments and do destructing:
def foo(*args)
yield *args
end
foo(3, 2, 1) do |*numbers|
numbers.sort
end
# [1, 2, 3]
foo(3, 1, 5, 8, 2) do |*numbers|
numbers.sort
end
# [1, 2, 3, 5, 8]
foo('a', 'c', 'e', 'b', 'f') do |first, *middle, rest|
middle.sort
end
# ["b", "c", "e"]
You can even destructure a single argument:
{ bar: [1,2,3], baz: [5, 6, 7, 8] }.map do |key, (first, *middle, last)|
middle
end
# [[2], [6, 7]]
And you can use keyword arguments if there is no logical order to the arguments or if there are so many that you can't keep track of them:
def foo
yield a: 1, b: 2, c: 3, bar: 4, baz: 5
end
foo do |baz:, bar:, optional_parameter: nil|
bar
end
# 1
foo do |**kwargs|
kwargs
end
# { a: 1, b: 2, c: 3, bar: 4, baz: 5 }

Optimize print output where i use check on zero. Ruby

Currently, I'm having print like this
print ((stamp_amount[0], 'first mark') unless stamp_amount[0].zero?), (', ' if !stamp_amount[0].zero? && !stamp_amount[1].zero?),
((stamp_amount[1], 'second mark') unless stamp_amount[1].zero?)
stamp_amount is an array with 2 integer values
Let's say in the current situation stamp_amount[0] = 10 and stamp_amount[1] = 3
Output preview:
10 first mark, 3 second mark
So if stamp_amount[0] = 0 the 10 first mark, part won't be show. Same if stamp_amount[1] = 0 the , 3 second mark part won't be shown
For me, it seems a little bit incorrect in terms of theory. Could you please suggest me the more correct or less painful print of this? :)
Cheers!
Your code is trying to join a sequence of up to two elements with a separator. The joining is a solved problem, see Array#join.
The problem can be then reduced to "how can I produce the correct sequence, given my stamp_amount input". Now this can be done in a thousand ways. Here's one:
def my_print(stamp_amount)
ary = [
!stamp_amount[0].zero? && stamp_amount[0],
!stamp_amount[1].zero? && stamp_amount[1],
].select{|elem| elem }
ary.join(', ')
end
my_print([10, 3]) # => "10, 3"
my_print([0, 3]) # => "3"
my_print([10, 0]) # => "10"
my_print([0, 0]) # => ""
Here's another
ary = []
ary << stamp_amount[0] unless stamp_amount[0].zero?
ary << stamp_amount[1] unless stamp_amount[1].zero?
ary.join(', ')
Here's yet another. This version can handle stamp_amount of any length.
ary = stamp_amount.reject(&:zero?)
ary.join(', ')
I'd go with the third, but the second one may be the easiest to understand for a beginner.
Use the select, as an alternative to reject (shown in part 3 of the answer by Sergio Tulentsev). It is just asa readable, and depending on the context and on the future changes to the code, you may prefer one versus the other.
puts stamp_amount.select{ |a| !a.zero? }.join(", ")
A few examples of inputs and outputs are:
stamp_amount output
--------------------------------------------------------------------------
10, 3 10, 3
10, 0 10
0, 3 3
0, 0 (prints an empty line, because the selected array is empty)
You're calculating zero? on index points more often than is needed, but the first thing I would look at refactoring here is the readability of the code. It might be nicer to calculate the message to print outside of the print method and explain what is happening with variable names.
# rubocop is going to complain about variable assignment like this
first_amount, second_amount = *stamp_amount
We can actually use the reason rubocop prefers the .zero? over == 0 or .empty? method to guide our development. zero? is in essence just empty? but it communicates the meaning of what you are attempting to do in a better manner. I would use this reasoning when assigning strings to variables that explain what they are doing.
some_name_that_explains_what_this_is_0 = "#{first_amount} piecu centu marka"
some_name_that_explains_what_this_is_1 = "#{second_amount} tris centu marka"
Your current code is confusing as you have the possibility of printing a string like "10 tris centu marka" which does not make lexical sense and probably not what you are after considering tis evaluates to 'second mark', which would pose an issue if the first value is zero. We also could reject zero integers before we start converting them to strings.
array = [1, 0].reject(&:zero?)
Now we can take the array and do something like:
string = []
array.each_with_index { |e, i| string << "#{e} #{Ordinalize.new(i).ordinalize} mark" }
message = string.join(', ')
print(message)
# ord class
class Ordinalize
def initialize(value)
#value = value
end
def ordinalize
mapping[#value]
end
def mapping
# acounting for zero index
['first', 'second']
end
end
where we are calculating the ordinalization and letting our new class handle the sentence structure for us.
Outputs:
[1, 0] => "1 first mark"
[0, 1] => "1 first mark"
[1, 2] => "1 first mark, 2 second mark"

Trying to refactor ruby code so parameter list isn't so long

If I have a method with a parameter list like such:
def func(param1, param2, param3, para4, param5, param6)
what would be the best way to get rid of the long list? There are suggestion to create a separate object, but I'm not sure how I would do that.
You can use the variadic * splat in Ruby:
def f(*p)
p1,p2,p3,p4,p5,p6,p7,p8=*p
p p
p p8
end
f(*(1..8).to_a)
# [1, 2, 3, 4, 5, 6, 7, 8]
# 8
There are tradeoffs here. You loose the interpreter's help in counting the args actually passed to the method.
By doing:
p1,p2,p3,p4,p5,p6,p7,p8=*p
any arguments more than 8 to the method will be silently ignored and if less than 8, the shortfall will be silently assigned nil:
> f(1,2,3)
[1, 2, 3]
nil
If that is OK, the * is a useful shortcut.
You can also use an empty array as a default arg:
def f2(p=[])
p1,p2,p3,p4,p5,p6,p7,p8=*p
p p
p p8
end
Then call without the splat since now the method is expecting one argument, not a variable number:
f2(1..8)
With the same comment regarding the array length apply: arguments lengths greater than 8 are silently ignored and less than 8 are silently assigned nil
You can add argument checking to variable length arguments if desired:
def f(*p)
args_expected=8
raise ArgumentError, "\"#{__method__}\": wrong number of arguments (given %d expected %d)" % [p.length, args_expected] if p.length !=args_expected
p1,p2,p3,p4,p5,p6,p7,p8=*p
end
> f(1,2,3)
ArgumentError: "f": wrong number of arguments (given 3 expected 8)
But now you are adding words and complexity back.
There are good reasons to use named positional arguments if you are expecting a fixed number of arguments. The function is easy to change and you are allowing the interpreter help you.
A suggestion would be to use a single hash with the parameters as keys/options.
def func(hash_param = {})
param1 = hash_param[:param1]
param2 = hash_param[:param2]
param3 = hash_param[:param3]
param4 = hash_param[:param4]
param5 = hash_param[:param5]
param6 = hash_param[:param6]
#rest_of_code
end
hash = {
param1: 'foo',
param2: 'bar',
param3: 'baz',
param4: 'qux',
param5: 'alice',
param6: 'bob'
}
func(hash)
If some specific keys inside the hash are not defined, they will simply return nil.

Call a Ruby method explicitly using the default for a parameter

An unfortunately large number of methods are written in the following form:
def my_method(foo = {}, bar = {})
# Do stuff with foo and bar
end
While I appreciate not having to write my_method({}, {}) everywhere I reference the method, using something other than the default for the second parameter makes me use something other than the default for the first parameter too - my_method({}, foo: 'bar').
Is there a way to tell Ruby to use the default for a parameter when other, later parameters need to use something other than the default? I'm hoping for something in the form of my_method(__default__, foo: 'bar'), but would welcome any other solutions that address the core of this problem.
This would be particularly useful when APIs undergo minor (but significant) changes. It can lead to hard to find bugs occasionally:
# Original method
def foo(value = 'true', options = {})
# ...
end
# Defaults are updated slightly in a new version of the library
def foo(value = true, options = {})
# ...
end
# My code might break in an unexpected way now
foo('true', bar: 'baz')
This is the problem which keyword arguments (new to ruby 2) were made to solve (provided that you control the method definition).
def foo(a: {}, b: {})
"a: #{a}, b: #{b}"
end
foo # => "a: {}, b: {}"
foo(a: 1, b: 2) # => "a: 1, b: 2"
foo(a: 3) # => "a: 3, b: {}"
foo(b: 4) # => "a: {}, b: 4"
You could set defaults to nil then handle the actual defaulting of values within the body of the method. ie.,
def my_method(first=nil, second=nil)
first_value = first || 1
second_value = second || 2
end
This allows you to pass 'nil' when you want that value to be its default. For example,
my_method(nil, 'second')
Now 'first_value' is 1 and second_value is 'second'.
edit: though 'nil' is really non-descriptive of the action of making the method use its default value. Consider:
def my_method(first=:default, second=:default)
first_value = (first == :default ? 1 : first)
second_value = (second== :default ? 2 : second)
end
Then you can do:
my_method(:default, 'second')
(but really Sergio's answer is the best =) )
You can just refactor the code to something like this, so it gets assigned to the default value only if the named parameter isn't provided a value.
def my_method(foo, bar)
foo ||= {}; bar ||= {};
#=> Do something with foo and bar now.
end
What ||= operator does is, it assigns the value on the right to the variable on the left if the variable isn't initialized or has nil value.
You can now call it like this
my_method(nil, "I'm bar");
If by any chance, you want to pass nil as a value, then this will fail. Sergio Tulentsev's answer is the way to go. I'd have suggested the same had I known it.

Blocks & Procs in Ruby

I have started learning Ruby, and I have read a couple of tutorials and I even bought a book ("Programming Ruby 1.9 - The Pragmatic Programmers' Guide"), and I came across something new that I haven't seen before in any of the other languages I know (I am working as a PHP webdeveloper).
Blocks & Procs.
I think I understand what they are, but what I don't understand is why they are so great, and when and why I should use them.
Everywhere I look they say blocks and procs are a great feature in Ruby, but I don't understand them.
Can anybody here give a total Ruby-newbie like me some explanations?
There are a lot of things that are good about blocks. The elevator pitch: Blocks let us pass around actions the same way we normally pass around data.
The most obvious level is that they let you abstract things out into functions that wouldn't be possible otherwise. For example, let's look at a common case where you have a list of things and you want to filter it to only include items that match some criterion:
int list[50] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50};
int evenNumbers[50] = {0};
int copyIndex = 0;
for (int i = 0; i < 50; i++) {
if (list[i] % 2 == 0) {
evenNumbers[copyIndex++] = list[i];
}
}
Here's how you write that in Ruby:
list = 1..50
listCopy = list.select {|n| n.even?}
All the common busywork is moved out of your code and into a method with a meaningful name. We don't care about copying the array and going through indexes and all that — we just want a filtered list. And that's what select gives us. The block allows us to pass our custom logic into this standard method.
But iterators aren't the only place where this "hole in the middle pattern" is useful. For example, if you pass a block to File.open, it will open the file, execute the block with the file and then close the file for you.
Another thing that blocks give us is a really powerful form of callbacks. For example, without blocks, we might have to do something like this (based on how dialogs actually work in Objective-C Cocoa):
class Controller
def delete_button_clicked(item)
item.add_red_highlight
context = {:item => item}
dialog = Dialog.new("Are you sure you want to delete #{item}?")
dialog.ok_callback = :delete_OK
dialog.ok_receiver = self
dialog.cancel_callback = :cancel_delete
dialog.cancel_receiver = self
dialog.context = context
dialog.ask_for_confirmation
end
def delete_OK(sender)
delete(sender.context[:item])
sender.dismiss
end
def cancel_delete(sender)
sender.context[:item].remove_red_highlight
sender.dismiss
end
end
Yowza. With blocks, we could do this instead (based on a common pattern used in many Ruby libraries):
class Controller
def delete_button_clicked(item)
item.add_red_highlight
Dialog.ask_for_confirmation("Are you sure you want to delete #{item}?") do |response|
response.ok { delete item }
response.cancel { item.remove_red_highlight }
end
end
end
That's actually two levels of blocks — the do...end block and the two {}-style blocks. But it reads pretty naturally, doesn't it? This works because a block captures the context it's created in, so we don't need to pass around self and item.
As for Procs, they're just an object wrapper for blocks. Not very much to them.
Its important to view blocks not as using methods to begin a code block, you are actually taking the block and using it like a parameter in the function.
So when you use the each method to iterate over an array like so:
superOverFlowArray.each { |flow| puts flow }
You are sending the block { |flow| puts flow } into the each method. The code is telling ruby to send the current value of the array to this block in place of |flow|.
Procs take a block and make them into a variable. Procs are object instances that hold blocks. Blocks are passed as a parameter to the proc and are executed when you call the 'call' method on that Proc instance.
So here is a Proc example:
def category_and_title(category)
Proc.new { |title| "The title is: " + title + " in category: " + category }
end
myFirstTitle = category_and_title("Police Drama")
mySecondTitle = category_and_title("Comedy")
puts myFirstTitle.call("Law and Order")
puts mySecondTitle.call("Seinfeld")
puts myFirstTitle.call("CSI")
The Proc will remember the original category that was passed in, allowing a convenient way of grouping types.
Blocks are used from many methods in Ruby classes, and they are used where in PHP you would use a callback.
[1,2,3,4,5].each {|i| print "#{i} "}
[1,2,3,4,5].each do |i|
print "#{i} "
end
File.open('p014constructs.rb', 'r') do |f1|
while line = f1.gets
puts line
end
end
PHP5 introduced anonymous functions; instead of using a callback, you could use an anonymous function.
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
Procs, also known as closures or lambdas is a concept in ruby that may seem confusing at first, especially to a newbie. In short, procs allow you to pass code blocks around with ease. An example, below
hello = Proc.new do |x, y|
puts "i am a proc"
sum = x+y
puts "sum: #{sum}"
end
now to make use of this block of code, just call the method "call" on hello. Note that the example above receives arguments x and y which the code block uses. Therefore be sure to pass in arguments when you call out the Proc object like i have done below:
hello.call(2, 3)
yielding the following results:
i am a proc
sum: 5
Hurray!! That was an easy way to create a Proc object. How useful is this? Well, proc objects allow you to pass around chunks of code. An illustration below explains it better by making use of the proc created in the example above.
Let's create some random class,
class SomeClass
def initialize(&block)
#block = block
end
def output_value(x, y)
#block.call(x, y)
end
end
now, let's create an instance of SomeClass,
some_class = SomeClass.new(&hello)
NOTE that the ampersand sign "&" before the hello allows you to pass a proc object as an argument.
finally, let's output a value by passing 2 arguments, like below:
some_class.output_value(1, 3)
the result you get is as follows:
i am a proc
sum: 4
See!! it's that simple. You have been able to pass a chunk of code around.
Procs are so useful that ruby makes use of it a lot. Hope this was super helpful :)
These concepts are tied to concepts from functional programming into ruby, hence it enables you to use patterns and techniques that are usually found in languages, where functions are first-class citizens.
Blocks and procs let you extract small bits of code without the full overhead and complexity of methods.
Even map by itself is pretty powerful, and jQuery is built around this same concept:
['spite','rest','purpose'].map {|s| s << 'ful' }
And you can throw logic in if necessary
['sprite','restful','luck'].map {|s| s << (s.end_with?('uck') ? 'i' : '') << 'ly' }
There is a clever operator '&' that means "convert the symbol to a proc and call it", so you can convert objects strings:
['spite',12,:purpose].map(&:to_s)
And using closures and combining writing a simple closures we can find where adjacent of numbers appear. This is rather clumsy Ruby, but more concise than most languages:
last = -2 # this variable is accessed and changed within the closure
objs.sort.map do |o|
if (last + 1) != o
last = o
nil # not one more than previous so return nil
else
o
end
end.compact # compact removes nils
When you start rewriting it in another language you realize how convenient this is. It encourages you to structure your code into smaller operations, so it is more re-usable and testable.

Resources