Tuesday, May 28, 2019

Rust Closure - PART2

Rust Closure - PART2.html

Closure Rust - Cont…

FnMut Trait

This is a continuation of the previous post ( https://naveendavisv.blogspot.com/2019/05/what-is-closures-how-can-it-be-used-in.html) on closures in rust.
Last post we defined the closures as Fn(i32) -> i32 when we want to pass the closure to a function.
Fn trait borrows values from the environment immutably.
But now we will see what is FnMut? .
FnMut can change the environment because it mutably borrows values.
fn double(mut db1:T)
   where T:FnMut() -> i32 {
     println!("{:?}",db1());
  }

fn main() {

  let mut x = 10;
  let  db = || { x*=2; x};
  double(db);
  println!("{:?}",x);
}
The above example, the ‘x’ value will recalculated when we call the closure inside the function ( double)
If we want to change a value in the environment that closure is enclosing, the FnMut trait can be used to define the closure.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5102dff068bc256a59bc9c8c9bf3f92f

Cacher struct with closure.

We will try to build a Cacher Structure as explained in the rust book - https://doc.rust-lang.org/book/ch13-01-closures.html
The need for Cacher structure is explained in the book.
Final part of Cacher structure chapter , the author ask us to create the struct with HaspMap to store the calculated value
I will try to explain the Code wrote in Rust here.
How nice would it be if we can cache the computation intensive function and store it's calculated values in a struct !!
A data structure with a 'Closure' and 'Hashmap' will serve the purpose very nicely.

How do we define Cacher Structure with HashMap ?

We can call data structure as Cacher as it cache/store the result values.
Normally we don’t define the parameter type or return type of a Closure in Rust. But it is must to explicitly declare the field types of a Struct , so we need to explicitly define the 'T' where T is type of the Closure .Rust Compiler needs to understand all the field types of structures in order to allocate memory
resultMap field is Box (A pointer type for heap allocation - https://doc.rust-lang.org/std/boxed/struct.Box.html) reference to Hashmap.
If you don’t know how much memory you are going to use, one option would be “Box” type. Here we defined the field resultMao as Box reference to a HaspMap .
struct Cacher
  where T:Fn(u32) -> u32
  {
    square:T,
    resultMap:Box>,
  }

How do we implement the Cacher Struct ?

We defined the Cacher Struct , the next step would be we need to implement the Struct with methods.
one method that we would require is “new” . This method creates Objects of the Struct. Another one would be “value” - to get the value from the resultMap. As resultMap is reference to a HashMap , we can use “insert” method to add key and value pairs to the hashmap.
Also we can use “get” method to get a value for a key from the haspmap.
impl Cacher
  where T:Fn(u32) -> u32{
  fn new(square:T,mut resultMap: HashMap) -> Cacher{
    Cacher{
              square,
              resultMap:Box::new(resultMap),
           }
  }

  fn value(&mut self,x:u32) -> u32 {


     match self.resultMap.get(&x){
       Some(v) => *v,

       None    => {
                   let v = (self.square)(x);
                      self.resultMap.insert(x,v);
                   v
                  },
    }
  }
}

Rust Playground - https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d131716d3620b60521a2af2067a32dcd

Tuesday, May 21, 2019

What is a Closure ? How can it be used in Rust programming ? - PART1

Closures in Rust

Closure is record storing a function along with it environment variables. You can read about closures in wiki

Difference between Closure and a function.

function definition:
Note: we have to explicitly pass the type and variable.
fn add (x:u32) -> u32 { x +1 }

Closure definition in Rust:
Note: We can follow any one of the following syntax to define a Closure
//explicitly defining types
let add = |x:u32| -> u32 { x +1 }
or
//the compiler dynamically type the Closure variables
let add = |x| -> {x+1}
or
//ignoring curly braces if you have only one statement
let add = |x| -> x+1

We will go through some example for Closure and discuss its features

Example#1 - passing Closure to a function

Below example shows the closure is defined with parameter ’ x ’ passed from environment where it is called. Closure is enclosed in a variable called square_x here.
We can see that value of the variable x is 2 . In the main program, first we define the Closure and then it is called from square_x(x) in println! statement.
square_x is the Closure.
When Closure looks for it's required variable's 'x' value for calculation, Closure its self will be enclosed with its required variables and understand that 'x' is parameter and it need to get its value from lexical environment which is 2 . And it perform the calculation: x*x - square of 2 which is 4.

The second print statement execute inside the function square . When we call the square(square_x) function, Closure invoked and looks for its lexical environment and find the value for parameter ‘x’ variable.The ‘x’ variable value is 3 over there, so the Closure calculate the square of 3 which is 9 .

fn square<T>(sq:T)
 where T:Fn(i32) -> i32
  {
    let  x = 3;
    println!("square called from insidefn value = {}",sq(x));
  }

fn main() {

    let mut x = 2;
    let square_x  =  |x| x*x;
    println!("square of x = {}",square_x(x));
   

    square(square_x);

}

From what we learned , Closure doesn’t need to specify it’s Parameters type or Return type. But in the (square) function definition, we explicitly defined ‘T’ as Fn(i32) -> i32.
Because for a function, it is necessary to define it's parameters type.

run in Rust Playground -
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c7dafb2aa3b7f7f83fc7490be6f30925

Example 2 # What will happen if we are not passing variable

This example we remove the passing parameter, to make the Closure as no-parameters.

let sq = || x*x;

But Closure has the property to get all its variables from its lexical environment . When you pass it to a function, it actually pass the Closure and along with variables enclosed.

fn square<T>(sq:T)
 where T:Fn() -> i32
  {
    let  x = 3;
    println!("square called from insidefn value = {}",sq());
  }

fn main() {
    let x = 2;    
    let square_x  =  || x*x;
    println!("square of x = {}",square_x());
    square(square_x);
 
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=adc2ce2cb7fc2f73ddee5e1cbfe10a9d

Example 3- What will happen if you pass different variable to Closure in the above example

fn square<T>(sq:T)
 where T:Fn(i32) -> i32
  {
    let  x = 3;
    println!("square called from insidefn value = {}",sq(x));
  }

fn main() {

    let x = 2;
    let square_x  =  |y| x*x;

    square(square_x);
    println!("square of x = {}",square_x(x));
}

Can you guess the output ?Hint : Closure is record which stores function along with its environment variables.
run the example above and check out the output.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7763c76893f87426f975db3eafab5e0f

Reference https://doc.rust-lang.org/rust-by-example/fn/closures.html

https://doc.rust-lang.org/book/ch13-00-functional-features.html

Friday, April 12, 2019

Concurrency in Rust programming language- PART1

rust concurrency

Concurrency in Rust - PART 1

As per Rust documentation, concurrency in Rust is Fearless concurrency. Handling concurrency in a safe and efficient way is one of the Rust goal. The Ownership is the back bone of rust concurrency.

Concurrency means multiple computations at the same time.

  • In fact, concurrency is essential part of modern programming

eg > websites should handle multiple users at the same time
Graphical user interface need to do some background work when users are not interrupting the screens.
Multiple applications needs to run on the cloud (server)
Travel reservation system
Many algorithms can be broken down to concurrent parts -
merge sort
quick sort
summing a list by summing fragments in parallel

Concurrency can be achieved in Hardware level and software level. Here we will be talking about software concurrency and what makes Rust an efficient programming language to handle this.

Hardware examples:

  • A single processor can have multiple execution pipelines (but only one set of registers)
  • A processor can have multiple cores (multicore)
  • A computer can have multiple processors
  • A network can have multiple computers (Grid computing happens on these)
  • An internet has multiple networks
  • All combinations of the above

Software examples:

  • Multiprogramming, or running a lot of programs concurrently (the O.S. has to multiplex their execution on available processors). For example:
    • downloading a file
    • listening to streaming audio
    • having a clock running
    • chatting
    • analyzing data from some weird experiment
    • streaming a movie

Two Models for Concurrent Programming

  • Shared Memory - In this case, the same memory will be shared amount the processors /threads or programs.
    A and B programs can be trying to use the same object .
    A and B threads can be using the same file system that they can read and write. etc…
  • Message passing -
    There will be a transmitter and a receiver in this model. They communicate each other through a communication channel. Modules sends the messages and the incoming messages will be queued up for modules.
    A web browser and web server communication is an example. Web browser client request for a connection and web page, the server sends the data back to browser.

Jumping directly into Rust concurrency

Process. A process is an instance of a running program that is isolated from other processes on the same machine. In particular, it has its own private section of the machine’s memory.
Thread. A thread is a locus of control inside a running program. Think of it as a place in the program that is being run, plus the stack of method calls that led to that place to which it will be necessary to return through.
Threads are automatically ready for shared memory, because threads share all the memory in the process. It needs special effort to get “thread-local” memory that’s private to a single thread. It’s also necessary to set up message-passing explicitly, by creating and using queue data structures.

use::std::thread;

fn main() {

// spawning a new thread
    let handle = thread::spawn(||{
        loop {
                println!("thread1");
        }
    });

//looping the main thread
    loop{
        println!("thread2");
    }


}

thread::spawn function creates the new thread and returns a handle to it. The parameter would be a closure . Here it is an infinite loop that prints thread1.
You will see thread1 and thread2 printing in the screen. Unfortunately I could not get thread2 in the screenshot!

Thread 1 and Thread 2

For listing the threads running under the process, you can use below command in linux
get the process id using command
ps -e
then use top -H -p processid
The memory and CPU usage for each threads can be listed using above command.

threads in linux Rust programming

Run the below code and see the output …
The program just print “hello world”. It will not wait for the inner thread to complete and print the vector.

use::std::thread;
fn main() {
    let v = vec![1,2,3];
    let handle = thread::spawn(||{
                println!("{:?}",v);
    });
//    handle.join().unwrap();
    println!("Hello, world!");
}

Now remove comments (//) from handle.join().unwrap(); and run the program. You would assume the main thread wait for the inner thread to print the vector values as handle.join() makes main thread to wait/join with inner thread.

But,
We do get a compile time error . The error says the variable vector “v” does not live long enough. If the main thread complete without waiting for inner thread to complete (as we are seen above). The borrowed vector points to wrong memory when its tries to execute. Here Rust help us.

Rust compiler caught that scenario and threw an error .

   Compiling concurrent-proj2 v0.1.0 (/home/naveen/rustprojects/concurrent-proj2)
error[E0597]: `v` does not live long enough                                                                                                    
  --> src/main.rs:11:19                                                                                                                        
   |                                                                                                                                           
10 |     let handle = thread::spawn(||{                                                                                                        
   |                                -- value captured here                                                                                     
11 |         println!("{:?}",v);                                                                                                               
   |                         ^ borrowed value does not live long enough                                                                        
...                                                                                                                                            
16 | }                                                                                                                                         
   | - `v` dropped here while still borrowed

We can use the move keyword to transfer the ownership of the variables that we are going to use in the inner thread from the environment.

Below program prints both vector values and helloworld.

use::std::thread;
fn main() {
    let v = vec![1,2,3];
    let handle = thread::spawn(move ||{
                println!("{:?}",v);
    });

   handle.join().unwrap();
    println!("Hello, world!");
}
    

Threads Flow diagram

vector 'v'
handle
main thread
inner thread
main thread
handle.join - wait for the inner thread to finish
main thread get completed

Wednesday, March 13, 2019

Have you heard about Competitive programming ?

---

Competitive Programming

If you are looking for job in Google,Amazon or facebook as programmer or developer/designer, definitely you will be familiar with the word "Competitive programming ".

I thought of sharing some of my thoughts on "competitive programming ".
As per wikipedia - Competitive programming is a mind sport usually held over the Internet or a local network. https://en.wikipedia.org/wiki/Competitive_programming

As per definition it’s a “sports”

I heard about hackerrank 3 or 4 years back. I got surprised seeing the success of hackerrank. Definitely its very useful website those who are trying to understand different algorithms/concepts/problems in computer science. After that there was a rain of similar websites … Codechef, CodeByte etc …etc … I don’t know which one of these came first.

But I would suggest nothing harm in login those websites and try to solve some of the problems . Don’t get disappointed /discouraged if you are not able to solve the questions. you don’t need to be a competitive programmer to be a programmer.

I am not huge fan of competitive programming. But it improves your programming skill in multiple perspective and definitely you might need to have this skill for getting into Product based Software companies like Google, Amazon and facebook etc . When I started trying to solve some of the problems in code force , I thought I would require PHD in mathematics to understand the problems . Most of them will be really tough mathematical problems. But if you start from easy , medium and then to difficult once, I hope you won’t need to run away from it :-)

Let me start with advantages of Competitive programming

  • You are going to get good understanding on the Algorithms and data structures .

  • You will get to know different areas in computer science - number theory,set theory,graph theory,string analysis etc. If you ask me , Are these mathematics subjects? I would need to say “YES”. But the fact is you need to have good understanding on these areas in order to develop something unique. ( This is debatable subject) , you can develop innovative or useful applications without much deep understanding on these areas.

  • definitely it’s a plus point for you to get into Software companies.

  • This gives you the ability to approach problems in different ways and helps to get the optimized one.

  • Definitely you will come to time complexity O(n) and space complexity in computer programming :-)

  • Some of the competitive programming sites gives you only limited time to solve the problem. When you start solving the problems in time bound question ,this helps a lot in interviews. You will be able to face the software companies interviews more efficiently.

I think I wrote some advantages , so let me mention some of the websites you can try this .

In my opinion you don’t need to be competitive programmer to become a programmer/developer.

Competitive programming Drawbacks:

  • First of all , its not a technology or programming style or skill that every programmer is needed. Everybody know we need good algorithms to perform the program well. Reading,writing,debugging programs will makes you skillful programmer. Sometimes competitiveness makes to take decision immediately or jump into conclusion quickly.

  • For getting into competitive programming there are some prerequisites - good mathematical knowledge, Computer languages that the websites are using, good knowledge in computer science concepts.

  • If you are trying to learn a programming language from basics (eg: C programming ), I don’t think those sites are the starting point. Those who are good in C, C++,python etc languages , these websites will be a good place to play around.

  • Competitive programming will not take you to most of the computer applications areas .
    eg: Those who are interested in embedded systems , will not get any knowledge on peripheral or architecture of the micro controller/processor from this. or those who are all interested website designing and development not going to get much from competitive programming apart from understanding on the algorithms or logical thinking.

  • Nowadays Application building is like “building blocks” game. More you know about libraries and modules on the area, you will be succeeded in building some good applications.

  • Software life cycle is totally different - As you know it start with requirement gathering,designing,coding,unit testing, functional testing and User acceptance testing and deployment etc. I don’t see competitive programming give much importance to designing and collaboration and testing.

  • If you look at object oriented programming or functional programming , they are a programming style that every programmer should be aware of .

  • You can build innovative applications without competitive programming skills.

Conclusion

Please don’t consider Competitive programming as waste of time. It will definitely improve knowledge on algorithms and computer theories. Keep improving your programming skill on competitive perspective as well. Also be ware of that there are lot of other areas in programming where we can focus on application building or we can playground. As I said earlier You don’t need to be competitive programmer to be developer/programmer.

Please share your thoughts and comments. Thanks!