Can't locate object method "say_hello" via package "1" - linux

I just started to learn Perl. When I moved to object orientation I am getting an error like
Can't locate object method "say_hello" via package "1" (perhaps you forgot to load "1"?) at ./main.pl line 8.
I googled a lot for a solution. Got some similar issues like this. My understanding is it's not a general issue.
Here is my class
# MyModule.pm
package MyModule;
use strict;
use warnings;
sub new {
print "calling constructor\n";
}
sub say_hello {
print "Hello from MyModule\n";
}
1;
Here is my test script
# main.pl
#!/usr/bin/perl -w
use strict;
use warnings;
use MyModule;
my $myObj = new MyModule();
$myObj->say_hello();
The code is working perfectly if remove last line from main.pl

Your constructor new needs to return a blessed reference to the data structure you are using to contain the object's information. You have no relevant data here, but you still need to return something
bless associates the data with a specific package. In this case, your object should be blessed into MyModule, so that perl knows to look for MyModule::say_hello when it sees a method call like $myObj->say_hello()
Your current constructor returns the value returned by the print statement, which is 1 if it succeeded, as it almost certainly does. That is why you see the "1" in the error message
Can't locate object method "say_hello" via package "1" (perhaps you forgot to load "1"?) at ./main.pl line 8.
The most common container for an object's data is a hash, so you need to change new to this
sub new {
print "calling constructor\n";
my $self = { };
bless $self, 'MyModule';
return $self;
}
and then your program will work as it should. It creates an anonymous hash and assigns it to the $self variable, then blesses and returns it
Note that this can be made much more concise:
Without a return statement, a subroutine will return the value of the most recently executed statement
By default, bless will bless the data into the current package
There is no need to store the reference in a variable before blessing it
So the same effect may be achieved by writing
sub new {
print "calling constructor\n";
bless { };
}
Note also that your call
my $myObj = new MyModule()
is less than ideal. It is called indirect object notation and can be ambiguous. It is better to always use a direct method reference, such as
my $myObj = MyModule->new()
so as to disambiguate the call

You're not creating a new object, and thus $myObj is just the return code of the "print" statement (or 1).
You need to bless something and return it.
sub new {
my ( $class ) = #_;
print "Calling Constructor\n";
my $self = {};
bless $self, $class;
return $self;
}
That way $myObj will actually be an object, not just a return code :)

Related

Proper Way to Provide Variable to Objects below the present calling subroutine?

In my code base, I have several variables that "live" in the main namespace and various modules I utilize can expect to always find in main (for example, $main::author is a reference to a hash about the user, $main::dbh is the open database handle, $main::loader is an object of a core utility class and $main::FORM has the processed QUERY_STRING). E.g. when the program starts up:
$main::author = &getAuthor;
$main::loader = SAFARI::Loader->new;
use SAFARI::View;
my $view = SAFARI::View->new;
$view->output;
And then when I'm in SAFARI::View::output, I can call on those core variables, e.g.:
# Display user name:
$output .= 'Hello, ' . $main::author->{'fullName'} . '! Welcome!';
The problem: when the code is running in a threaded environment, one thread may need a different $loader object or have a different $author logged in than the other thread. More pressingly still, each thread has, of course, a different database handle.
I know I could pass along the core information when creating objects such as View by adding parameters it takes. But that means every type of object that presently can just reference these items in the main namespace must have a lengthy list of parameters instead. I'm trying to think of the most efficient and "safe" way to solve this problem.
I've considered creating a hash reference that has all the different bits in it within each thread, e.g. $common that has $common->{'FORM'}, $common->{'loader'}, $common->{'author'}, etc., and then pass those as a single argument to each object:
my $common = #Logic to set up this combination of bits for this particular thread.
my $view = SAFARI::View->new({ 'common' => $common });
my $article = SAFARI::Article->new({ 'common' => $common });
my $category = SAFARI::Category->new({ 'common' => $common });
That's not too tedious, but it still seems inefficient; it'd be preferable if the "environment" of just that thread could contain something that object within in it could access. As far as I can tell, declaring our $common within the subroutine that is run by the thread would do this and any objects created within that subroutine would have access to that variable. Is there any harm in this approach?
It seems like it would be cleaner to have these items in some sort of namespace, but if I refer to, say, $SAFARI::common, that name space would reach across threads just like main does. Would having $SAFARI::common but then declaring a local variant of it in each thread be reasonable?
Is there a "best practice" for what I'm trying to do? It's going to take some significant reworking of code to fix this one way or another, so I'd really like to get it "right."
This is a complex question, with multiple major components.
For starters, there is a question of how to pass an initial data-structure to threads so that they can use it, but without it being shared.
In Perl, when threads are created the existing data are copied to each thread. That's why it's often a good idea to create threads right up front, before there's much data in the program, to avoid those threads being bloated. The copied data is not shared, by default, in Perl.
So you can just create your initial $common structure in the main:: and then create threads, and each will get its own copy of it. Then threads can create their own SAFARI:: objects and do as they please with the data structure. A simple demo
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd pp);
use threads;
my $ds = { val => 10, ra => [ 10..12 ] };
my #threads = map { async(\&proc_ds, $ds) } 1..3;
$_->join() for #threads;
say "main: ", pp $ds;
sub proc_ds {
my ($ds) = #_;
# Modify data in the thread
$ds->{val} += 10 * threads->tid;
$_ += $ds->{val} for #{$ds->{ra}};
say "Thread ", threads->tid, ": ", pp $ds;
}
This prints
Thread 1: { ra => [30, 31, 32], val => 20 }
Thread 2: { ra => [40, 41, 42], val => 30 }
Thread 3: { ra => [50, 51, 52], val => 40 }
main: { ra => [10, 11, 12], val => 10 }
If, instead, you need to share data structures perhaps see this page, for example.
Each thread then needs to use a class hierarchy, whereby multiple subclasses should be initialized the same way using a common data structure modified in each thread.†
In Perl's inheritance model, methods gets inherited from the parent class but not data. So the question here is how to nicely populate all subclasses to same data.
There are advanced techniques that may make the process more elegant, but I'd suggest to simply introduce the attribute and define the method in the parent class and then have all subclasses use it to initialize. That is going to be crystal clear, and as economical as anything else. Like
use SAFARI::View;
use SAFARI::Other;
# ... set/customize $common
my ($sview_obj, $sother_obj) =
map { $_->new->init_common($common) }
qw(SAFARI::View SAFARI::Other);
say "View object: $sview_obj"; # overload "" (quotes) for this, see below
This would be done in each thread, where $common is first customized per thread as needed.
There isn't a magical way for the derived classes to pick up data from the parent, and you don't want a base class to have to know about its derived classes, in principle. And there is nothing wrongjk with nicely instantiating all subclasses, much like in the question itself.
The sub init_common need only be defined in SAFARI, the parent class
SAFARI.pm file
package SAFARI;
use warnings;
use strict;
sub new {
my ($class, #args) = #_;
my $self = {
common => {}, # introduce the attribute, for clarity
# ...
};
return bless $self, $class;
}
sub init_common {
my ($self, $data) = #_;
$self->{common}->{dbh} = $data->{dbh}; # etc, populate common
return $self;
}
...
1;
We don't need to specify the attribute in the constructor if it's not being set as it will be created by writing to $self reference in init_common, but listing it helps clarity. (Of course, common attribute can be written at construction ‡ as well; and, we don't need a separate method for it either.)
Derived subclasses need not mention any of this, attribute nor init_common method, unless they should customize things.
SAFARI/View.pm file
package SAFARI::View;
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(pp);
# Make sure #INC gets set as needed
use parent 'SAFARI';
use overload ( q("") => sub { return pp {%$_[0]} } );
# no need for init_common, nor for new (except to modify/override)
sub output {
my ($self, #args) = #_;
say $self->{common}->{...};
return $self;
};
...
1;
† Inheritance is already in place here, otherwise composition or roles would be good alternatives. Even so, still consider using a role here; see this post for instance.
‡ If 'common' data can be passed to the constructor
sub new {
my ($class, $attr) = #_; # pass a hashref with attribute => value
my $self = {
common => {}, # introduce the attribute, for clarity
# ...
};
bless $self, $class;
$self->init_common( $attr->{common} ) if exists $attr->{common};
return $self;
}
sub init_common {
my ($self, $data) = #_;
$self->{common}->{$_} = $data->{$_} for keys %$data;
return $self;
}
then 'common' can also be initialized as
# ... set/customize $common
my ($sview_obj, $sother_obj) =
map { $_->new( { common => $common } ) }
qw(SAFARI::View SAFARI::Other);

How to set a puppet class variable from within a hiera_hash each loop?

hiera data
ae::namespace_by_fqdn_pattern:
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/blah/regression/client'
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/blah/regression/server'
class
class ae {
$namespace = hiera('ae::namespace')
$target_host_patterns = hiera('ae::target_host_patterns')
hiera_hash('ae::namespace_by_fqdn_pattern').each |String $pattern, String $ns| {
if $facts['networking']['fqdn'].match($pattern) {
$ae::namespace = "${ns}"
}
}
<snip>
... yields
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Illegal attempt to assign to 'ae::enforcerd_namespace'. Cannot assign to variables in other namespaces (file: /etc/puppetlabs/code/environments/ar/modules/ae/manifests/init.pp, line: 21, column: 13) on node dfw-ubuntu1604-client02.pp-devcos.us-central1.gcp.dev.blah.com
... anyone here know how to do this correctly? trying to conditionally override that $ae::namespace variable but i'm too puppet-ignorant to know how to get it working : (
the loop and the pattern matching bits work. just can't figure out how to correctly set that class variable from within the hiera_hash().each loop.
How to set a puppet class variable from within a hiera_hash each loop?
You cannot. The associated block of an each() call establishes a local scope for each iteration. Variable assignments within apply to that local scope, and therefore last only for the duration of one execution of the block. You cannot anyway assign a new value to a variable during its lifetime, so even if you could assign to a class variable from within an each() call, it would be difficult to use that capability (and your approach would not work).
There are several ways you could approach the problem without modifying the form of the data. You could leverage the filter() function, for example, but my personal recommendation would be to use the reduce() function, something like this:
$namespace = lookup('ae::target_host_patterns').reduce(lookup('ae::namespace')) |$ns, $entry| {
$facts['networking']['fqdn'].match($entry[0]) ? { true => $entry[1], default => $ns }
}
That does pretty much exactly what your original code seems to be trying to do, except that the selected namespace is returned by the reduce() call, to be assigned to a variable by code at class scope, instead of the lambda trying to assign it directly. Note also that it takes care not only of testing the patterns but of assigning the default namespace when none of the patterns match, as it needs to do because you can only assign to the namespace variable once.
so the solution i landed on was to change the hiera data to:
ae::namespace : '/test/blah/regression'
ae::namespace_patterns: ['((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com', '((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com']
ae::namespace_by_pattern:
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((client))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/paypal/regression/client'
'((^dfw-oel6)|(^dfw-oel7)|(^dfw-ubuntu1604))-((server))([0-9]{2}).pp-devcos-ae.us-central1.gcp.dev.blah.com': '/test/paypal/regression/server'
then the class code to:
$pattern = hiera_hash('ae::namespace_patterns').filter |$pattern| {
$facts['networking']['fqdn'] =~ $pattern
}
if length($pattern) {
$namespace = hiera('ae::namespace_by_pattern')[$pattern[0]]
} else {
$namespace = hiera('ae::namespace')
}
definitely still open to better answers. just what my own hacking produced as workable so far through much trial and error.

Is it possible to get the name of variable in Groovy?

I would like to know if it is possible to retrieve the name of a variable.
For example if I have a method:
def printSomething(def something){
//instead of having the literal String something, I want to be able to use the name of the variable that was passed
println('something is: ' + something)
}
If I call this method as follows:
def ordinary = 58
printSomething(ordinary)
I want to get:
ordinary is 58
On the other hand if I call this method like this:
def extraOrdinary = 67
printSomething(extraOrdinary)
I want to get:
extraOrdinary is 67
Edit
I need the variable name because I have this snippet of code which runs before each TestSuite in Katalon Studio, basically it gives you the flexibility of passing GlobalVariables using a katalon.features file. The idea is from: kazurayam/KatalonPropertiesDemo
#BeforeTestSuite
def sampleBeforeTestSuite(TestSuiteContext testSuiteContext) {
KatalonProperties props = new KatalonProperties()
// get appropriate value for GlobalVariable.hostname loaded from katalon.properties files
WebUI.comment(">>> GlobalVariable.G_Url default value: \'${GlobalVariable.G_Url}\'");
//gets the internal value of GlobalVariable.G_Url, if it's empty then use the one from katalon.features file
String preferedHostname = props.getProperty('GlobalVariable.G_Url')
if (preferedHostname != null) {
GlobalVariable.G_Url = preferedHostname;
WebUI.comment(">>> GlobalVariable.G_Url new value: \'${preferedHostname}\'");
} else {
WebUI.comment(">>> GlobalVariable.G_Url stays unchanged");
}
//doing the same for other variables is a lot of duplicate code
}
Now this only handles 1 variable value, if I do this for say 20 variables, that is a lot of duplicate code, so I wanted to create a helper function:
def setProperty(KatalonProperties props, GlobalVariable var){
WebUI.comment(">>> " + var.getName()" + default value: \'${var}\'");
//gets the internal value of var, if it's null then use the one from katalon.features file
GlobalVariable preferedVar = props.getProperty(var.getName())
if (preferedVar != null) {
var = preferedVar;
WebUI.comment(">>> " + var.getName() + " new value: \'${preferedVar}\'");
} else {
WebUI.comment(">>> " + var.getName() + " stays unchanged");
}
}
Here I just put var.getName() to explain what I am looking for, that is just a method I assume.
Yes, this is possible with ASTTransformations or with Macros (Groovy 2.5+).
I currently don't have a proper dev environment, but here are some pointers:
Not that both options are not trivial, are not what I would recommend a Groovy novice and you'll have to do some research. If I remember correctly either option requires a separate build/project from your calling code to work reliable. Also either of them might give you obscure and hard to debug compile time errors, for example when your code expects a variable as parameter but a literal or a method call is passed. So: there be dragons. That being said: I have worked a lot with these things and they can be really fun ;)
Groovy Documentation for Macros
If you are on Groovy 2.5+ you can use Macros. For your use-case take a look at the #Macro methods section. Your Method will have two parameters: MacroContext macroContext, MethodCallExpression callExpression the latter being the interesting one. The MethodCallExpression has the getArguments()-Methods, which allows you to access the Abstract Syntax Tree Nodes that where passed to the method as parameter. In your case that should be a VariableExpression which has the getName() method to give you the name that you're looking for.
Developing AST transformations
This is the more complicated version. You'll still get to the same VariableExpression as with the Macro-Method, but it'll be tedious to get there as you'll have to identify the correct MethodCallExpression yourself. You start from a ClassNode and work your way to the VariableExpression yourself. I would recommend to use a local transformation and create an Annotation. But identifying the correct MethodCallExpression is not trivial.
no. it's not possible.
however think about using map as a parameter and passing name and value of the property:
def printSomething(Map m){
println m
}
printSomething(ordinary:58)
printSomething(extraOrdinary:67)
printSomething(ordinary:11,extraOrdinary:22)
this will output
[ordinary:58]
[extraOrdinary:67]
[ordinary:11, extraOrdinary:22]

How to solve the "String" in "for each" loop

My task is to open multiple files after a button clicked, and read all those selected files.
I have found an example of foreach function in c#, but I would like to write it in C++. How should I actually to convert that?
It shows the error that System::String, cannot use this type here without top level '^'.
I'm still new with that. Does anyone can give suggestion?
Thank you very much.
Below is my written codes
Stream^ myStream;
OpenFileDialog^ openFileDialog1 = gcnew OpenFileDialog;
openFileDialog1->InitialDirectory = "c:\\";
openFileDialog1->Title = "open captured file";
openFileDialog1->Filter = "CP files (*.cp)|*.cp|All files (*.*)|*.*|txt files (*.txt)|*.txt";
openFileDialog1->FilterIndex = 2;
//openFileDialog1->RestoreDirectory = true;
openFileDialog1->Multiselect = true;
if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
{
**for each (String line in openFileDialog1->FileName)**
System::Diagnostics::Debug::WriteLine("{0}",line);
myStream->Close();
}
Depending on the Container type returned, there is a std::for_each defined in <algorithm>-header.
The function Looks like this:
#include <algorithm>
std::for_each(InputIterator first, InputIterator last, Function fn);
You need to provide two iterators, one for the beginning of the Container and one for the end of the iterator. As a third Argument you can provide a function (function-object) and operate on the current argument.
See here for further reference.
As I got it from MSDN, the property SafeFileNames returns an array<String^>.
System::Array provides a static method called Array::ForEach. You would need to call it like
System::Action<T> myAction; // You will Need to provide a function here to be used on every filename.
System::Array::ForEach(openFileDialog1->SafeFileNames, myAction);
This comes closest to foreach from C#.
Look here for System::Array::ForEach and here for OpenFileDialog::SafeFileNames.

How should I update a hash of hashes when using multi-threading in Perl?

I have been spending the last hours trying to figure this out and now I'm really confused.
This is the outline of my task. I should write a Perl subroutine that gets a reference to a hash of hashes.
I have another sub (helper) that gets a single inner hash and does some stuff to with, including adding keys.
sub helper {
$href = shift;
$href->{NEW_KEY}=1;
}
Since each of the internal hashes is independent of the others, I would like to use multi-threading to call helper.
I'm using Thread::Pool::Simple which almost lacks any documentation. Thread::Pool is not supported by my Perl version.
So I have something like this:
sub my_sub {
$hohref = shift;
# create thread pool
my $pool = Thread::Pool::Simple->new(
do => [ \&helper ]
);
# submit jobs
foreach my $hashref ( values %{$hohref} ) {
$pool->add( $hashref );
}
# wait for all threads to end
$pool->join();
}
The key point is that I would like the main hash of hashes to reflect all the changes made to the inner hashes.
my_sub gets an unshared reference to $hohref so I tried creating a shared copy in the body of my_sub:
my $shared_hohref = shared_clone $hohref;
use it and return it instead, but still, the internal hashes were not updated.
When I use the exact same code, but simply replace all the thread pool block with a simple loop
foreach my $hashref ( values %{$hohref} ) {
helper( $hashref );
}
then everything works fine.
Your help would be greatly appreciated.
UPDATE
See this runnable example:
use strict;
use warnings;
use threads;
use threads::shared;
use Thread::Pool::Simple;
use 5.010;
use Data::Dumper;
sub helper {
say "helper starts";
my $href = shift;
say "href is $href";
$href->{NEW_KEY} = 1;
say "helper ends with $href";
}
sub my_sub {
my $hohref = shift;
my $shared_hohref = shared_clone $hohref;
my $pool = Thread::Pool::Simple->new( do => [\&helper] );
# submit jobs
foreach my $hashref ( values %{$shared_hohref} ) {
say "adding to pool: $hashref";
$pool->add($hashref);
}
# wait for all threads to end
$pool->join();
return $shared_hohref;
}
my $hoh = {
A => { NAME => "a" },
B => { NAME => "bb" }
};
say "1\t", Dumper $hoh;
my $updated_hoh = my_sub($hoh);
say "2\t", Dumper $updated_hoh;
'helper starts' but that's it... what ever happens to it?
See http://www.perlmonks.org/?node_id=860786.

Resources