What does `::parse()` do on a struct? - rust

I'm learning rust, and the best way to learn a programming language is obviously reading and understanding other's code. Now I faced this line I am not able to understand even after reading docs, other source files and googling for it :
In zoxide's main file, there's this line :
if let Err(e) = App::parse().run() { ... }
What does App::parse() mean ? App is a structure and not a variable, so I understand why it's not .parse(), but why ::parse() and what does it do ? (I couldn't find its definition in app's source code (nor in this file))

First, both the files you mentioned are not the App that zoxide is including. zoxide's main.rs file says use crate::app::{App, Run};, so it's including App from src/app/mod.rs, which exports App from src/app/_app.rs
In that file, we can see the declaration of App:
#[derive(Debug, Clap)]
#[clap(
bin_name = env!("CARGO_PKG_NAME"),
about,
author,
after_help = ENV_HELP,
global_setting(AppSettings::ColoredHelp),
global_setting(AppSettings::DisableHelpSubcommand),
global_setting(AppSettings::DisableVersionForSubcommands),
global_setting(AppSettings::PropagateVersion),
version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
)]
pub enum App {
Add(Add),
Import(Import),
Init(Init),
Query(Query),
Remove(Remove),
}
The key in this case is #[derive(Clap)]. If you look at the clap crate you'll see that it's a crate for parsing command line parameters, and deriving from Clap adds a parse method to the structure.

Related

Optimizing Node.js Enum Elements using Webpack

I am working on a node.js project and have created pseudo-enum elements using an object literal as below:
export const Relation = { OTHER: '', FRIEND: 'fr', ENEMY: 'en' }
In my code, I am using the enum elements like this:
if (player.relation === Relation.ENEMY)
I am using webpack for compiling my code and I would like to know how I can compile the above code to get something like this:
if (player.relation === 'en')
If there is no way to do that, I would like to not compile unused enum fields.
I would appreciate if someone could guide me on how to achieve this.

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.

Defining a struct member with private module types

I've been using a bunch of modules that have a build() function which returns a struct. However, when I try to create my own "super" struct to bundle them together, I run into the error module `xxx` is private rustc(E0603). If there is a trait I can pass the individual variable as a parameter but cannot figure out how to define/box it up for a struct.
The current example of this I'm hitting is when creating a hyper client.
// Error due to privacy and cannot use the trait to define the member type
// Both the "hyper_rustls::connector" and "hyper::client::connect::http" modules are private.
struct SecureClient {
client: hyper::client::Client<
hyper_rustls::connector::HttpsConnector<hyper::client::connect::http::HttpConnector>>
}
// Works, but passing the client everywhere as an individual variable is not realistic.
fn use_client(client: hyper::client::Client<impl hyper::client::connect::Connect>) -> () {
()
}
let https_conn = hyper_rustls::HttpsConnector::new(4);
let client: hyper::client::Client<_, hyper::Body> = hyper::Client::builder().build(https_conn);
Being newish to Rust, I'm struggling to figure out what the proper jargon is for what I'm trying to do, let alone make it work. Links to any docs or code examples about this would be appreciated.
Thanks
I'm not sure what you want to do, but you can use the public re-export hyper_rustls::HttpsConnector instead of the private hyper_rustls::connector::HttpsConnector and the public re-export hyper::client::HttpConnector instead of the private hyper::client::connect::http::HttpConnector.
You can read about re-exports here: https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use

How to make typedef type accessible in multiple files?

typedef has great benefits, but I don't know how to include the same type in multiple files is haxe?
for example I need to use this type in a.hx and b.hx files:
typedef JsonControl = {
var name:String;
var type:String;
var user_answer:String;
var answer:Array<String>;
var htmlID:String;
}
how to do so?
It works like a regular class definition, so preferably you would define a package and save it as a .hx file. Then simply import it where you want to use it.
As another answer states, the rules for how haxe discovers typedefs is identical to how it finds classes.
Type-Named Module Files
The easiest way to share a type between multiple files in Haxe is to create a module named after that type. For example, suppose you are in package x and want to access the type MyType from multiple files. You would create the file x/MyType.hx and place MyType’s definition in x/MyType.hx. This file might look like this:
package x;
typedef MyType = {
id:String,
}
Module Sub-Types
If you want, you may place MyType in a differently-named file such as x/MySharedTypes.hx. If you do that, accessing it takes more work. To consume it in another file, you either need to have an import x.MySharedTypes statement or type the module-qualified name x.MySharedTypes.MyType (from a file in package x, you only need to type MySharedTypes.MyType). In this example, you might have:
x/MySharedTypes.hx:
package x;
typedef MyType = {
id:String,
}
x/MyFirstConsumer.hx:
package x;
import x.MySharedTypes;
class MyFirstConsumer {
var instance:MyType;
}
x/MySecondConsumer.hx:
package x;
class MySecondConsumer {
var instance:MySharedTypes.MyType;
}
Documentation
You may read further details in the page titled Module Sub-Types in the manual.

Declaring a map in a separate file and reading its contents

I'm trying to declare a map in a separate file, and then access it from my main function.
I want Rust's equivalent (or whatever comes closest) to this C++ map:
static const std::map<std::string, std::vector<std::string>> table = {
{ "a", { "foo" } },
{ "e", { "bar", "baz" } }
};
This is my attempt in Rust.
table.rs
use std::container::Map;
pub static table: &'static Map<~str, ~[~str]> = (~[
(~"a", ~[~"foo"]),
(~"e", ~[~"bar", ~"baz"])
]).move_iter().collect();
main.rs
mod table;
fn main() {
println(fmt!("%?", table::table));
}
The above gives two compiler errors in table.rs, saying "constant contains unimplemented expression type".
I also have the feeling that the map declaration is less than optimal for the purpose.
Finally, I'm using Rust 0.8.
As Chris Morgan noted, rust doesn't allow you to run user code in order to initialize global variables before main is entered, unlike C++. So you are mostly limited to primitive types that you can initialize with literal expressions. This is, afaik, part of the design and unlikely to change, even though the particular error message is probably not final.
Depending on your use case, you might want to change your code so you're manually passing your map as an argument to all the functions that will want to use it (ugh!), use task-local storage to initialize a tls slot with your map early on and then refer to it later in the same task (ugh?), or use unsafe code and a static mut variable to do much the same with your map wrapped in an Option maybe so it can start its life as None (ugh!).

Resources