Hash equality in Crystal specs - specifications

I'm getting:
Expected: {text: "Hello World"}
got: {:text => "Hello World"}
When the key is a symbol.
And
Expected: {text: "Hello World"}
got: {"text" => "Hello World"}
When the key is a string.
How can I output {text: "Hello World"}?
My code:
#output = {} of Symbol => Output'
#output[name] = #buffer # name is a Symbol
language.parse("Hello World").should eq({ text: "Hello World" })
And to use a string I do:
#output = {} of String => Output'
#output[name.to_s] = #buffer # name is a Symbol

Essentially, {text: "Hello World"} is a NamedTuple, so you're comparing a Hash to a NamedTuple. What you need is {:text => "Hello World"} or {"text" => "Hello World"}. See the docs of Hash for details.

Related

Perl: How do I print the result of an Array of Hashes onto the body of an e-mail

I have some data stored in an array of hashes, and I am trying to print the results onto the body of the email being sent. Results will print on the command line when the script is ran, however the body of the email will remain blank.
sub DailyInflow {
my #inflow = SQLTableHash("select count(FOO), count(BAR), BAZ from table1 where days in (0,1) group by BAZ", $reportdbh);
foreach my $inflow (#inflow) {
print $inflow->{"BAZ"} . ": " . $inflow->{"COUNT(FOO)"}."\n";
print "Total: " . $inflow->{"COUNT(BAR)"} . "\n";
}
}
################### Send E-mail with CSV Attachment ##################
print "Sending Email ... \n" if $ENV{DEBUG};
my $subject = "Snapshot $reportdate";
SendEmail({
FROM => 'user#email.com',
TO => $args{EMAIL},
SUBJECT => $subject,
BODY =>DailyInflow()
ATTACHFILES => [{
Type => 'BINARY',
Path => "$fullzipname",
Disposition => 'attachment',
Filename => "$zipname",
}],
});
Your DailyInflow() subroutine should look like this:
sub DailyInflow {
my #inflow = SQLTableHash("select count(FOO), count(BAR), BAZ from table1 where days in (0,1) group by BAZ", $reportdbh);
my $string;
foreach my $inflow (#inflow) {
$string .= $inflow->{"BAZ"} . ": " . $inflow->{"COUNT(FOO)"}."\n";
$string .= print "Total: " . $inflow->{"COUNT(BAR)"} . "\n";
}
return $string;
}
But you can simplify it by interpolating variables within double-quoted strings.
sub DailyInflow {
my #inflow = SQLTableHash("select count(FOO), count(BAR), BAZ from table1 where days in (0,1) group by BAZ", $reportdbh);
my $string;
foreach my $inflow (#inflow) {
$string .= "$inflow->{'BAZ}: $inflow->{'COUNT(FOO)'}\n";
$string .= "Total: $inflow->{'COUNT(BAR)'}\n";
}
return $string;
}

try to print mixed hash element in perl

I try to print hash key and value in tree form. my perl code is given below.
use strict ;
use warnings ;
my %hash = (
first => {
a => "one",
b => "two",
c => "three",
},
second => {
d => "four",
e => "five",
f => "six",
},
third => "word",
);
foreach my $line (keys %hash) {
print "$line: \n";
foreach my $elem (keys %{$hash{$line}}) {
print " $elem: " . $hash{$line}->{$elem} . "\n";
}
}
output error message:
second:
d: four
f: six
e: five
third:
Can't use string ("word") as a HASH ref while "strict refs" in use at C:\Users\Dell\Music\PerlPrac\pracHash\hshofhsh_net.pl line 19.
here, under third key value not print. how can i do it?
You can't dereference a string ($hash{third}, i.e. word). You can test whether a particular scalar is a reference or not using ref:
for my $line (keys %hash) {
print "$line: \n";
if ('HASH' eq ref $hash{$line}) {
for my $elem (keys %{ $hash{$line} }) {
print " $elem: $hash{$line}{$elem}\n";
}
} else {
print " $hash{$line}\n";
}
}

Perl Hash by reference

so I'm trying to write a subroutine that takes a hash parameter and adds a couple key-value pairs to it (by reference). So far, I've got this:
addParams(\%params);
sub addParams
{
my(%params) = %{$_[0]}; #First argument (as a hash)
$params{"test"} = "testing";
}
But for some reason, It doesn't seem to add the 'test' key. I am new to Perl, but isn't this how you pass a hash by reference? Thanks beforehand.
You can use the hash-ref without de-referencing it:
addParams(\%params);
sub addParams
{
my $params = shift;
$params->{"test"} = "testing";
}
EDIT:
To address your code's issue, when you do:
my(%params) = %{$_[0]};
You're actually making a copy of what the ref points to with %{...}. You can see this via a broken down example (no function, same functionality):
my %hash = ( "foo" => "foo" );
my %copy = %{ \%hash };
$hash{"bar"} = "bar";
$copy{"baz"} = "baz";
print Dumper( \%hash );
print Dumper( \%copy );
Run:
$ ./test.pl
$VAR1 = {
'bar' => 'bar',
'foo' => 'foo'
};
$VAR1 = {
'baz' => 'baz',
'foo' => 'foo'
};
Both hashes have the original 'foo => foo', but now each have their different bar/baz's.

Use of uninitialized value in concatenation (.) or string in slapd_ munin plugin

I'm trying to implement the slapd_ munin plugin which is written in perl which I'm pretty much clueless about. The full plugin is available here. The error I'm getting is this one:
Use of uninitialized value in concatenation (.) or string at
/etc/munin/plugins/slapd_localhost line 232, <DATA> line 275.
Line 232 is this one:
my $searchdn = $ops{$action}->{'search'} . "," . $basedn;
I tried debugging by outputing all the variables/objects as follows:
use Data::Dumper; # top of script
# [...]
print Dumper(%ops);
print "action = [$action]\n";
print "basedn = [$basedn]\n\n";
my $searchdn = $ops{$action}->{'search'} . "," . $basedn;
When I run it again here is what I obtain:
[...] # 15 other variables belonging to $ops
$VAR16 = {
'info' => 'The graph shows the number of Waiters',
'search' => 'cn=Waiters',
'desc' => 'The current number of Waiters',
'filter' => '(|(cn=Write)(cn=Read))',
'title' => 'Number of Waiters',
'label2' => {
'read' => 'Read',
'write' => 'Write'
},
'vlabel' => 'Waiters'
};
action = [localhost]
action = [cn=Monitor]
Use of uninitialized value in concatenation (.) or string at /etc/munin/plugins/slapd_localhost line 237, <DATA> line 275.
Since all the variables seem to be set, I really don't understand the error message I'm getting
Q: Can anybody advise on how debugging this script?
You should dump a reference to %ops, as in
print Dumper \%ops;
This will make the debug output clearer. To illustrate, consider the output of
#! /usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %h = (foo => { bar => 1 }, baz => { quux => 3 });
print "No reference:\n",
Dumper(%h),
"\n",
"Reference:\n",
Dumper(\%h);
Notice how you see the structure much more clearly in the latter half:
No reference:
$VAR1 = 'baz';
$VAR2 = {
'quux' => 3
};
$VAR3 = 'foo';
$VAR4 = {
'bar' => 1
};
Reference:
$VAR1 = {
'baz' => {
'quux' => 3
},
'foo' => {
'bar' => 1
}
};
You cut out a critical bit of the output. What's the value of $VAR15? Is it "localhost" or something else?
When you print $searchdn, what is its value?

Perl, "closure" using Hash

I would like to have a subroutine as a member of a hash which is able to have access to other hash members.
For example
sub setup {
%a = (
txt => "hello world",
print_hello => sub {
print ${txt};
})
return %a
}
my %obj = setup();
$obj{print_hello};
Ideally this would output "hello world"
EDIT
Sorry, I failed to specify one requirement
I should be able to do
$obj{txt} = "goodbye";
and then $obj{print_hello} should output goodbye
If you want the calling code to be able to modify the message in the hash, you need to return the hash by reference. This does what you asked for:
use strict;
use warnings;
sub self_expressing_hash {
my %h;
%h = (
msg => "hello",
express_yourself => sub { print $h{msg}, "\n" },
);
return \%h;
}
my $h = self_expressing_hash();
$h->{express_yourself}->();
$h->{msg} = 'goodbye';
$h->{express_yourself}->();
However, it's a bizarre concoction -- essentially, a data structure that contains some built-in behavior. Sounds a like an object to me. Perhaps you should look into an O-O approach for your project.
This will work:
sub setup {
my %a = ( txt => "hello world" );
$a{print_hello} = sub { print $a{txt} };
return %a;
}
my %obj = setup();
$obj{print_hello}->();
Close:
sub setup {
my %a = (
txt => "hello world",
print_hello => sub {
print $a{txt};
});
return %a;
}
my %obj = setup();
$obj{print_hello}->();