Saturday, February 9, 2019

Rust macros are Amazing!!!

rust macro

Macros in Rust programming

Macros are a powerful feature in Rust programming language. Since it is compiled to syntax tree rather than string pre-processing, it has advantages over other language’s macro.

When I started with Rust macro, it was taking me to a new programming style altogether. You can easily convert the reusable part of your program to macros. It is called meta programming .

Declarative Macros

we are going to discuss only this type macro creation in this post.

Macros will try to match pattern passed , if it succeed the match proceed with code defined in curly brackets.

How to start with Rust macro: 

macro_rules! macroname{
 () => { }
}
macro_rules! = is the macro using in rust for creating 
'macro_name' = is the name you want to be for the macro which can be invoked by *'macro_name!'*
( ) => {}

 () is the sytax for pattern matching 
 {} is the place we need to enter the code to exceuted.
 

($x:expr) 
$x is Name or variable
expr is type to match for name
  • ident: an identifier. Examples: x; foo.
  • path: a qualified name. Example: T::SpecialA.
  • expr: an expression. Examples: 2 + 2; if true { 1 } else { 2 }; f(42).
  • ty: a type. Examples: i32; Vec<(char, String)>; &T.
  • pat: a pattern. Examples: Some(t); (17, 'a'); _.
  • stmt: a single statement. Example: let x = 3.
  • block: a brace-delimited sequence of statements. Example: { log(error, "hi"); return 12; }.
  • item: an item. Examples: fn foo() { }; struct Bar;.
  • meta: a “meta item”, as found in attributes. Example: cfg(target_os = "windows").
  • tt: a single token tree.



Macro custom print

macro_rules! print_new{
//in this example we are passing the expression which has only one value which will be stored in $x
 
 //we need to define name and designator 
 // here **$x** is Name or variable
 // **expr** is type to match for name
    ($x:expr) => (
        println!("value={}",$x);
    )
}


fn main() {
    print_new!(5);
}

In rust almost everything is expression .In the above example we passed the ‘expr’ as 5 where 5 designated as name


example 2:
In this example we formatted the pattern as x=> 10+10 which equivalent to x=>$x:expr where $x get the value of 20
macro expression passing


example3:
Here we are passing function name as Identifer to generate/define a function
macro - building function

example4:

macro -apply function to a range of numbers


example5:

macro with pass dentifiers(variables)

Reference

https://words.steveklabnik.com/an-overview-of-macros-in-rust

https://danielkeep.github.io/tlborm/book/index.html

https://danielkeep.github.io/practical-intro-to-macros.html

Wednesday, February 6, 2019

Sum type with Enum in Rust programming language


Enum - Enumeration

Enumeration as user defined data type and in C programming language its mainly used for names to integral constants .

C syntax: 
Enum state { success = 1, failed = 0 };
Enums has very limited usage in C language. But Rust has used all use cases for Enum and adopted lot of use cases from Functional programming languages like Haskell and ML.
Rust Enum Syntax:
enums are the best example for Sum types. If you want to restrict the input to any one of the types which defined , then they are called some types.

Say you have 'Shape' Type, and you know that shape can be only Circle ,Square or Rectangle. You  want to do action for each types separately. then you can go with Enum.

sum type aslo called Tagged Union, is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time, and a tag field explicitly indicates which one is in use.
The primary advantage of a tagged union/sum type over an untagged union is that all accesses are safe, and the compiler can even check that all cases are handled. 

Enum Shape{
        Circle(f32),
        Square(f32),
        Rectangle(f32,f32),
}





Enum example


Product type:

Struct is good example for product type. As we know, it is required to provide values for each types in a struct . It will be cartesian product of combinations we can make on struct types. It is must to provide value for each for defining an object. 




Importance of enum :

As I mentioned earlier, enum allows to define our own types which increase the readability
of the code as well as reduce the type issues in the programs.

For example , when we know we can only pass our defined type to function and if we can give a meaningful name for that type , which improve strength of the type system in our programs as well as improve the readability of the code.

if parent type consist of different child types, then it will be nice to use them with the hierarchy .Since it is not a product type, you can use one of them from parent at a time. For different type of input can do type validation and perform corresponding action.


Sunday, February 3, 2019

Building a Tree DataStructure in Rust programming language

Building Tree data structure gives more understanding on "Struct" and Box pointers in Rust.

Tree data structure is recurrences of Nodes of same Type where each Node normally will have  "value" field and Pointer pointer to the next node.

This is a little challenging to build the Tree in Rust as Rust won't allow to allocate recurring type as their memory space can not predetermined. But we can use  smart pointer BOX for it.

And implementing methods for the 'Tree' will be interesting.

Please find the problem and solution here in github,

https://github.com/davnav/rustgeeks/blob/master/tree_rust.md




Reference: https://matthias-endler.de/2017/boxes-and-trees/







Wednesday, December 26, 2018

Fundamentals of Webassembly

I was reading more on the WebAssembly last week.wrote about JavaScript in the last post, I don't know whether I have given wrong feeling that we should not study JavaScript at all. I did not meant that.In fact we should study JavaScript to understand more on the internals and browser JS engines .

The only thing I meant , we are in need finding alternative ways for more robust/new languages to replace JS drawbacks.

Web Assembly + Rust can offer some of the replacement for JS drawbacks. read more https://webassembly.org/


I don't know I know good enough to write this post, but still writing..


How to start with Web Assembly + Rust:


You can read webassembly+ rust on  https://rustwasm.github.io/book/why-rust-and-webassembly.html


In Ubuntu Linux machine probably we need the below steps to run webassembly with rust:

1. You need Rust tool chain: rustc, rustup and Cargo   . read the below link for rust tool chain - https://www.rust-lang.org/tools/install


2. wasm-pack - is a one shop for building testing Rust+webassembly applications.
 read about wasm-pack here https://rustwasm.github.io/wasm-pack/installer/

  wasm-pack has prerequisite for  Rust and npm. Since we installed rust in the above step, we only need npm to install ( if you haven't installed)

npm is a package manager for JavaScript. You can install it from https://www.npmjs.com/get-npm


You can get a project template with following ..

Clone a project template with this command:

cargo generate --git https://github.com/rustwasm/wasm-pack-template

you can follow below steps from the document to start with it .. https://rustwasm.github.io/book/game-of-life/hello-world.html




How to access Document elements(DOM ) using Webassembly+Rust

We need wasm_bindgen and web_sys libraries to access the DOM elements with Rust. You can read more about web_sys here -https://rustwasm.github.io/wasm-bindgen/api/web_sys/






Code: lib.rs

extern crate wasm_bindgen;
extern crate web_sys;

mod utils;

use wasm_bindgen::prelude::*;

use wasm_bindgen::JsCast;
use web_sys::{Document, Element, HtmlElement, Window};


#[wasm_bindgen(start)]
pub fn run() {
    using_web_sys();
}


fn using_web_sys()-> Result<(),JsValue>{
use web_sys::console;

console::log_1(&"Hellowrld to console using websys".into());

let window = web_sys::window().expect("no global window exists");
let document = window.document().expect("no document  found");

let body  = document.body().expect("document should have a body");


let val = document.create_element("p")?;

    val.set_inner_html("Hello from 121Rust!");
val.set_attribute("id","p1");
body.append_child(&val);
        let element = document
.get_element_by_id("p2").expect("no p2 element found");

let element1 = document
.get_element_by_id("p1").expect("no p1 element found");


let att = element.text_content().expect("no element text found");

let att1 = element1.text_content().expect("no element text found");
console::log_1(&att.into());

console::log_1(&att1.into());
    Ok(())

}

cargo.toml:

[package]
name = "na-rust-web"
version = "0.1.0"
authors = ["naveen "]

[lib]
crate-type = ["cdylib", "rlib"]


[dependencies]
cfg-if = "0.1.2"
wasm-bindgen = "0.2.29"
#web-sys = { version = "0.3.6", features = ['console'] }

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.1", optional = true }

# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.2", optional = true }

[dev-dependencies]
wasm-bindgen-test = "0.2.29"


[dependencies.web-sys]
version = "0.3.4"
features = [
  'Document',
  'Element',
  'HtmlElement',
  'Node',
  'Window',
  'console',
]
profile.release]
# Tell `rustc` to optimize for small code size.

opt-level = "s"