What's the best way to write a custom format! macro? - rust

I'm trying to create a custom crash! macro that essentially just wraps eprintln!, but it could be any other format!-like macro. It currently looks like this.
macro_rules! crash {
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $args);
std::process::exit(1);
}};
}
I can't use $args directly as it's still repeating, so I need some way to break it apart, but I'm not sure how to do that.

While your solution work, the best way to forward macro arguments is to capture them as tt. In your case, since all you want is to forward them, you can use $($t:tt)*:
macro_rules! crash {
($($t:tt)*) => {{
eprintln!($($t)*);
std::process::exit(1);
}};
}
This has the advantage that it is completely transparent and enables everything the underlying macro enables. For instance, in this case, the tt version supports early-expanded format string, while your original version does not (playground):
// crash!(concat!("a", "b")); // Does not compile
crash_tt!(concat!("a", "b"));

Turns out I was just having a mental blank, and ended up answering my own question. I just needed to expand $args... Just for anyone else who ends up here, the solution looks like this:
macro_rules! crash {
($fmt_str:literal) => {{
eprintln!($fmt_str);
std::process::exit(1);
}};
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $($args),*);
std::process::exit(1);
}};
}

Related

What's the functional approach to replace this match block?

What's the functional approach to replace the below match?
match second_db.player_create(player_id).await {
Ok(o) => Ok(o),
Err(err) => {
first_db.player_delete(player_id).await?;
Err(err)
}
}
As others have pointed out, the usual helper methods on Result and Option do not work with async (see links below). However, these methods are mostly about transforming the Result / Option which you are not doing. Hence, your code could be rephrased to the following (assuming you want to return the result of the match expression):
let result = second_db.player_create(player_id).await;
if result.is_err() {
first_db.player_delete(player_id).await?;
}
result
This omits the "mapping" part of both branches and is, in my opinion, easier to understand.
Related discussions:
How to use async/await inside closure of `Option::and_then` or `Option::map` without using OptionFuture?
https://users.rust-lang.org/t/how-to-run-async-code-within-option-result-function-chain/64053

How can I match a single condition in Rust; 'match', 'if matches!', or 'if let'?

I want to check a condition that depends only on its structure (but not the actual values it holds), and do something in either case. I can think of three ways do this: with match, if let, or if matches!. I'm not sure if there are any drawbacks to any of these or if they are effectively equivalent.
Am I safe to use any of these or are there known drawbacks that I might run into with one or more of these? Is there a fourth way that I haven't thought of?
match self.context.get(s) {
Some(Bound::Function(_, _)) => Err("Parse Error".to_string())
_ => {
self.context.insert(s.clone(), ...);
Ok(None)
}
}
if let Some(Bound::Function(_, _)) = self.context.get(s) {
Err("Parse Error".to_string())
}
else {
self.context.insert(s.clone(), ...);
Ok(None)
}
if matches!(self.context.get(s), Some(Bound::Function(_, _))) {
Err("Parse Error".to_string())
}
else {
self.context.insert(s.clone(), ...);
Ok(None)
}
Your three solutions are equivalent. As of today they even compile to the same machine code: https://godbolt.org/z/d4acvY5G3
Performance-wise, you would need to benchmark but I suspect that the fastest would be to use the entry API. Something along the lines of:
match self.context.entry (s) {
Entry::Occupied (_) => Err("Parse Error".to_string()),
Entry::Vacant (e) => {
e.insert (Bound::Number(evaluate(&self.context, parseadd(tokens))?));
Ok (None)
}
}
Note that depending on the rest of your code, this solution might require to always clone s whereas yours don't clone it if the entry already exists. However:
Your solutions only avoid cloning when an error occurs, which should be a rare occurrence and less performance-sensitive than the non-error case.
If performance is really an issue, it would probably be best to avoid cloning altogether if possible (but that depends on where s comes from).
As with all performance-related questions, you should measure it in your environment to see if it brings any significant improvement (and you should only try to improve it after you have shown that it is a performance bottleneck for your application).

How can I best pattern match in Result::map

I know I can pattern match like this in rust
some_result.map(|some_number| {
match some_number {
1 => HttpResponse::NoContent().finish(),
_ => HttpResponse::NotFound().finish(),
}
})
but in Scala I can do like this
some_option.map {
case 1 => ???
case _ => ???
}
Is there a way to avoid the repetition of the variable some_number in the rust code above?
EDIT:
I found out i could do it this way, but i still think the original question answered my question best.
Ok(match result {
Ok(1) => HttpResponse::NoContent(),
Ok(_) => HttpResponse::NotFound(),
Err(_) => HttpResponse::InternalServerError()
}.finish())
its all about the context and in this case i didnt include much of it ...
EDIT #2:
Changed to another answer. I really like inverting the problem. And if else is not idiomatic rust afaik.
If we're just bike-shedding style, you could avoid introducing some_number entirely by matching on the whole result:
match some_result {
Ok(1) => Ok(HttpResponse::NoContent().finish()),
Ok(_) => Ok(HttpResponse::NotFound().finish()),
Err(e) => Err(e)
};
But this just trades some_number for some Oks and Errs. I would generally prefer the original style, but beauty is in the eye of the beholder.
There is no way that I know of to avoid the repetition, however I think it might be more idiomatic to simply write
some_result.map(
|some_number|
if some_number == 1 {
HttpResponse::NoContent().finish()
} else {
HttpResponse::NotFound().finish()
}
)
since there is no need for a match in such a simple situation.
EDIT: Why is an if statement more idiomatic than a match on in this situation?
The general idea is that match is more powerful than if (every if statement could be replaced by a match statement), therefore if is more specific, and thus should be used when possible (without matches!). The only exception is the switch/case use-case, which could be expressed as an if statement but a match one should be used.
But this is more of a guideline than an argument, so let's break down the reason why if is more idiomatic.
You start with something like
match some_number {
1 => { ... }
_ => { ... }
}
In the situation of
match x {
Pattern => { ... }
_ => { ... }
}
if let is more idiomatic. Since we're in this situation, we can rewrite
if let 1 = some_number { ... } else { ... }
However, in our case, we are matching a single literal, so it is more idiomatic to simply transform the if let into
if some_number == 1 { ... } else { ... }
The only exception is when you are planning to add more branching to the match statement, like
match some_number {
1 => { ... }
2 => { ... }
_ => { ... }
}
in which case it would make sense to keep it like that.
Keep in mind that being idiomatic also means being able to convey by the way you code your intention so that your programming becomes clear.
Note: Why is this more idiomatic than than simply matching the whole result?
Most of the time, being idiomatic is a synonym of being concise. If you are being verbose, it's a good hint you're not being idiomatic. However, it'is not always true, and this is a good example of being idiomatic meaning being more verbose.
When you are matching a result, you are expressing that you want to handle both the error and the ok case. When you are mapping, you are instead expressing that you are only interested in the ok case.
Most of the time, people don't want to handle manually the error case, and just add a ?. However, when they don't, most of the time they want to handle the error case. Finally, they might want not to handle the error, but also not to get rid of it right away.
These three choices are increasingly verbose to implement due to the frequency of usage. This means that you should not aim for the one that is less verbose, but instead for the solution that matches your intention, so that when one reads your code, it's easier to grasp your intention just by your choice structure of implementation.
In your original question, you seemed not to care about the error case, and also you didn't seem to want to get rid of it with ?, which is why I think that having an if statement inside a map is more idiomatic, in the sense that it is more clear and communicates better what you want to achieve. Indeed, I didn't even think about the error case, which is, IMO, what idiomatic means (ie. the capacity of adapting the way one thinks to ease the comprehension of code by writing it in the most expressive way, for a given language).
Finally, I would point out the most idiomatic choice for handling an error, that you didn't seem to take into account, and I wonder why.
if some_result? == 1 {
HttpResponse::NoContent().finish()
} else {
HttpResponse::NotFound().finish()
}
Where you have implemented an appropriate conversion from the eventual error type to the return type.

Twig function/filter with no input?

I'm using Slim 3 and Slim Twig-View. I want to add a Twig function (or filter, not sure what is the difference?) which generates a random string, and doesn't take any input.
I was able to add a filter like this:
$twig->getEnvironment()->addFilter(
new \Twig_Filter('guid', function(){ return generateGUID(); })
);
But I can't seem to use it without providing some dummy input:
{{ 0|guid }} This will work
{{ guid }} This will not work
How can I use my guid filter/function without providing any input?
A filter always apply on something, it filters something.
What you want is a function, indeed.
The extending Twig page of the documentation is an incredible source of information on that matter.
At first glance, I would even have said you should define a tag for this but the documentation on the tag, explicitly says:
If your tag generates some output, use a function instead.
Source: https://twig.symfony.com/doc/3.x/advanced.html#tags
So indeed, in order to define a function:
Functions are defined in the exact same way as filters, but you need to create an instance of \Twig\TwigFunction:
$twig = new \Twig\Environment($loader);
$function = new \Twig\Twig_Function('function_name', function () {
// ...
});
$twig->addFunction($function);
So more specifically for you:
$container->get('view')->getEnvironment()->addFunction(
new Twig_SimpleFunction('guid', function(){ return generateGUID(); })
);
Will be accessible via:
{{ guid() }}
Other worth reading:
extending twig, in Slim documentation
you can achieve the same with a macro

How can I make this Rust code more idiomatic

Recently I started to learn Rust and one of my main struggles is converting years of Object Oriented thinking into procedural code.
I'm trying to parse a XML that have tags that are processed by an specific handler that can deal with the data it gets from the children.
Further more I have some field members that are common between them and I would prefer not to have to write the same fields to all the handlers.
I tried my hand on it and my code came out like this:
use roxmltree::Node; // roxmltree = "0.14.0"
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
let tag_handler: dyn XMLTagHandler = match tag_name {
"name" => NameHandler::new(),
"phone" => PhoneHandler::new(),
_ => DefaultHandler::new()
}
if tag_handler.is_recursive() {
for child in node.children() {
let child_value = get_data_from(&child);
// do something with child value
}
}
let value: String = tag_handler.value()
value
}
// consider that handlers are on my project and can be adapted to my needs, and that XMLTagHandler is the trait that they share in common.
My main issues with this are:
This feels like a Object oriented approach to it;
is_recursive needs to be reimplemented to each struct because they traits cannot have field members, and I will have to add more fields later, which means more boilerplate for each new field;
I could use one type for a Handler and pass to it a function pointer, but this approach seems dirty. e.g.:=> Handler::new(my_other_params, phone_handler_func)
This feels like a Object oriented approach to it
Actually, I don't think so. This code is in clear violation of the Tell-Don't-Ask principle, which falls out from the central idea of object-oriented programming: the encapsulation of data and related behavior into objects. The objects (NameHandler, PhoneHandler, etc.) don't have enough knowledge about what they are to do things on their own, so get_data_from has to query them for information and decide what to do, rather than simply sending a message and letting the object figure out how to deal with it.
So let's start by moving the knowledge about what to do with each kind of tag into the handler itself:
trait XmlTagHandler {
fn foreach_child<F: FnMut(&Node)>(&self, node: &Node, callback: F);
}
impl XmlTagHandler for NameHandler {
fn foreach_child<F: FnMut(&Node)>(&self, _node: &Node, _callback: F) {
// "name" is not a recursive tag, so do nothing
}
}
impl XmlTagHandler for DefaultHandler {
fn foreach_child<F: FnMut(&Node)>(&self, node: &Node, callback: F) {
// all other tags may be recursive
for child in node.children() {
callback(child);
}
}
}
This way you call foreach_child on every kind of Handler, and let the handler itself decide whether the right action is to recurse or not. After all, that's why they have different types -- right?
To get rid of the dyn part, which is unnecessary, let's write a little generic helper function that uses XmlTagHandler to handle one specific kind of tag, and modify get_data_from so it just dispatches to the correct parameterized version of it. (I'll suppose that XmlTagHandler also has a new function so that you can create one generically.)
fn handle_tag<H: XmlTagHandler>(node: &Node) -> String {
let handler = H::new();
handler.foreach_child(node, |child| {
// do something with child value
});
handler.value()
}
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
match tag_name {
"name" => handle_tag::<NameHandler>(node),
"phone" => handle_tag::<PhoneHandler>(node),
_ => handle_tag::<DefaultHandler>(node),
}
}
If you don't like handle_tag::<SomeHandler>(node), also consider making handle_tag a provided method of XmlTagHandler, so you can instead write SomeHandler::handle(node).
Note that I have not really changed any of the data structures. Your presumption of an XmlTagHandler trait and various Handler implementors is a pretty normal way to organize code. However, in this case, it doesn't offer any real improvement over just writing three separate functions:
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
match tag_name {
"name" => get_name_from(node),
"phone" => get_phone_from(node),
_ => get_other_from(node),
}
}
In some languages, such as Java, all code has to be part of some class – so you can find yourself writing classes that don't exist for any other reason than to group related things together. In Rust you don't need to do this, so make sure that any added complication such as XmlTagHandler is actually pulling its weight.
is_recursive needs to be reimplemented to each struct because they traits cannot have field members, and I will have to add more fields later, which means more boilerplate for each new field
Without more information about the fields, it's impossible to really understand what problem you're facing here; however, in general, if there is a family of structs that have some data in common, you may want to make a generic struct instead of a trait. See the answers to How to reuse codes for Binary Search Tree, Red-Black Tree, and AVL Tree? for more suggestions.
I could use one type for a Handler and pass to it a function pointer, but this approach seems dirty
Elegance is sometimes a useful thing, but it is subjective. I would recommend closures rather than function pointers, but this suggestion doesn't seem "dirty" to me. Making closures and putting them in data structures is a very normal way to write Rust code. If you can elaborate on what you don't like about it, perhaps someone could point out ways to improve it.

Resources