Accessing thread variables of threads stored in instance variables - ruby

This is expected,
t = Thread.new{
Thread.current[:rabbit] = 'white'
}
##### t[:rabbit] = white
But I can't understand this:
class Whatever
def initialize
#thd = Thread.new{
Thread.current[:apple] = 'whatever'
}
end
def apple
#thd[:apple]
end
def thd
#thd
end
end
I want to access these, why are they nil?
Whatever.new.apple # nil
Whatever.new.thd[:apple] # nil
Whatever.new.thd.thread_variable_get(:apple) # nil
Why does this happen? How can I access #thd Thread variables?

What you're seeing here is a race condition. You're attempting to read the thread variable before the body of the thread has been run.
Compare the following:
w = Whatever.new
w.apple
# => nil
w = Whatever.new
sleep 0.1
w.apple
# => "whatever"
Whether or not the thread body gets run in time with Whatever.new.apple is pretty much random, it seems to happen 0.1% of the time for me, but this is probably different on other machines
1000.times.
map { Whatever.new.apple }.
each_with_object(Hash.new(0)) { |val, memo| memo[val] += 1 }
# => {nil=>999, "whatever"=>1}
2000.times.
map { Whatever.new.apple }.
each_with_object(Hash.new(0)) { |val, memo| memo[val] += 1 }
# => {nil=>1998, "whatever"=>2}
(note: I cannot try with a higher number of iterations because the large amount of thread spawning causes my IRB to run out of resources)
This relates to what I've heard described as the "number one rule of async", namely that you can't get the return value of an asynchronous method from a synchronous one. The usual way to handle this is with a "callback", which Ruby can do in the form of yield / blocks.
I recommend looking for a tutorial about how to do asynchronous programming in Ruby.

Related

ruby do map and compact together

I'm new to ruby and this looks wrong but works fine
def get_internal_deps
self.internal_dependencies = self.sources.map do |f|
s = File.open(File.join(self.dir, f)).grep(/\d{8}-\w{5}/)
if s.length > 0
{:file => f, :line => s}
end
end.compact
#how crazy does that look?
end
So how do I do this without having an end.compact?
Some notes
Your method is called get_internal_deps, but it looks like it actually sets an instance variable.
You could define internal_dependencies and use caching.
In this case, you'd need to remove any attr_reader/writer/accessor for #internal_dependencies.
File.open(f) isn't really clean.
You don't need self in self.dir or self.sources
:line is an Array. Shouldn't it be called :lines?
2 separate, short methods might be better than a bigger one.
Refactored code
def internal_dependencies
#internal_dependencies ||= sources.map{|s| parse_dependency(s) }
.reject{|h| h[:line].empty? }
end
private
def parse_dependency(source)
{
file: source,
line: File.readlines(File.join(dir, source)).grep(/\d{8}-\w{5}/)
}
end
To avoid compact one might use reduce (Enumerable#each_with_object in this particular case) instead of map:
def get_internal_deps
self.internal_dependencies = sources.each_with_object do |f, acc|
s = File.open(File.join(self.dir, f)).grep(/\d{8}-\w{5}/)
acc << {:file => f, :line => s} if s.length > 0
end
end
Also, note that an explicit self receiver might make sense in a case of assignment, but it is completely redundant in RHO (sources in this snippet.)

Self enumerating function

I've got some code:
def my_each_with_index
return enum_for(:my_each_with_index) unless block_given?
i = 0
self.my_each do |x|
yield x, i
i += 1
end
self
end
It is my own code, but the line:
return enum_for(:my_each_with_index) unless block_given?
is found in solutions of other's. I can't get why they passed the function to enum_for as a parameter. When I invoke my function without a block, it won't return anything with or without enum_for. I could left sth like:
return unless block_given?
and it has the same result. Or am I wrong?
Being called without a block, it will return an enumerator:
▶ def my_each_with_index
▷ return enum_for(:my_each_with_index) unless block_given?
▷ end
#⇒ :my_each_with_index
▶ e = my_each_with_index
#⇒ #<Enumerator: main:my_each_with_index>
later on you might iterate on this enumerator:
▶ e.each { |elem| ... }
This behavior is specifically useful in some cases, like lazy iteration, passing block to this enumerator later etc.
Just returning nil cuts this ability off.
Think you for very precise answer. I recived also very good example to understand this issue for other new developers:
def iterator
yield 1
yield 2
yield 3
puts "koniec"
end
iterator { |v| puts v }
it = enum_for(:iterator)
puts it.next
puts it.next
puts it.next
puts it.next
Just run and analyze this code.
For any method that accepts a block, a good method implementation should have a well-defined behavior when the block is not given.
In the example shared by you, each_for_index is being re-implemented by author, may be to provide additional semantics or may be just for academic purpose given that its behavior is same as Ruby's Enumerable#each_with_index.
The documentation has following for Enumerable#each_with_index.
Calls block with two arguments, the item and its index, for each item
in enum. Given arguments are passed through to each().
If no block is given, an enumerator is returned instead.
In order to stay consistent with highlighted line indicating what should be the behavior if block is not given, one has to use something like
return enum_for(:my_each_with_index) unless block_given?
enum_for is interesting method
enum_for creates a new Enumerator which will enumerate by calling method on obj.
Below is an example reproduced from documentation:
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
So, if one does not pass block to my_each_with_index, they have a chance to pass it later - just like one would have done with each_with_index.
e = obj.my_each_with_index
...
e.each { |x, i| # do something } # `my_each_with_index` executed later
In summary, my_each_with_index tries to be consistent with each_with_index and tries to be a well-behaved API.

How to handle thread returns Ruby

I have a ruby script in which I'm parsing a large csv file. Ihave everything handled and working fairly well, except for how to deal with the thread's return values. I have:
length = (ses.size/4).ceil
ses.each_slice(length) do |x|
threads << Thread.new { a,b = splat x }
end
threads.each { |thr|
thr.join
}
'splat' returns to temp files that need to appended to the output files out1 and out2. I'm stumbling on where exactly to do that/how to get that information. If someone could point me in the right direction that'd be great.
Two things, first, when you pass the 'x' into the thread, it's safer to make it thread-local by changing this:
threads << Thread.new { a,b = splat x }
Into this:
threads << Thread.new(x) { |x| a,b = splat x }
Next, to get the return value out, you join using :value.
So here's a quick demo I whipped up:
dummy = [
['a.txt', 'b.txt'],
['c.txt', 'd.txt'],
['e.txt', 'f.txt'],
['g.txt', 'h.txt'],
['i.txt', 'j.txt'],
['k.txt', 'l.txt']
]
threads = dummy.map do |pair|
Thread.new(pair) { |val| val }
end
vals = threads.map(&:value) # equiv. to 'threads.map { |t| t.value }'
puts vals.inspect
Crib off that and it should get you where you want to go.

Use of yield and return in Ruby

Can anyone help me to figure out the the use of yield and return in Ruby. I'm a Ruby beginner, so simple examples are highly appreciated.
Thank you in advance!
The return statement works the same way that it works on other similar programming languages, it just returns from the method it is used on.
You can skip the call to return, since all methods in ruby always return the last statement. So you might find method like this:
def method
"hey there"
end
That's actually the same as doing something like:
def method
return "hey there"
end
The yield on the other hand, excecutes the block given as a parameter to the method. So you can have a method like this:
def method
puts "do somthing..."
yield
end
And then use it like this:
method do
puts "doing something"
end
The result of that, would be printing on screen the following 2 lines:
"do somthing..."
"doing something"
Hope that clears it up a bit. For more info on blocks, you can check out this link.
yield is used to call the block associated with the method. You do this by placing the block (basically just code in curly braces) after the method and its parameters, like so:
[1, 2, 3].each {|elem| puts elem}
return exits from the current method, and uses its "argument" as the return value, like so:
def hello
return :hello if some_test
puts "If it some_test returns false, then this message will be printed."
end
But note that you don't have to use the return keyword in any methods; Ruby will return the last statement evaluated if it encounters no returns. Thus these two are equivelent:
def explicit_return
# ...
return true
end
def implicit_return
# ...
true
end
Here's an example for yield:
# A simple iterator that operates on an array
def each_in(ary)
i = 0
until i >= ary.size
# Calls the block associated with this method and sends the arguments as block parameters.
# Automatically raises LocalJumpError if there is no block, so to make it safe, you can use block_given?
yield(ary[i])
i += 1
end
end
# Reverses an array
result = [] # This block is "tied" to the method
# | | |
# v v v
each_in([:duck, :duck, :duck, :GOOSE]) {|elem| result.insert(0, elem)}
result # => [:GOOSE, :duck, :duck, :duck]
And an example for return, which I will use to implement a method to see if a number is happy:
class Numeric
# Not the real meat of the program
def sum_of_squares
(to_s.split("").collect {|s| s.to_i ** 2}).inject(0) {|sum, i| sum + i}
end
def happy?(cache=[])
# If the number reaches 1, then it is happy.
return true if self == 1
# Can't be happy because we're starting to loop
return false if cache.include?(self)
# Ask the next number if it's happy, with self added to the list of seen numbers
# You don't actually need the return (it works without it); I just add it for symmetry
return sum_of_squares.happy?(cache << self)
end
end
24.happy? # => false
19.happy? # => true
2.happy? # => false
1.happy? # => true
# ... and so on ...
Hope this helps! :)
def cool
return yield
end
p cool {"yes!"}
The yield keyword instructs Ruby to execute the code in the block. In this example, the block returns the string "yes!". An explicit return statement was used in the cool() method, but this could have been implicit as well.

Understanding Ruby Enumerable#map (with more complex blocks)

Let's say I have a function
def odd_or_even n
if n%2 == 0
return :even
else
return :odd
end
end
And I had a simple enumerable array
simple = [1,2,3,4,5]
And I ran it through map, with my function, using a do-end block:
simple.map do
|n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]
How could I do this without, say, defining the function in the first place? For example,
# does not work
simple.map do |n|
if n%2 == 0
return :even
else
return :odd
end
end
# Desired result:
# => [:odd,:even,:odd,:even,:odd]
is not valid ruby, and the compiler gets mad at me for even thinking about it. But how would I implement an equivalent sort of thing, that works?
edit
In reality, the solution to my problem matters to me a lot less than the motivation/reasoning behind it, to help me understand more how ruby blocks work :)
You're so close. Just remove the returns and you're golden.
This is because the block passed to map is a proc (i.e. created with Proc.new), and not a lambda. A return within a proc doesn't just jump out of the proc- it jumps out of the method that executed (i.e. called call on) the proc. A return within a lambda, on the other hand, jumps out of only the lambda.
The proc method returns a lambda in Ruby 1.8, and a Proc in Ruby 1.9. It's probably best to just not use this method and be explicit with which construct you want to use.
I'm guessing you were either in IRB or a plain ruby script when you were trying this out.
a = Proc.new { return }
a.call # fails. Nothing to return from.
def foobar
a = Proc.new { return }
a.call
puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.
b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.
def bazquux
b = lambda { return }
b.call
puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'
The lesson to learn from this is to use implicit returns unless you can't, I guess.
I suspect this may be a duplicate question, but to give a value out of a block, use next
simple.map do |n|
if n%2 == 0
next :even
else
next :odd
end
end
Shortest variant using Andrew's answer:
simple.map { |n| next :even if n % 2 == 0; :odd }

Resources