Ruby min max assignment operators - ruby

When programming ruby I always find myself doing this:
a = [a, b].min
This means compare a and b and store the smallest value in a. I don't like writing the code above as I have to write a twice.
I know that some non-standard dialects of C++ had an operator which did exactly this
a <?= b
Which I find very convenient. But I'm not really interested in the operator as much as I'm in the feature of avoiding repetition. I would also be happy if I could write
a.keep_max(b)
a can be a quite long variable, like my_array[indice1][indice2], and you don't want to write that twice.
I did alot of googling on this and found no result, hopefully this question will pop up and be useful for others aswell.
So, is there any non-repeitive way to express what I want in ruby?

What you would like to do is in fact not possible in ruby (see this question). I think the best you can do is
def max(*args)
args.max
end
a = max a, b

I don't understand your question. You can always do something like this ...
module Comparable
def keep_min(other)
(self <=> other) <= 0 ? self : other
end
def keep_max(other)
(self <=> other) >= 0 ? self : other
end
end
1.keep_min(2)
=> 1
1.keep_max(2)
=> 2
Well, that won't work for all objects with <=> because not all of them are implementing Comparable, so you could monkey-patch Object.
Personally I prefer clarity and tend to avoid monkey-patching. Plus, this clearly is a binary predicate, just like "+", therefore method-chaining doesn't necessarily make sense so I prefer something like this to get rid of that array syntax:
def min(*args)
args.min
end
def max(*args)
args.max
end
min(1, 2)
=> 1
max(1, 2)
=> 2
But hey, I'm also a Python developer :-)

You can define your own method for it:
class Object
def keep_max(other)
[self, other].max
end
end
a = 3
b = 7
puts a.keep_max(b)
But you should be careful defining methods on Object as it can have unpredictable behaviour (for example, if objects cannot be compared).

def keep_max(var, other, binding)
eval "#{var} = [#{var}, #{other}].max", binding
end
a = 5
b = 78
keep_max(:a, :b, binding)
puts a
#=> 78
This basically does what you want. Take a look at Change variable passed in a method

Related

Loop method until it returns falsey

I was trying to make my bubble sort shorter and I came up with this
class Array
def bubble_sort!(&block)
block = Proc.new { |a, b| a <=> b } unless block_given?
sorted = each_index.each_cons(2).none? do |i, next_i|
if block.call(self[i], self[next_i]) == 1
self[i], self[next_i] = self[next_i], self[i]
end
end until sorted
self
end
def bubble_sort(&prc)
self.dup.bubble_sort!(&prc)
end
end
I don't particularly like the thing with sorted = --sort code-- until sorted.
I just want to run the each_index.each_cons(s).none? code until it returns true. It's a weird situation that I use until, but the condition is a code I want to run. Any way, my try seems awkward, and ruby usually has a nice concise way of putting things. Is there a better way to do this?
This is just my opinion
have you ever read the ruby source code of each and map to understand what they do?
No, because they have a clear task expressed from the method name and if you test them, they will take an object, some parameters and then return a value to you.
For example if I want to test the String method split()
s = "a new string"
s.split("new")
=> ["a ", " string"]
Do you know if .split() takes a block?
It is one of the core ruby methods, but to call it I don't pass a block 90% of the times, I can understand what it does from the name .split() and from the return value
Focus on the objects you are using, the task the methods should accomplish and their return values.
I read your code and I can not refactor it, I hardly can understand what the code does.
I decided to write down some points, with possibility to follow up:
1) do not use the proc for now, first get the Object Oriented code clean.
2) split bubble_sort! into several methods, each one with a clear task
def ordered_inverted! (bubble_sort!), def invert_values, maybe perform a invert_values until sorted, check if existing methods already perform this sorting functionality
3) write specs for those methods, tdd will push you to keep methods simple and easy to test
4) If those methods do not belong to the Array class, include them in the appropriate class, sometimes overly complicated methods are just performing simple String operations.
5) Reading books about refactoring may actually help more then trying to force the usage of proc and functional programming when not necessary.
After looking into it further I'm fairly sure the best solution is
loop do
break if condition
end
Either that or the way I have it in the question, but I think the loop do version is clearer.
Edit:
Ha, a couple weeks later after I settled for the loop do solution, I stumbled into a better one. You can just use a while or until loop with an empty block like this:
while condition; end
until condition; end
So the bubble sort example in the question can be written like this
class Array
def bubble_sort!(&block)
block = Proc.new { |a, b| a <=> b } unless block_given?
until (each_index.each_cons(2).none? do |i, next_i|
if block.call(self[i], self[next_i]) == 1
self[i], self[next_i] = self[next_i], self[i]
end
end); end
self
end
def bubble_sort(&prc)
self.dup.bubble_sort!(&prc)
end
end

Running method on two variables at once

I am wondering what the proper way is to refactor this code for efficiency besides running it twice.
class Hamming
def compute (a, b)
a.to_a.split("")
b.to_a.split("")
end
end
Is there something similar to assigning two variables at once like
a, b = 1, 2?
First off, your code is invalid. #to_a returns an array; #split is not defined on arrays.
Secondly, if your code was valid (say, a.to_s.split(""); b.to_s.split(""), it would not actually do much, because your code would just return the value of the last executed statement (b.to_s.split("")). Both #to_s and #split are non-destructive, which means they will not change a or b - the only effect you get from this function is what it returns, and you do not return the result of a.to_s.split("") in any way: it is forgotten.
If you meant something like this:
class Hamming
def compute(a, b)
[
a.to_s.split(""),
b.to_s.split("")
]
end
end
this is fairly readable. However, if you had more complex operation than just .to_s.split(""), it would be better to isolate it into its own function:
class Hamming
def compute(a, b)
[
list_chars(a),
list_chars(b)
]
end
private def list_chars(str)
str.to_s.split("")
end
end
You could simplify it even more using map, but it really only becomes necessary when you have multiple elements, as the two-element case is perfectly legible as-is. However, here goes:
class Hamming
def compute(a, b)
[a, b].map { |x| list_chars(x) }
end
private def list_chars(str)
str.to_s.split("")
end
end
Also, you might want to see the method #each_char, giving you an iterator, which is more readable, and often the more correct choice, than .split("").
EDIT: After thinking about it a bit, it seems like you're starting a method to evaluate a Hamming distance between two strings; and that you do not intend to have that function simply return the character of the two strings. In that case, I'd just write this:
def compute(a, b)
a_chars = a.to_s.each_char
b_chars = b.to_s.each_char
# ...
end
or possibly this, if you absolutely need to have characters themselves, and not an iterator:
def compute(a, b)
a_chars = a.to_s.each_char.to_a
b_chars = b.to_s.each_char.to_a
# ...
end
The solution I believe you are looking for would look like this:
def compute(a, b)
a_chars, b_chars = *[a, b].map { |x| x.to_s.each_char.to_a }
# ...
end
but I'd consider that less readable than the non-DRY one; if you really want to DRY it up, extract the listification into its own function as described above, and just do
a_chars = list_chars(a)
b_chars = list_chars(b)
which is actually the best of both worlds, even if it is a bit of an overkill in this case: it is DRY-ly maintainable and self-documentingly legible, for a bit of tradeoff in verbosity.
Since the code doesn't make sense, I think what you're asking is how do you avoid repeating yourself.
Simple, write another method and call that. Here's an example of wanting to find out which phrase is longer, but you want to ignore lots of whitespace. So foo bar isn't longer than 12345678.
def longer_phrase(phraseA, phraseB)
normalizedA = normalize(phraseA)
normalizedB = normalize(phraseB)
return normalizedA.length > normalizedB.length ? phraseA : phraseB
end
def normalize(phrase)
normalized = phrase.gsub(/\s+/, ' ');
normalized.strip!
return normalized
end
puts longer_phrase("foo bar ", "12345678")
Needing to normalize all your data before doing work on it comes up a lot. This avoids repeating yourself. It makes your code easier to understand, since we know what the point of all that work is, to normalize the string. And it gives you a normalization function to use elsewhere so you're normalizing your data the same way.

What is prefered way to loop in Ruby?

Why is each loop preferred over for loop in Ruby? Is there a difference in time complexity or are they just syntactically different?
Yes, these are two different ways of iterating over, But hope this calculation helps.
require 'benchmark'
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
a.each { |x| sum += x }
}
This takes 5.866932 sec
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
for x in a
sum += x
end
}
This takes 6.146521 sec.
Though its not a right way to do the benchmarking, there are some other constraints too. But on a single machine, each seems to be a bit faster than for.
The variable referencing an item in iteration is temporary and does not have significance outside of the iteration. It is better if it is hidden from outside of the iteration. With external iterators, such variable is located outside of the iteration block. In the following, e is useful only within do ... end, but is separated from the block, and written outside of it; it does not look easy to a programmer:
for e in [:foo, :bar] do
...
end
With internal iterators, the block variable is defined right inside the block, where it is used. It is easier to read:
[:foo, :bar].each do |e|
...
end
This visibility issue is not just for a programmer. With respect to visibility in the sense of scope, the variable for an external iterator is accessible outside of the iteration:
for e in [:foo] do; end
e # => :foo
whereas in internal iterator, a block variable is invisible from outside:
[:foo].each do |e|; end
e # => undefined local variable or method `e'
The latter is better from the point of view of encapsulation.
When you want to nest the loops, the order of variables would be somewhat backwards with external iterators:
for a in [[:foo, :bar]] do
for e in a do
...
end
end
but with internal iterators, the order is more straightforward:
[[:foo, :bar]].each do |a|
a.each do |e|
...
end
end
With external iterators, you can only use hard-coded Ruby syntax, and you also have to remember the matching between the keyword and the method that is internally called (for calls each), but for internal iterators, you can define your own, which gives flexibility.
each is the Ruby Way. Implements the Iterator Pattern that has decoupling benefits.
Check also this: "for" vs "each" in Ruby
An interesting question. There are several ways of looping in Ruby. I have noted that there is a design principle in Ruby, that when there are multiple ways of doing the same, there are usually subtle differences between them, and each case has its own unique use, its own problem that it solves. So in the end you end up needing to be able to write (and not just to read) all of them.
As for the question about for loop, this is similar to my earlier question whethe for loop is a trap.
Basically there are 2 main explicit ways of looping, one is by iterators (or, more generally, blocks), such as
[1, 2, 3].each { |e| puts e * 10 }
[1, 2, 3].map { |e| e * 10 )
# etc., see Array and Enumerable documentation for more iterator methods.
Connected to this way of iterating is the class Enumerator, which you should strive to understand.
The other way is Pascal-ish looping by while, until and for loops.
for y in [1, 2, 3]
puts y
end
x = 0
while x < 3
puts x; x += 1
end
# same for until loop
Like if and unless, while and until have their tail form, such as
a = 'alligator'
a.chop! until a.chars.last == 'g'
#=> 'allig'
The third very important way of looping is implicit looping, or looping by recursion. Ruby is extremely malleable, all classes are modifiable, hooks can be set up for various events, and this can be exploited to produce most unusual ways of looping. The possibilities are so endless that I don't even know where to start talking about them. Perhaps a good place is the blog by Yusuke Endoh, a well known artist working with Ruby code as his artistic material of choice.
To demonstrate what I mean, consider this loop
class Object
def method_missing sym
s = sym.to_s
if s.chars.last == 'g' then s else eval s.chop end
end
end
alligator
#=> "allig"
Aside of readability issues, the for loop iterates in the Ruby land whereas each does it from native code, so in principle each should be more efficient when iterating all elements in an array.
Loop with each:
arr.each {|x| puts x}
Loop with for:
for i in 0..arr.length
puts arr[i]
end
In the each case we are just passing a code block to a method implemented in the machine's native code (fast code), whereas in the for case, all code must be interpreted and run taking into account all the complexity of the Ruby language.
However for is more flexible and lets you iterate in more complex ways than each does, for example, iterating with a given step.
EDIT
I didn't come across that you can step over a range by using the step() method before calling each(), so the flexibility I claimed for the for loop is actually unjustified.

Is it possible to access block's scope in method?

I'd like to write the method (define_variables) which can get a block and use the variables defined in it. Is it possible? For example, I'd like to get 5 in output:
module A
def self.define_variables
yield
puts a # not 5 :(
end
end
A::define_variables do
a = 5
end
Maybe there is some tricks with eval, but haven't found anyone yet.
In short, no. After you've called yield those variables defined in the block are gone (sort of, as we shall see), except for what is returned—that's just how scope works. In your example, the 5 is still there in that it is returned by the block, and thus puts yield would print 5. Using this you could return a hash from the block {:a => 5}, and then access multiple "variables" that way. In Ruby 1.8 (in IRb only) you can do:
eval "a = 5"
a # => 5
Though I don't know of anyway to eval the contents of a block. Regardless, in Ruby 1.9 the scope of eval was isolated and this will give you a NameError. You can do an eval within the context of a Binding though:
def foo
b = yield
eval(a, b) + 2
end
foo do
a = 5
binding
end # => 7
It seems to me that what you're trying to do is emulate macros in Ruby, which is just not possible (at least not pure Ruby), and I discourage the use of any of the "workarounds" I've mentioned above.
Agreed that this is a bit backwards, and Andrew's explanation is correct. If your use case is defining variables, however, there are already class_variable_set and instance_variable_set methods that are great for this:
module A
def self.define_variables(vars = {})
vars.each { |n, v| class_variable_set n, v }
puts ##a
end
end
A::define_variables :##a => 5
The above is more of an example of how it would work within the code you've posted rather than a recommendation.

How to create an operator for deep copy/cloning of objects in Ruby?

I would like to achieve the following by introducing a new operator (e.g. :=)
a := b = {}
b[1] = 2
p a # => {}
p b # => {1=>2}
As far as I understand, I need to modify the Object class, but I don't know what to do in order to get what I want.
require 'superators'
class Object
superator ":=" operand # update, must be: superator ":=" do |operand|
# self = Marshal.load(Marshal.dump(operand)) # ???
end
end
Could you help me with this?
Update
Ok, superators will probably not help me here, but I still want such operator. How can I (or you) create an extension for Ruby, which I could load as a module?
require 'deep_copy_operator'
a !?= b = {} # I would prefer ":=" but don't really care how it is spelled
b[1] = 2
p a # => {}
p b # => {1=>2}
wow, superators look neat! But unfortunately, this won't work for you, for two reasons. First, your operator does not match the regex (you cannot use a colon). Easy enough, find a new operator. But the second one I don't think can be overcome, the superator is basically a method name defined on the object to the left. So you can't use it for assignment statements. If your variable is not defined, then you cannot use it, that would raise an error. And if it is defined, then you can't change its type in any way that is obvious to me (maybe with some level of reflection and metaprogramming that is way beyond anything I know, but it honestly seems unlikely... of course, I would have never expected it to be possible to create superators, so who knows).
So I think you're back to hacking parse.y and rebuilding your Ruby.
First of all, the syntax for superators is
superator ":=" do |operand|
#code
end
It's a block, because superator is a metaprogramming macro.
Secondly, you have something going their with Marshal...but it's a bit of magic-ish. Feel free to use it as long as you understand exactly what it is you're doing.
Thirdly, what you are doing isn't quite doable with a superator (I believe), because self cannot be modified during a function. (if someone knows otherwise, please let me know)
Also, in your example, a must first exist and be defined before being able to call the method := in it.
Your best bet is probably:
class Object
def deep_clone
Marshal::load(Marshal.dump(self))
end
end
to generate a deep clone of an object.
a = (b = {}).deep_clone
b[1] = 2
p a # => {}
p b # => {1=>2}

Resources