Here is the code:
struct A<'a, 'b> {
s1: &'a str,
s2: &'b str,
}
struct B<'a> {
s3: &'a str,
}
macro_rules! gen_fn {
( $name:ident, $param:ty, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $param< $($gen),+ >) {
todo!()
}
}
}
fn main() {
gen_fn!( op_a, A, <'a, 'b>);
gen_fn!( op_b, B, <'a> );
}
However this code can't compile because Rust consider $param as a single argument, and $gen is another argument, so it expect token , or ).
When I try to expand the macro, the code is generated as I expect:
fn op_a<'a, 'b>(param: A<'a, 'b>) {
$crate::panicking::panic("not yet implemented")
}
fn op_b<'a>(param: B<'a>) {
$crate::panicking::panic("not yet implemented")
}
Am I doing wrong or it is just unsupported.
You can use ident instead of ty, but only if you're not using paths (a::b):
macro_rules! gen_fn {
( $name:ident, $param:ident, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $param< $($gen),+ >) {
todo!()
}
}
}
If you're using paths, you can use a repeated ident:
macro_rules! gen_fn {
( $name:ident, $($param:ident)::+, < $($gen:tt),+ > ) => {
fn $name< $($gen),+ >(param: $($param)::+< $($gen),+ >) {
todo!()
}
}
}
Related
This question already has answers here:
How to use an array of keys to fetch the value from a Javascript object
(3 answers)
Closed 2 years ago.
I have an array of keys ['a', 'b', 'c', 'd'] and nested object { a: { b: { c: { d: '58' } } } }
How can get a value of nested object '58'?
I tried something like this, but I've got only value from one 'level'
const a = ['a', 'b', 'c', 'd']
const b = { a: { b: { c: { d: '58' } } } }
const getValue = (a,b) => { return Object.values(b).find(key => a[key] === b[key]) }
.reduce() method can help.
Call .reduce() on the array and pass object b as the initial value to the .reduce() method. Callback function of the .reduce() method should just return the result of acc[curr].
During the first call, acc will be the object b and curr will be the first element in the array, i.e. 'a'. So the first call to callback function will return b['a'], i.e. { b: { c: { d: '58' } } }.
const a = ['a', 'b', 'c', 'd'];
const b = { a: { b: { c: { d: '58' } } } };
const result = a.reduce((acc, curr) => acc[curr], b);
console.log(result);
This is a naturally recursive operation, so this is a perfect use case for a recursive function:
const getValue = (Target, [k, ...Kr]) =>
Kr.length > 0
? getValue(Target[k], Kr)
: Target[k];
const keys = ['a', 'b', 'c', 'd']
const obj = { a: { b: { c: { d: '58' } } } }
console.log(getValue(obj, keys));
But you could also use array reducers:
const getValue = (obj, keys) =>
keys.reduce((target, key) => target[key] ,obj);
const keys = ['a', 'b', 'c', 'd']
const obj = { a: { b: { c: { d: '58' } } } }
console.log(getValue(obj, keys));
Or just a regular for loop:
const getValue = (obj, keys) => {
let target = obj;
for (let k of keys) {
target = target[k];
}
return target;
}
const keys = ['a', 'b', 'c', 'd']
const obj = { a: { b: { c: { d: '58' } } } }
console.log(getValue(obj, keys));
b[a[0]][a[1]][a[2]][a[3]]
it will output 58
I'm not sure if your array a fixed size?
if the size is dynamic
Try
function getValue(a, b) {
let output = b;
for (let i = 0; i < a.length; ++i) {
output = output[a[i]];
}
return output;
}
match input_string {
func_that_returns_string(MyEnum::MyVariant1) => do_something(),
func_that_returns_string(MyEnum::MyVariant2) => do_something_else(),
_=> do_nothing(),
}
Here is an examples of the error message:
Error: expected tuple struct or tuple variant, found function func_that_returns_string
Well, you can do it using a match guard, which looks like x if condition =>
fn fun(variant: MyEnum) -> String {
match variant {
MyEnum::Variant1 => "String1".to_string(),
MyEnum::Variant2 => "String2".to_string(),
}
}
pub fn main() {
let s = "String2".to_string();
match s {
s if s == fun(MyEnum::Variant1) => do_something(1),
s if s == fun(MyEnum::Variant2) => do_something(2),
_ => {},
}
// prints 2
}
But either way it looks clumsy and I suggest you to revise your design.
I am using ngx-formly v: 5.5.10. I try to check if field is focused in the expressionProperties.
This is necessary for changing the value based on focus. Something like this:
expressionProperties: {
'model.testField': (m) => {
if (m.testField.value && testField.focus=true) {
return x;
} else {
return y;
}
}
}
Is there a formly built-in solution for checking focus in the expressionProperties?
Thanks for any help!
The field instance is passed as a third argument of the expression callback:
expressionProperties: {
'model.testField': (m, formState, field) => {
if (m.testField.value && field.focus === true) {
return x;
} else {
return y;
}
}
}
I need to create a json to use as body in an http.request. I'm able to build dynamically up the json, but I noticed a strange behavior when calling builder.toString() twice. The resulting json was totally different. I'm likely to think this is something related to a kind of buffer or so. I've been reading the documentation but I can't find a good answer. Here is a code to test.
import groovy.json.JsonBuilder
def builder = new JsonBuilder()
def map = [
catA: ["catA-element1", "catA-element2"],
catB:[],
catC:["catC-element1"]
]
def a = map.inject([:]) { res, k, v ->
def b = v.inject([:]) {resp, i ->
resp[i] = k
resp
}
res += b
}
println a
def root = builder.query {
bool {
must a.collect{ k, v ->
builder.match {
"$v" k
}
}
}
should([
builder.simple_query_string {
query "text"
}
])
}
println builder.toString()
println builder.toString()
This will print the following lines. Pay attention to the last two lines
[catA-element1:catA, catA-element2:catA, catC-element1:catC]
{"query":{"bool":{"must":[{"match":{"catA":"catA-element1"}},{"match":{"catA":"catA-element2"}},{"match":{"catC":"catC-element1"}}]},"should":[{"simple_query_string":{"query":"text"}}]}}
{"match":{"catC":"catC-element1"}}
In my code I can easily send the first toString() result to a variable and use it when needed. But, why does it change when invoking more than one time?
I think this is happening because you are using builder inside the closure bool. If we make print builder.content before printing the result (buider.toString() is calling JsonOutput.toJson(builder.content)) we get:
[query:[bool:ConsoleScript54$_run_closure3$_closure6#294b5a70, should:[[simple_query_string:[query:text]]]]]
Adding println builder.content to the bool closure we can see that the builder.content is modified when the closure is evaluated:
def root = builder.query {
bool {
must a.collect{ k, v ->
builder.match {
"$v" k
println builder.content
}
}
}
should([
builder.simple_query_string {
query "text"
}
])
}
println JsonOutput.toJson(builder.content)
println builder.content
The above yields:
[query:[bool:ConsoleScript55$_run_closure3$_closure6#39b6156d, should:[[simple_query_string:[query:text]]]]]
[match:[catA:catA-element1]]
[match:[catA:catA-element2]]
{"query":{"bool":{"must":[{"match":{"catA":"catA-element1"}},{"match":{"catA":"catA-element2"}},{"match":{"catC":"catC-element1"}}]},"should":[{"simple_query_string":{"query":"text"}}]}}
[match:[catC:catC-element1]]
You can easily avoid that with a different builder for the closure inside:
def builder2 = new JsonBuilder()
def root = builder.query {
bool {
must a.collect{ k, v ->
builder2.match {
"$v" k
}
}
}
should([
builder.simple_query_string {
query "text"
}
])
}
Or even better:
def root = builder.query {
bool {
must a.collect({ k, v -> ["$v": k] }).collect({[match: it]})
}
should([
simple_query_string {
query "text"
}
])
}
How can I collect all property paths in a large JSON file containing a specific case-sensitive value?
Here's an example:
JSON:
{
"level1": {
"level1node1": "hit",
"level1node2": "miss",
"level1node3": {
"level2node1" : {
"level3node1": "hit",
"level3node2": {
"level4node1": "miss",
"level4node2": "hit"
}
}
}
}
}
Search text (case-sensitive): "hit"
Return C# string array:
[ "level1.level1node1",
"level1.level1node3.level2node1.level3node1",
"level1.level1node3.level2node1.level3node2.level4node2" ]
I'd like to use JSON.NET to get an array of matching node paths.
This does the trick:
void AddPath(List<string> propertyPaths, JToken jToken, string searchForValue) {
if (jToken is JValue && ((JValue)jToken).Value != null && ((JValue)jToken).Value.ToString() == searchForValue) {
propertyPaths.Add(jToken.Path);
} else if (jToken is JProperty) {
((JProperty)jToken).Values().ToList().ForEach(_ => AddMatch(propertyPaths, _, searchForValue));
} else if (jToken is JObject || jToken is JArray) {
if (jToken.HasValues) {
jToken.Children().ToList().ForEach(_ => AddMatch(propertyPaths, _, searchForValue));
}
}
}