I have some code as follow:
my $d1 = $start_date;
$c->log->debug(Dumper($start_date));
my #date_range;
while($d1 <= $end_date){
push #date_range, $d1->day();
$d1->add(days => 1);
}
How can I do to prevent $start_date changed?
You can use clone method:
my $date = new DateTime();
my $temp_date = $date->clone();
It will be a copy and not a reference. If instead you do the below:
my $temp_date = $date;
then both will refer to the same object.
In perl, objects are scalar references. When you do "my $d1 = $start_date" you are making $d1 a referemce which refers to the same object as $start_date.
You probably want to modify a copy of $start_date. I don't know what class $start_date is, but see if that class provides a copy constructor for you to use.
Related
Test case:
use 5.026;
use Perl6::Controls qw(for);
for (1..10) -> $n {
say $n;
}
loop {};
Expect:
Can't call method "loop" without a package or object reference
Got:
infinite loop
use Perl6::Controls qw(for);
BEGIN {
delete $^H{'Keyword::Simple/keywords'}{"loop"};
}
...
which I stumbled into running your script through B::Deparse.
To pick and choose the keywords you want to keep, you could say
use Perl6::Controls;
BEGIN {
my #keep = ...; # e.g. #keep = qw(for);
my %keywords;
#keywords{#keep} = #{$^H{'Keyword::Simple/keywords'}}{#keep};
$^H{'Keyword::Simple/keywords'} = \%keywords;
}
You can't. Looking at the source-code for Perl6::Controls it uses it's own import method to define all the new keywords using Keyword::Declare. It ignores any parameters passed on the use line.
I am trying to write some classes with Perl 6 just for testing out Perl 6 classes and methods.
Here is the code:
class human1 {
method fn1() {
print "#from human1.fn1\n";
}
}
class human2 {
method fn1() {
print "#from human2.fn1\n";
}
}
my $a = human1.new();
my $b = human2.new();
$a.fn1();
$b.fn1();
print "now trying more complex stuff\n";
my $hum1_const = &human1.new;
my $hum2_const = &human2.new;
my $c = $hum2_const();
$c.fn1();
Essentially I want to be able to use either the human1 constructor or human2 constructor to be able to build $c object dynamically. But I'm getting the following error:
Error while compiling /usr/bhaskars/code/perl/./a.pl6
Illegally post-declared types:
human1 used at line 23
human2 used at line 24
How do I create $c using the function pointers to choose which constructor I use?
I think this is a case of an LTA error. What I understand you want to achieve, is a lambda that will create a new human1 or human2 object for you. The way you do that is not correct, and the error it causes is confusing.
my $hum1_const = -> { human1.new };
my $hum2_const = -> { human2.new };
would be a correct way of doing this. Although, I would consider this a bit of an obfuscation. Since human1 and human2 are already constants, you can assign them to a variable, and then just call new on that:
my $the_human = $condition ?? human1 !! human2;
my $c = $the_human.new;
$c.fn1;
Does that make sense?
To get a “reference” to .new you have to use the meta object protocol.
Either .^lookup, or .^find_method.
my $hum1-create = human1.^find_method('new');
That is still not quite what you are looking for, as methods require either a class object or an instance, as their first argument.
my $c = $hum1-create( human1 );
So you would probably want to curry the class as the first argument to the method.
my $hum1-create = human1.^find_method('new').assuming(human1);
my $c = $hum1-create();
Note that .assuming in this case basically does the same thing as
-> |capture { human1.^find_method('new').( human1, |capture ) }
So you could just write:
my $hum1-create = -> |capture { human1.new( |capture ) }
Or if you are never going to give it an argument
my $hum1-create = -> { human1.new }
Also you can store it in a & sigiled variable, so you can use it as if it were a normal subroutine.
my &hum1-create = human1.^find_method('new').assuming(human1);
my $c = hum1-create;
Using DBIx::Class, I found a solution to my issue, thankfully. But I'm sure there has to be a nicer way.
my $record = $schema->resultset("food")->create({name=>"bacon"});
How would I turn this record into a simple hashref instead of having to make this call right after.
my record = $schema->resultset("food")->search({name=>"bacon"})->hashref_array();
Ideally I want to be able to write a code snippet as simple as
{record=> $record}
instead of
{record => {name => $record->name, $record->food_id, ...}}
This would drive me insane with a table that has alot more columns.
I assume you're talking about DBIx::Class?
my $record = $schema->resultset("food")->create({name=>"bacon"});
my %record_columns = $record->get_columns;
# or, to get a HashRef directly
my $cols = { $record->get_columns };
# or, as you've asked for
my $foo = { record => { $record->get_columns } };
What you're looking for is included in DBIx::Class as DBIx::Class::ResultClass::HashRefInflator.
I have a function that returns the value of a global variable. When I assign this result to a local variable, and changing the local value the another variable is changing too.
Example:
function setGlobal
{
$temp = #{}
$temp.id = 50;
$Global:global1 = $temp;
return $Global:global1;
}
then I call this function, and set the result value:
$result = setGlobal
$result.id = 80
now both variables has the same value.
$Global:global1 # id = 60
$result # id = 60
How can I prevent this from happening? And why does changing the local value will affect the global copy?
The reason is, of course, that you don't have two copies of the object. You have two references to the same object, a hashtable. The reference is copied, not the object. The object is like a house. The variables (global1 and result) are like pieces of paper. I write the address of the house on my piece of paper (global1) and then I copy the address onto your piece of paper (result). Then you go to the address you have and paint the door red. Now when I go to the address I have, and my house now has a red door.
Making a deep copy of an object is slightly easier than making a copy of a house. For an arbitrary object use PSObject.Copy():
function setGlobal
{
$temp = #{}
$temp.id = 50;
$Global:global1 = $temp;
return $Global:global1.PSObject.Copy();
}
In this case, this is exactly the same as Clone since PSObject.Copy uses Clone if it is available.
This is happening because powershell is implicitly using references. So $Global:global1 and $result end up pointing to the same place when you make the assignment.
To get a copy, use the .Clone() method:
$result = $Global:global1.Clone()
Or instead of doing that on assignment, do it in the return of the function:
function setGlobal
{
$temp = #{}
$temp.id = 50;
$Global:global1 = $temp;
return $Global:global1.Clone();
}
Is there a way to make a variable classname in javascript. In php the next is allowed:
$classname = "klasse";
$class = new $classname();
Tom
Use square bracket notation:
some_object["string_containing_method_name"]();
If you want to play with globals, then just remember they are all properties of the window object.
… but don't play with globals.
Your particular example:
var $classname = "klasse";
var $class = new window[$classname]();
(Obviously, the usual conventions for only using $ in machine generated code should apply too)
Bear in mind that "eval is evil", but if you are aware of this, then:
var classname= "klasse";
eval( "var obj = new " + classname + "();");
If you want to call something like
new acme.tools.Hammer();
Then do
var $toolName = "Hammer";
var myObject = new window['acme']['tools'][$toolName]();