How to iterate fields of a shape in hacklang? - hacklang

Say I have a shape like this
$something = shape(
'some_key' => ...,
'another_key' => ...,
...
);
How can I iterate each field of the shape? I'm looking for something like this
foreach ($something as $key) {
...
}

Convert to a dict first with the built-in HH\Shapes::toDict then iterate:
foreach(HH\Shapes::toDict($something) as $k => $v) {
// ...
}

Related

Perl - multithreading on foreach loop:

I have a big code that somewhere in the middle of it, there's a foreach loop filling up some dictionaries. Each iteration is independant and fills those dictionaries with disjoint keys.
I'm trying to turn the "foreach" loop in the middle to multithreaded in order to decrease time.
In the following example, $a1, $b1 are the pointers to dictionaries.
I tried "thread::shared" this way:
my $a1 = {};
my $b1 = {};
my $c1 = {};
my $d1 = {};
# a lot of code using $a1 and $b1
share($a1);
share($b1);
share($c1);
share($d1);
my #threads;
foreach my $Inst ( sort keys %{ $a1->{ports} }) {
push( #threads, threads->create('some_func', $Inst, $a1, $b1, $c1, $d1, $e ...));
}
for my $thr (#threads) {
thr->join();
}
# all the other code
But I get an error of:
Invalid value for shared scalar at ...
Any ideas how to get the data-structures filled, but not that it would interfere with the code before and after the for-each loop?
It is not possible to make a hash shared after it has been created/declared without losing the data in the hash. Instead you could try use shared_clone() like this:
use feature qw(say);
use strict;
use warnings;
use threads ;
use threads::shared ;
use Data::Dumper qw(Dumper);
my %h1 = (a => 1, b => 2);
my %h2 = (c => 3, d => 4);
my $a1 = \%h1;
my $b1 = \%h2;
my $a1c = shared_clone($a1);
my $b1c = shared_clone($b1);
my $lockvar:shared;
my $nthreads = 3;
for ( 1..$nthreads ) {
threads->create('job_to_parallelize', $a1c, $b1c, \$lockvar ) ;
}
$_->join() for threads->list();
sub job_to_parallelize {
my ($a1, $b1, $lockvar) = #_;
{
lock $lockvar;
$a1->{a}++;
$b1->{d}++;
}
}
print Dumper({a1c => $a1c});
print Dumper({b1c => $b1c});
Output:
$VAR1 = {
'a1c' => {
'a' => 4,
'b' => 2
}
};
$VAR1 = {
'b1c' => {
'd' => 7,
'c' => 3
}
};

Expanding a recursive macro in rust, similar to serde_json but for HTML elements

#[macro_export]
macro_rules! reactant {
// Converts (function) {...} into element
( $f:ident $t:tt ) => {
{
let mut elem = HtmlElement::new($f);
reactant!(#expand elem $t);
elem
}
};
// Expands {...} and parses each internal node individually
( #expand $self:ident { $($t:tt),* } ) => {
$(
reactant!(#generate $self $t);
)*
};
// Takes a (function) {...} node, feeds it back recursively, and pushes it into parent
( #generate $self:ident $t1:tt $t2:tt) => {
{
$self.push_inner(reactant!($t1 $t2));
}
};
// Takes a literal and sets the parent internal to a string
( #generate $self:ident $l:literal) => {
{
$self.set_inner(String::from($l)).unwrap();
}
};
}
#[allow(unused_macros)]
#[cfg(test)]
mod tests {
use crate::html::types::*;
use crate::html::HtmlElement;
use crate::reactant;
#[test]
fn test() {
// Doesn't work, not expecting '{' after second div, although the first one works fine
let x = reactant!(div {
div {
"test"
}
});
// Works, outputs <div>thing</div>
let y = reactant!(div {
"hello",
"thing"
});
}
}
I am working on making an uncreatively named HTML library in Rust, and am also learning macros at the same time (the macro documentation is confusing). Part of the project is making a macro that generates HTML elements recursively to make a document, in a similar appearance to serde_json. The syntax is shown in the test cases. Basically, every HTML element (div, h1, etc.) is mapped to a function that outputs a struct that I have crafted for HTML elements. I managed to get the macro working in one way, but it only allowed for HTML children when I want it to also take literals to fill in, say, an h1 with a string (test case 1). Test case 2 shows where it doesn't work, and I am not understanding why it can't read the {.
Let's try to trace what happens when the macro is being expanded:
reactant!(div { div { "test" } });
This triggers the first rule: $f:ident $t:tt with:
$f set to div
$t set to { div { "test" } }
Which gets expanded to:
reactant!(#expand elem { div { "test" } });
I believe you intended the second step to trigger rule number 2: #expand $self:ident { $($t:tt),* } with:
$self set to elem
$t set to div { "test" }
Which would get expanded to:
reactant!(#generate elem div { "test" });
But div { "test" } is actually two tts and so can't be parsed by this rule (or by any other rule).
If my interpretation of your intentions is correct, you will need to have separate rules to handle each case and process the list iteratively:
// Expands {...} and parses each internal node individually
( #expand $self:ident { $t1:tt $t2:tt, $($tail:tt)* } ) => {
reactant!(#generate $self $t1 $t2);
reactant!(#expand $self { $($tail)* })
};
( #expand $self:ident { $t:tt, $($tail:tt)* } ) => {
reactant!(#generate $self $t);
reactant!(#expand $self { $($tail)* });
};
// Duplicate rules to handle the last item if it's not followed by a ","
( #expand $self:ident { $t1:tt $t2:tt } ) => {
reactant!(#generate $self $t1 $t2);
};
( #expand $self:ident { $t:tt } ) => {
reactant!(#generate $self $t);
};
Playground

How check if shape vector contains a shape with a certain value

shape x {
?'a' => ?string,
?'b' => ?string,
}
I have an array of shape x, And I am trying to see if any of the shapes have a value of 'hello' in field 'a'. How can i do so using built in functions?
function has_hello(vec<shape(?'a' => string, ?'b' => string)> $items): bool {
foreach ($items as $item) {
if (Shapes::idx($item, 'a') === 'hello') {
return true;
}
}
return false;
}
You can use Shapes::idx to get the value of an optional field. If you're looking for helper functions to iterate on arrays, check out the C\ namespace.

Perl hashes don't work as expected

#!/usr/bin/perl
sub f { {
a => 1,
b => 2
} }
sub g { {
%{f()},
c => 3,
d => 4,
} }
use Data::Dumper;
print Dumper g();
The above code outputs
$VAR1 = 'a';
$VAR2 = 1;
$VAR3 = 'b';
$VAR4 = 2;
$VAR5 = 'c';
$VAR6 = 3;
$VAR7 = 'd';
$VAR8 = 4;
despite in my understanding it should output
$VAR1 = {
'a' => 1,
'c' => 3,
'b' => 2,
'd' => 4
};
What is my misunderstanding?
The problem is that a pair of braces is ambiguous in Perl, and may be either a block or an anonymous hash
Because of the contents of the hash in your g (please use better names) perl has assumed that you are writing a code block, which is just a list of scalar values
Make it more explicit like this and your code will function as you expect
use strict;
use warnings 'all';
sub foo {
{
a => 1,
b => 2,
}
}
sub bar {
my $href = {
%{ foo() },
c => 3,
d => 4,
}
}
use Data::Dump;
dd bar();
output
{ a => 1, b => 2, c => 3, d => 4 }
The Perl language has ambiguities. Take for example
sub some_sub {
{ } # Is this a hash constructor or a block?
}
{ } is valid syntax for a block ("bare loop").
{ } is valid syntax for a hash constructor.
And both are allowed as a statement!
So Perl has to guess. Perl usually guesses correctly, but not always. In your case, it guessed correctly for f(), but not for g().
To fix this, you can give Perl "hints". Unary-+ can be used to do this. Unary-+ is a completely transparent operator; it does nothing at all. However, it must be followed by an expression (not a statement). { } has only one possible meaning as an expression.
+{ } # Must be a hash constructor.
Similarly, you can trick Perl to guess the other way.
{; } # Perl looks ahead, and sees that this must be a block.
So in this case, you could use
sub g { +{
%{f()},
c => 3,
d => 4,
} }
or
sub g { return {
%{f()},
c => 3,
d => 4,
} }
(return must also be followed by an expression if anything.)

Nested `each` loops in Groovy

Need guidance on the syntax of nested looping in groovy. How to use iterator to print values of (value of a.name, value of b.name) here?
List a
a.each {
print(it.name)
List b = something
b.each {
print(value of a.name, value of b.name)
}
}
List a
a.each { x ->
println(x.name)
List b = something
b.each { y ->
println(x.name + y.name)
}
}

Resources