I'm having trouble understanding how to use worker processes along with modules. I'll try to explain my difficulty simply.
I have on my main process (process 1) a module, module A.
On worker processes ,I have module B, which is supposed to handle numerous complicated calculations (as is often the case with parallel workers).
The problem is that it seems as if module A needs to be defined on the workers...
The problem is that module A is much larger than module B, it includes thousands of lines of code, but module B only uses around 15 short functions.
Is there any workaround so I can make my main worker have access to module A but the workers access to module B but be able to call workers from methods in module A, and make them run functions defined in their module B? For example, there could be a method in module B called calculate_stuff().
The structure I was hoping to achieve is something like:
module A # main worker process using this module
function call_worker_and_calculate()
remotecall_fetch(calculate_stuff, 2)
end
export call_worker_and_calculate
end
module B # worker process 2 is using this module
function calculate_stuff()
# some stuff
end
export calculate_stuff
end
This particular example would return the error message:
julia> A.call_worker_and_calculate()
ERROR: On worker 2:
UndefVarError: A not defined
The error message is odd (I can't reproduce it with your code, what version do you use?). So I'm not sure this answers your question.
If you want to use a name from a module B in another module A, you must import or using module B in A.
For this to work, B must be in a path contained in the Julia variable LOAD_PATH or defined on all workers with #everywhere before the definition of A, e.g.,
#everywhere module B # defined on all workers
function calculate_stuff()
# do stuff
end
export calculate_stuff
end
module A # only defined on the main worker process
using B # introduces calculate_stuff into A's scope because it is exported in B
function call_worker_and_calculate()
remotecall_fetch(calculate_stuff, 2)
end
export call_worker_and_calculate
end
Then A.call_worker_and_calculate() works and A is also not defined on other workers:
julia> remotecall_fetch(whos,2)
From worker 2: B 4537 bytes Module
From worker 2: Base 34048 KB Module
From worker 2: Core 12482 KB Module
From worker 2: Main 40807 KB Module
Related
I was having trouble understanding an error while unit testing my module, which is a mixin.
Suppose the mixin to be tested is module A:
require 'path/b'
module A
def methodA()
puts methodB.attr1
end
end
And it depends on another mixin B which was defined in a file at path/b.rb
module B
def methodB
return someObject #that has property 'attr1'
end
end
Now, we have a class to unit test module A
require 'path/moduleA'
class TestA
include Path::moduleA
end
describe 'test moduleA.methodA'
it 'does something'
testObject = TestA.new
testObject.methodA()
expect(....)
end
end
I get following error on running the rspec test
NameError:
undefined local variable or method `methodB' for #<TestA:0x00007f77a03db9a8>
I am able to resolve it by one of following ways:
including module B in module A
including module B in class TestA
Questions
I am not clear why include is required to get access to methodB in
module A and class TestA when 'require' was already added in module A.
My intention is to use methods of module B in module A, but not let users of module A access module B methods automatically.
resolution 1 above gives users of A, access to B's methods
resolution 2 forces users of A (user -> the unit test class in this example) to include A's dependency B directly, even though user is only interested in accessing A's methods.
Hence, both resolutions don't achieve what I want. Is there a way to achieve it?
I'm new to Ruby so may be it doesn't support this. I'm from Java background where I would model A and B as two classes, make an instance of B as field of A, then expose A's own public methods to users of A. But since they are mixins, I need to use modules in ruby.
Just to be very explicit: require / require_relative / load and include / extend / prepend have absolutely nothing whatsoever to do with each other.
The former three simply run a Ruby file. That's it. That is all they do. They differ in how and where they search for the file, but after they found the file, they don't do anything else than just execute it.
The latter three add a module to the ancestor chain. include essentially makes the module the superclass, extend is really the same as singleton_class.include (i.e. makes the module the superclass of the singleton class), and prepend inserts the module at the beginning of the ancestor's chain, i.e. actually before the class that it is prepended to.
require just tells ruby to read / load the code inside the ruby file. In this case it will just define the module. However in order for code inside a module to be included inside another module or class, you must include it inside the module or class. So you should just as you mentioned do:
require 'path/b'
module A
include B
def methodA()
puts methodB.attr1
end
end
You should not need to change your test with this since module A already includes module B. However this is not a very good OOP design pattern here. But hopefully you understand why now.
After more googling, I found the answer to my 2nd question using suggestion from:
https://makandracards.com/makandra/977-calling-selected-methods-of-a-module-from-another-module
so basically i did:
require 'path/b'
module A
module B_RequiredMethods
include Path::B
module_function :methodB
end
def methodA
puts B_RequiredMethods.methodB.attr1
end
end
In my case, B_RequiredMethods could be named properly to represent the method of B which would be exposed by it. Ideally, I would make those methods class level methods of B, but it is managed by some other team.
Given I have the following data structure:
module A
module B
module C
class D
end
end
end
end
I want to access it in client code like this:
C::D
rather than
A::B::C::D
One solution would be to define a method in module A like this:
module A
def self.get_d
B::C::D
end
end
A.get_d
But the thing is that C::D is defined in many places already in system. So I need to be backward compatible. How can I address this situation?
There is no such thing as a "nested module". It's just a module that is assigned to a namespaced constant. If you want to assign to a different constant … just assign it to a different constant:
C::D = A::B::C::D
Note: this assumes that a constant named C exists in the current namespace and that it refers to a module or class. However, that assumption is already present in your question.
I wanted to separate some methods into a module for abstraction purposes but I am getting a nomethod error when testing the first function in my module.
functions.rb
module Functions
def avg_ticket(vol,count)
(vol.to_f/count).round(2)
end
end
example.rb
require_relative 'functions'
vol = 5000
count = 2500
avg_ticket = Functions.avg_ticket(vol,count)
I am getting a undefined method 'avg_ticket' for functions:Module (NoMethodError)
both files are in the same folder so I am using require_relative if that makes a difference. this may be basic, but can anyone help me understand why the method is undefined here?
edit: changed module functions to module Functions in question
You named your module functions, but you're trying to call Functions. Names are case sensitive. Also, you need to name your module with an upper case first letter anyway. Also, to be defined on the module itself, you want to use def self.avg_ticket, see the following:
module Functions
def self.avg_ticket(vol,count)
(vol.to_f/count).round(2)
end
end
And using it:
p Functions.avg_ticket(2, 25)
> 0.08
I am learning ruby at the moment. I am trying to understand the way closures work, and how they are different from functions. I am fully aware that closures should be implemented via proc or lambda.
I am trying to get an in depth understanding of ruby. As such I checking all kinds of unorthodox code. I am trying to understand why line 3 works while line 5 is an error.
x=123
def b(x)
p x
def a(u)
p x # why is this an error?!?!?
end
a 4
end
b 1
If a can't access b's parameters, why doesn't it access the global x=123?
Why does this work if I explicitly use change lines 1 & 5 to the global "$x"?
Why does this work if I use a lambda explictly?
This is purely a learning exercise, I am doing this to understand what is going on beneath the hood.
It's something called the "scope gate". Basically, when you start a definition of a method/class/module, a new scope is created and all local variables from other scopes can't be accessed. This doesn't apply to instance/global variables, you'll keep access to those.
Since a lambda isn't a method, it doesn't create new scope and reuses existing one instead.
Also,
why line 3 works
x = 123
def b(x)
p x # this "x" is "x the parameter", not "x the local variable from outer scope"
# that's why it works. If you tried to access the local var, it wouldn't work.
def a(u)
p x # like here, see? Doesn't work.
end
a 4
end
b 1
The first thing to understand is that def does not make a "function" (what does that even mean in Ruby?) -- def defines a method on some object or class. Even when it appears to be not inside any object, it still defines a method on the "main" object. So when you do def a, it is not "local" to the method b; it is a method a just like if you defined it at the top level, except that it doesn't get defined until b runs. It can be called as the method a from other places. You have nested method definitions.
Because it was meant to define methods, which most of the time is defined at the top level of a class or module, def was never made to capture outside variables.
I'm having some difficulty with referring to module-level variables in ruby. Say I have a situation like this, where I'm referring to M.a internally:
module M
##a=1
def self.a
##a
end
class A
def x
M.a
end
end
end
Now, this example works fine for me but it is failing in a slightly more complicated context (where the module is spread over a number of files installed in a local gem - but my understanding is that that should not effect the way the code is executed) with an error like this: undefined method `a' for M::M (NoMethodError).
So, is this the correct way to refer to module level variables in context? is there a simpler/more idiomatic way?
If the module is spread out over other files, you need to ensure that your initialization is run before the method is called. If they are in the same file, this should be as much as guaranteed, but if you somehow split them there could be trouble.
I've found you can usually get away with this:
module M
def self.a
#a ||= 1
end
end
If this variable is subject to change, you will need a mutator method. Rails provides mattr_accessor that basically does what you want, part of ActiveSupport.