I wrote a macro:
macro_rules! test {
($trait:tt<$($param:literal)+>) => {
{
println!("{}", stringify!($($param)++));
}
};
}
for the $param repeat separator, I couldn't use the + char which is the repeat 'op'.
The output looks like 1 2 3 + but how can I make it be 1 + 2 + 3 instead?
Related
The following code
macro_rules! test {
( $( $x1:expr ),*; blub $( $x2:expr ),* ) => {
$(
println!("{} * {} = {}", $x1, $x2, $x1 * $x2);
)*
}
}
fn main() {
test!{1, 2, 3; blub 4, 5, 6};
}
prints:
1 * 4 = 4
2 * 5 = 10
3 * 6 = 18
However I want to loop over both lists seperately like a nested loop. It should print:
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
How do I do that?
The only way I found was to cheat a little by using a token tree as one of the arguments like this:
macro_rules! test {
// secondary invocation with a `[]` delimited list of parameters
// as the first arguments and a single second argument.
( [ $( $x1:expr),* ] ; $x2:expr ) => {
$(
println!("{:?} * {:?} = {:?}", $x1, $x2, $x1 * $x2);
)*
};
// the main invocation of the macro, takes a token tree `x1`
// and a `[]` delimited `,` separated list of arguments for
// each of which it calls itself again with `x1` as first
// parameter and the element of the list as the second
( $x1:tt [ $( $x2:expr ),* ] ) => {
$(
test!($x1; $x2);
)*
};
}
fn main() {
test!{
[1, 2, 3]
[4, 5, 6]
};
}
You'll need to use a nested loop in some form or another because you need to iterate over x2 a variable number of times. You can expand each of your repeated tokens separately into an array, and loop over it the same way you would any iterable collection:
macro_rules! test {
( $($x1:expr ),*; blub $($x2:expr ),* ) => {
for x1 in [$($x1),*] {
for x2 in [$($x2),*] {
println!("{} * {} = {}", x1, x2, x1 * x2);
}
}
}
}
fn main() {
test!{1, 2, 3; blub 4, 5, 6};
}
macro_rules! retry_put {
($mod_name:ident, $data_type:ty) => {{
fn $mod_name() {
// somelike
if $mod_name == "red" {
// generate code written here and not the one in else block
return u8;
}
else {
// generate code written here and not the one in if
return "string";
}
}
}
}
I am tring to change the return type based on input basically, if input is true return string else return int.
Or maybe give example for :
give example where we are accepting a arguement in macro and if its even calulate factorial of 5 and return it as integer and if the agruement is odd calculate the factoreial of 5 and return it as string. And name of both functions should be same. and logic of calculating 5! should not be repeated.
You can overload a macro like this:
macro_rules! retry_put {
(red, $data_type:ty) => {{
fn red() {
return u8;
}
}
}
($mod_name:ident, $data_type:ty) => {{
fn $mod_name() {
return "string";
}
}
}
}
See macro_rules!.
#[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
I was dong hackerrank test. My code provides required output by providing input but test shows it is a wrong answer. The link for test is https://www.hackerrank.com/contests/fullstack/challenges/testrun
Input Format
1 2 3
Output Format
2 3 7
Sample Input
1 9 9
Sample Output
? ? ?
Explanation
function processData(input) {
//Enter your code here
var number;
var main = "";
const aray = input.split(' ').map(Number)
for (var i = 0; i < aray.length; i++) {
if (i === aray.length-1 && aray.length>1) {
if (aray[i]*2 + 1 >= 9) {
main += '?';
}
else {
main += aray[i]*2 + 1
}
}
else {
if (aray[i+1] >= 9) {
main += '?';
main += ' '
}
else {
main += aray[i] + 1;
main += ' '
}
}
}
console.log(main);
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = '';
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
How do I create test cases? If you know then please mention the mistake. Thanks
If you just want to test a bunch of inputs, then write a bunch of function calls with different types of input.
Example:
processData([1, 2, 3]);
processData([4, 5, 6]);
processData([2, 2, 2]);
processData(["1", "2", "3"]);
// More tests here
If you want to automate providing input into your application, then something like robotjs might be useful.
If you're looking for a full on testing framework, then you can use mocha and chai. Here's an article on how to use them with node.
#!/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.)