Saturday, April 23, 2022

Go vs Rust - Concurrency

 Go

Go has rich support for concurrency using goroutines and channels. 

Goroutines and Channels are a lightweight built-in feature for managing concurrency and communication between several functions executing at the same time. 

Goroutines

A goroutine is a function that is capable of running concurrently with other functions. To create a goroutine we use the keyword go followed by a function invocation:

package main
import "fmt"
func f(n int) {
  for i := 0; i < 10; i++ {
    fmt.Println(n, ":", i)
  }
}
func main() {
  go f(0)
  var input string
  fmt.Scanln(&input)
}

Channels

Channels provide a way for two goroutines to communicate with one another and synchronize their execution. Here is an example program using channels:

package main
import (
  "fmt"
  "time"
)
func pinger(c chan string) {
  for i := 0; ; i++ {
    c <- "ping"
  }
}
func printer(c chan string) {
  for {
    msg := <- c
    fmt.Println(msg)
    time.Sleep(time.Second * 1)
  }
}
func main() {
  var c chan string = make(chan string)
  go pinger(c)
  go printer(c)
  var input string
  fmt.Scanln(&input)
}

Channel Direction

We can specify a direction on a channel type thus restricting it to either sending or receiving. For example pinger's function signature can be changed to this:

func pinger(c chan<- string)

Now c can only be sent to. Attempting to receive from c will result in a compiler error. Similarly we can change printer to this:

func printer(c <-chan string)

A channel that doesn't have these restrictions is known as bi-directional. A bi-directional channel can be passed to a function that takes send-only or receive-only channels, but the reverse is not true.

Select

Go has a special statement called select which works like a switch but for channels:

The select statement is often used to implement a timeout. 

The default case happens immediately if none of the channels are ready.

select {
case msg1 := <- c1:
  fmt.Println("Message 1", msg1)
case msg2 := <- c2:
  fmt.Println("Message 2", msg2)
case <- time.After(time.Second):
  fmt.Println("timeout")
default:
  fmt.Println("nothing ready")
}

Buffered Channels

It's also possible to pass a second parameter to the make function when creating a channel:

c := make(chan int, 1)

This creates a buffered channel with a capacity of 1. Normally channels are synchronous; both sides of the channel will wait until the other side is ready. A buffered channel is asynchronous; sending or receiving a message will not wait unless the channel is already full.

Anonymous functions as goroutines

func main() {
fmt.Println("We are executing a goroutine")
arr := []int{2,3,4}
ch := make(chan int, len(arr))
go func(arr []int, ch chan int) {
for _, elem := range arr {
ch <- elem * 3
}
}(arr, ch)
for i := 0; i < len(arr); i++ {
fmt.Printf("Result: %v \n", <- ch)
}
}

Mutual exclusion

A problem that may arise when working with concurrency is when share the same resources, which shouldn’t be accessed at the same time by multiple goroutines.

In concurrency, the block of code that modifies shared resources is called the critical section.

package main
import (
"fmt"
"time"
)
var n = 1
var mu sync.Mutex
func timesThree() {
  mu.Lock()
defer mu.Unlock()
n *= 3
fmt.Println(n)
}
func main() {
fmt.Println("We are executing a goroutine")
for i := 0; i < 10; i++ {
go timesThree()
}
time.Sleep(time.Second)
}

Rust

Rust's memory safety features also apply to its concurrency story. Even concurrent Rust programs must be memory safe, having no data races. Rust's type system is up to the task, and gives you powerful ways to reason about concurrent code at compile time.

Send

The first trait we're going to talk about is Send. When a type T implements Send, it indicates that something of this type is able to have ownership transferred safely between threads.

This is important to enforce certain restrictions. For example, if we have a channel connecting two threads, we would want to be able to send some data down the channel and to the other thread. Therefore, we'd ensure that Send was implemented for that type.

Sync

The second of these traits is called Sync. When a type T implements Sync, it indicates that something of this type has no possibility of introducing memory unsafety when used from multiple threads concurrently through shared references. This implies that types which don't have interior mutability are inherently Sync, which includes simple primitive types (like u8) and aggregate types containing them.

For sharing references across threads, Rust provides a wrapper type called Arc<T>. Arc<T> implements Send and Sync if and only if T implements both Send and Sync. For example, an object of type Arc<RefCell<U>> cannot be transferred across threads because RefCell does not implement Sync, consequently Arc<RefCell<U>> would not implement Send.

These two traits allow you to use the type system to make strong guarantees about the properties of your code under concurrency.

Threads

The thread::spawn() method accepts a closure, which is executed in a new thread. It returns a handle to the thread, that can be used to wait for the child thread to finish and extract its result:

use std::thread;
fn main() {
    let handle = thread::spawn(|| {
        "Hello from a thread!"
    });
    println!("{}", handle.join().unwrap());
}

move closures

We can force our closure to take ownership of its environment with the move

use std::thread;
fn main() {
    let x = 1;
    thread::spawn(move || {
        println!("x is {}", x);
    });
}

Safe Shared Mutable State

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
    let data = Arc::new(Mutex::new(vec![1, 2, 3]));
    for i in 0..3 {
        let data = data.clone();
        thread::spawn(move || {
            let mut data = data.lock().unwrap();
            data[0] += i;
        });
    }
    thread::sleep(Duration::from_millis(50));
}

Channels

use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;
fn main() {
    let data = Arc::new(Mutex::new(0));
    // `tx` is the "transmitter" or "sender".
    // `rx` is the "receiver".
    let (tx, rx) = mpsc::channel();
    for _ in 0..10 {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            let mut data = data.lock().unwrap();
            *data += 1;
            tx.send(()).unwrap();
        });
    }
    for _ in 0..10 {
        rx.recv().unwrap();
    }





Friday, April 22, 2022

Go vs Rust - Strings

String

Go

In Go language, strings are different from other languages like Java, C++, Python, etc. it is a sequence of variable-width characters where each and every character is represented by one or more bytes using UTF-8 Encoding. Or in other words, strings are the immutable chain of arbitrary bytes(including bytes with zero value) or string is a read-only slice of bytes and the bytes of the strings can be represented in the Unicode text using UTF-8 encoding.

Due to UTF-8 encoding Golang string can contain a text which is the mixture of any language present in the world, without any confusion and limitation of the page.

    // Creating and initializing a slice of byte
    myslice1 := []byte{0x47, 0x65, 0x65, 0x6b, 0x73}
  
    // Creating a string from the slice
    mystring1 := string(myslice1)
    mystr := "Welcome to GeeksforGeeks ??????"
    // Finding the length of the string
    // Using len() function
    length1 := len(mystr)
  
    // Using RuneCountInString() function
    length2 := utf8.RuneCountInString(mystr)
    res1 := strings.Trim(str1, "@$")

Rust

There are two types of strings in Rust: String and &str.

A String is stored as a vector of bytes (Vec<u8>), but guaranteed to always be a valid UTF-8 sequence. String is heap allocated, growable and not null terminated.

&str is a slice (&[u8]) that always points to a valid UTF-8 sequence, and can be used to view into a String, just like &[T] is a view into Vec<T>.

let pangram: &'static str = "the quick brown fox jumps over the lazy dog";

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // Note that s1 has been moved here and can no longer be used
print!("{} ", s3);

let mut s = String::from("lo");
s.push('l');
let s2 = "bar";
s.push_str(&s2);
print!("{} ", s);

String Slices as Parameters

A more experienced Rustacean would write the following linebecause it allows us to use the same function on both Strings and &strs:

fn first_word(s: &str) -> &str {

The concepts of ownership, borrowing, and slices are what ensure memory safety in Rust programs at compile time. The Rust language gives you control over your memory usage like other systems programming languages, but having the owner of data automatically clean up that data when the owner goes out of scope.

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}
fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear(); // Error!
}

Bytes and Scalar Values and Grapheme Clusters

If we look at the Hindi word “नमस्ते” written in the Devanagari script, it is ultimately stored as a Vec of u8 values that looks like this:

[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164,
224, 165, 135]

That’s 18 bytes and is how computers ultimately store this data. If we look at them as Unicode scalar values, which are what Rust’s char type is, those bytes look like this:

['न', 'म', 'स', '्', 'त', 'े']
There are six char values here, but the fourth and sixth are not letters: they’re diacritics that don’t make sense on their own. Finally, if we look at them as grapheme clusters, we’d get what a person would call the four letters that make up the Hindi word:

["न", "म", "स्", "ते"]

If we need to perform operations on individual Unicode scalar values, the best way to do so is to use the chars method.

for c in "नमस्ते".chars() {
    println!("{}", c);
}

Indexing into a string is often a bad idea because it’s not clear what the return type of the string indexing operation should be: a byte value, a character, a grapheme cluster, or a string slice. Therefore, Rust asks you to be more specific if you really need to use indices to create string slices.

let hello = "Здравствуйте";
let s = &hello[0..4];

s will be a &str that contains the first four bytes of the string. Earlier, we mentioned that each of these characters was two bytes, which means s will be Зд.
What would happen if we used &hello[0..1]? The answer: Rust will panic at runtime. So should use ranges to create string slices with caution, because it can crash your program.

Escape character

Go

Escape character Description
\\ Backslash(\)
\000 Unicode character with the given 3-digit 8-bit octal code point
\’ Single quote (‘). It is only allowed inside character literals
\” Double quote (“). It is only allowed inside interpreted string literals
\a ASCII bell (BEL)
\b ASCII backspace (BS)
\f ASCII formfeed (FF)
\n ASCII linefeed (LF
\r ASCII carriage return (CR)
\t ASCII tab (TAB)
\uhhhh Unicode character with the given 4-digit 16-bit hex code point.
Unicode character with the given 8-digit 32-bit hex code point.
\v ASCII vertical tab (VT)
\xhh Unicode character with the given 2-digit 8-bit hex code point.

Rust 

All number literals allow _ as a visual separator: 1_234.0E+18f64

\x41 7-bit character code (exactly 2 digits, up to 0x7F)
\n Newline
\r Carriage return
\t Tab
\\ Backslash
\0 Null

\u{7FFF} 24-bit Unicode character code (up to 6 digits)

\' Single quote
\" Double quote


Go vs Rust - HashMap

 HashMap

The concept of HashMap is present in almost all programming languages like Java, C++, Python, it has key-value pairs and through key, we can get values of the map. Keys are unique no duplicates allowed in the key but the value can be duplicated.

Go

Maps are Go’s built-in associative data type (sometimes called hashes or dicts in other languages).

package main
import "fmt"
func main() {
    m := make(map[string]int)
    m["k1"] = 7
    m["k2"] = 13
    fmt.Println("map:", m)
    v1 := m["k1"]
    fmt.Println("v1: ", v1)
    fmt.Println("len:", len(m))
    delete(m, "k2")
    fmt.Println("map:", m)
    _, prs := m["k2"]
    fmt.Println("prs:", prs)
    n := map[string]int{"foo": 1, "bar": 2}
    fmt.Println("map:", n)
}

To initialize a map with some data, use a map literal:

commits := map[string]int{
    "rsc": 3711,
    "r":   2138,
    "gri": 1908,
    "adg": 912,
}

Concurrency

Maps are not safe for concurrent use. One common way to protect maps is with sync.RWMutex.

var counter = struct{
    sync.RWMutex
    m map[string]int
}{m: make(map[string]int)}

To read from the counter, take the read lock:

counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)

To write to the counter, take the write lock:

counter.Lock()
counter.m["some_key"]++
counter.Unlock()

Rust

let mut gfg=HashMap::new();
// inserting records 
gfg.insert("Data Structures","90");
gfg.insert("Algorithms","99");
gfg.entry(String::from("Blue")).or_insert("50");

for (key, val) in gfg.iter() {
    println!("{} {}", key, val);
}

if gfg.contains_key( & "FAANG") {
   println!("yes it contains the given key well done gfg");
}

println!("len of gfg HashMap={}",gfg.len());

gfg.remove(& "key");
let value= gfg.get(&"Algorithms");

// Update after check
for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}


Go vs Rust - Slices

 Slices

Go

Slice is more powerful, flexible, convenient than an array, and is a lightweight data structure. Slice is a variable-length sequence which stores elements of a similar type. It is just like an array having an index value and length, but the size of the slice is resized they are not in fixed-size just like an array. Internally, slice and an array are connected with each other, a slice is a reference to an underlying array.

    // Creating a slice using the var keyword
    var my_slice_1 = []string{"Geeks", "for", "Geeks"}
    // Creating an array
    arr := [4]string{"Geeks", "for", "Geeks", "GFG"}
    // Creating slices from the given array
    var my_slice_2 = arr[1:2]
    // Creating slices from the given slice
    var my_slice_3 = my_slice_3[1:5]

Generally, make() function is used to create an empty slice. Here, empty slices are those slices that contain an empty array reference

    // Creating an array of size 7 and slice this array  till 4
    // and return the reference of the slice Using make function
    var my_slice_1 = make([]int, 4, 7)
    fmt.Printf("Slice 1 = %v, \nlength = %d, \ncapacity = %d\n",
                   my_slice_1, len(my_slice_1), cap(my_slice_1))
 
    // Creating another array of size 7 and return the reference of the slice
    // Using make function
    var my_slice_2 = make([]int, 7)
    fmt.Printf("Slice 2 = %v, \nlength = %d, \ncapacity = %d\n",
                   my_slice_2, len(my_slice_2), cap(my_slice_2))

Multi-Dimensional Slice

 // Creating multi-dimensional slice
    s1 := [][]int{{12, 34},
        {56, 47},
        {29, 40},
        {46, 78},
    }
   
 sort.Ints(sl)
sort.IntsAreSorted(sl)

Rust

Slice is a data type that does not have ownership. Slice references a contiguous memory allocation rather than the whole collection. Slice is used when you do not want the complete collection, or you want some part of it. 

fn main() {
    let gfg = "GFG is a great start to start coding and improve".to_string();   
    // for first character
    println!("first character ={}",&gfg[0..1] );   
      // for first three characters
    println!("first three character ={}",&gfg[..3] );
      // calculating length of String
    let length_of_string=gfg.len();   
      let x=5;  
    // start from first to last character
    println!("start from 0 to x ={}",&gfg[..x] ); 
      // start from x to last character
    println!("start from x to end ={}",&gfg[x..length_of_string]);   
      // start from first to last character
    println!("from start to last ={}",&gfg[..length_of_string])
}


lc2)




Go vs Rust - Array and Vector (Rust)

 Array

programming languages. In the program, sometimes we need to store a collection of data of the same type, like a list of student marks. Such type of collection is stored in a program using an Array. 

Go

An array is a fixed-length sequence that is used to store homogeneous elements in the memory. Due to their fixed length array are not much popular like Slice in Go language. In Go language, an array is of value type not of reference type. So when the array is assigned to a new variable, then the changes made in the new variable do not affect the original array.

// Creating an array of string type Using var keyword
var myarr[3]string
// Elements are assigned using index
myarr[0] = "GFG"
myarr[1] = "GeeksforGeeks"
myarr[2] = "Geek"

Using shorthand declaration

// Shorthand declaration of array
arr:= [4]string{"geek", "gfg", "Geeks1231", "GeeksforGeeks"}
fmt.Println("Length of the array 1 is:", len(arr))

// Creating an array whose size is determined 
// by the number of elements present in it
// Using ellipsis
myarray:= [...]string{"GFG", "gfg", "geeks",
                    "GeeksforGeeks", "GEEK"}

Multi-Dimensional Array

Multi-Dimensional arrays are the arrays of arrays of the same type. 

// Creating and initializing 2-dimensional array
// Using shorthand declaration
// Here the (,) Comma is necessary
arr:= [3][3]string{{"C#", "C", "Python"}, 
                   {"Java", "Scala", "Perl"},
                    {"C++", "Go", "HTML"},}

Rust

An Array in Rust programming is a fixed-sized collection of elements denoted by [T; N] where is T is the element type and N is the compile-time constant size of the array.

We can create an array in 2 different ways:

  • Simply a list with each element [a, b, c].
  • Repeat expression [N, X].  This will create an array with N copies of X.
let mut array: [i32; 5] = [0; 5];
array[1] = 1;
array[2] = 2;
array[3] = 3;
array[4] = 4;
assert_eq!([1, 2 , 3 ,4], &array[1..]);
let arr = [1,2,3,4,5];
println!("array size is :{}",arr.len());
for index in 0..5 {
    println!("index is: {} & value is : {}",index, arr[index]);
}

Multi Array

use std::ops::{Index, Range};
struct ArrayView<'arr> {
    data: &'arr [[usize; 50]; 50],
    offsets: [usize; 2],
    size: [usize; 2],
}

Vector in Rust

Vector is a module in Rust that provides the container space to store values. It is a contiguous resizable array type, with heap-allocated contents.It can be increase size dynamically during runtime.Its length defines the number of elements present in the vector. Its capacity defines the actual allocated space on the heap of this vector that is in the form of 2^n.

let v : Vec<i64> = Vec::new(); 

or

let v = vec!['G','E','E','K','S'];

Examples

    // here index is the non negative value which is smaller than the size of the vector
    let index: usize = 3;
 
    let ch: char = v[index];
    let ch: Option<&char> = v.get(index);
    //loop to iterate elements in vector
    for i in v 
    { 
        // iterating through i on the the vector
        print!("{} ",i); 
    } 
    v.push('A');
    v.push('B');
    v.push('C');



Go vs Rust - Generics

 Generics are a way of writing code that is independent of the specific types being used. Functions and types may now be written to use any of a set of types.

Generics adds three new big things to the language:

  • Type parameters for function and types.
  • Defining interface types as sets of types, including types that don’t have methods.
  • Type inference, which permits omitting type arguments in many cases when calling a function.
Go

package main
import ("fmt")
type Number interface {
    int8 | int64 | float64
}
func sumNumbers[N Number](s []N) N {
    var total N
    for _, num := range s {
        total += num
    }
    return total
}
func main() {
    ints := []int64{32, 64, 96, 128}    
    floats := []float64{32.0, 64.0, 96.1, 128.2}
    bytes := []int8{8, 16, 24, 32}  
    fmt.Println(sumNumbers(ints))
    fmt.Println(sumNumbers(floats))    
    fmt.Println(sumNumbers(bytes))
}

any is essentially an alias for interface{}

func Print[T any] (s []T) {
for _, v := range s {
fmt.Println(v)
}
}

Another way generics can be used is to employ them in type parameters, as a way to create generic type definitions.

type Number interface {
    int8 | int64 | float64
}
type CustomSlice[T Number] []T
func Print[N Number, T CustomSlice[N]] (s T) {
for _, v := range s {
fmt.Println(v)
}
}
func main(){
    sl := CustomSlice[int64]{32, 32, 32}
    Print(sl)
}

Rust

Rust accomplishes generic by performing monomorphization of the code that is using generics at compile time. Monomorphization is the process of turning generic code into specific code by filling in the concrete types that are used when compiled.

struct Point<T> {
    x: T,
    y: T,
}
impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}
fn main() {
    let p = Point { x: 5, y: 10 };
    println!("p.x = {}", p.x());
}

Multiple bounds

impl <A: TraitB + TraitC, D: TraitE + TraitF> MyTrait<A, D> for YourType {}
// Expressing bounds with a `where` clause
impl <A, D> MyTrait<A, D> for YourType where
    A: TraitB + TraitC,
    D: TraitE + TraitF {}

New Type Idiom

To obtain the newtype's value as the base type, you may use the tuple or destructuring syntax like so:

struct Years(i64);
fn main() {
    let years = Years(42);
    let years_as_primitive_1: i64 = years.0; // Tuple
    let Years(years_as_primitive_2) = years; // Destructuring
}

Associated types

The use of "Associated types" improves the overall readability of code by moving inner types locally into a trait as output types. Syntax for the trait definition is as follows:

// `A` and `B` are defined in the trait via the `type` keyword.
// (Note: `type` in this context is different from `type` when used for
// aliases).
trait Contains {
    type A;
    type B;
    // Updated syntax to refer to these new types generically.
    fn contains(&self, _: &Self::A, _: &Self::B) -> bool;
}
// Without using associated types
fn difference<A, B, C>(container: &C) -> i32 where
    C: Contains<A, B> { ... }
// Using associated types
fn difference<C: Contains>(container: &C) -> i32 { ... }

Phantom type parameters

A phantom type parameter is one that doesn't show up at runtime, but is checked statically (and only) at compile time.

Data types can use extra generic type parameters to act as markers or to perform type checking at compile time. These extra parameters hold no storage values, and have no runtime behavior.

use std::marker::PhantomData;
// A phantom tuple struct which is generic over `A` with hidden parameter `B`.
#[derive(PartialEq)] // Allow equality test for this type.
struct PhantomTuple<A, B>(A,PhantomData<B>);
// A phantom type struct which is generic over `A` with hidden parameter `B`.
#[derive(PartialEq)] // Allow equality test for this type.
struct PhantomStruct<A, B> { first: A, phantom: PhantomData<B> }
// Note: Storage is allocated for generic type `A`, but not for `B`.
//       Therefore, `B` cannot be used in computations.
fn main() {
    // Here, `f32` and `f64` are the hidden parameters.
    // PhantomTuple type specified as `<char, f32>`.
    let _tuple1: PhantomTuple<char, f32> = PhantomTuple('Q', PhantomData);
    // PhantomTuple type specified as `<char, f64>`.
    let _tuple2: PhantomTuple<char, f64> = PhantomTuple('Q', PhantomData);
    // Type specified as `<char, f32>`.
    let _struct1: PhantomStruct<char, f32> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };
    // Type specified as `<char, f64>`.
    let _struct2: PhantomStruct<char, f64> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };    
}


Thursday, April 21, 2022

Go vs Rust - Functions & Methods & Closures

 Functions

A function is a group of statements that together perform a task. Both Go and Rust program has at least one function, which is main(). You can divide your code into separate functions. Logically, the division should be such that each function performs a specific task.

Go

Multiple results

package main
import "fmt"
func swap(x, y string) (string, string) {
   return y, x
}
func main() {
   a, b := swap("Mahesh", "Kumar")
   fmt.Println(a, b)
}

Named return values

func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}

Functions as Values

package main

import ("fmt" "math")

func main(){
   /* declare a function variable */
   getSquareRoot := func(x float64) float64 {
      return math.Sqrt(x)
   }

   /* use the function */
   fmt.Println(getSquareRoot(9))
}

Rust

fn add_one(x: i32) -> i32 {
    x + 1
}
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    f(arg) + f(arg)
}
fn main() {
    let answer = do_twice(add_one, 5);
    println!("The answer is: {}", answer);
}

Closures
Sometimes it is useful to wrap up a function and free variables for better clarity and reuse. The free variables that can be used come from the enclosing scope and are ‘closed over’ when used in the function. From this, we get the name ‘closures’ 

Function Closure in Go

Go programming language supports anonymous functions which can acts as function closures. Anonymous functions are used when we want to define a function inline without passing any name to it.

package main
import "fmt"
func getSequence() func() int {
   i:=0
   return func() int {
      i+=1
      return i  
   }
}
func main(){
   /* nextNumber is now a function with i as 0 */
   nextNumber := getSequence()  
   /* invoke nextNumber to increase i by 1 and return the same */
   fmt.Println(nextNumber())
   fmt.Println(nextNumber())
   
   /* create a new sequence and see the result, i is 0 again*/
   nextNumber1 := getSequence()  
   fmt.Println(nextNumber1())
}

Rust

Rust’s implementation of closures is a bit different than other languages. They are effectively syntax sugar for traits.

let plus_one = |x: i32| x + 1;

We have three separate traits to overload with:

Fn
FnMut
FnOnce

There are a few differences between these traits, but a big one is self: Fn takes &self, FnMut takes &mut self, and FnOnce takes self. This covers all three kinds of self via the usual method call syntax. But we’ve split them up into three traits, rather than having a single one. This gives us a large amount of control over what kind of closures we can take.

Closures and their environment

The environment for a closure can include bindings from its enclosing scope in addition to parameters and local bindings.

let num = 5;
let plus_num = |x: i32| x + num;

Move Closures

We can force our closure to take ownership of its environment with the move keyword

let num = 5;
let owns_num = move |x: i32| x + num;

Taking Closures as Arguments

Now that we know that closures are traits, we already know how to accept and return closures: the same as any other trait!

fn call_with_one<F>(some_closure: F) -> i32
    where F: Fn(i32) -> i32 {
    some_closure(1)
}
let answer = call_with_one(|x| x + 2);

In Rust, we can stack allocate our closure environment, and statically dispatch the call. This happens quite often with iterators and their adapters, which often take closures as arguments.

Of course, if we want dynamic dispatch, we can get that too. A trait object handles this case, as usual:

fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
    some_closure(1)
}
let answer = call_with_one(&|x| x + 2);

Now we take a trait object, a &Fn. And we have to make a reference to our closure when we pass it to call_with_one, so we use &||.

Higher-Ranked Trait Bounds

A closure that can borrow its argument only for its own invocation scope, not for the outer function's scope. In order to say that, we can use Higher-Ranked Trait Bounds with the for<...> syntax:

fn call_with_ref<F>(some_closure:F) -> i32
    where F: for<'a> Fn(&'a i32) -> i32 {

    let value = 0;
    some_closure(&value)
}

Returning Closures

Closures are represented by traits, which means you can’t return closures directly. In most cases where you might want to return a trait, you can instead use the concrete type that implements the trait as the return value of the function. But you can’t do that with closures because they don’t have a concrete type that is returnable. Rust doesn’t know how much space it will need to store the closure. We can use box to resolve this problem.

fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}

Function Pointers and Closures

A function pointer is kind of like a closure that has no environment. As such, you can pass a function pointer to any function expecting a closure argument.

fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
    some_closure(1)
}
fn add_one(i: i32) -> i32 {
    i + 1
}
let answer = call_with_one(&add_one);
assert_eq!(2, answer);

Methods

 Go

Go language support methods. Go methods are similar to Go function with one difference, i.e, the method contains a receiver argument in it. With the help of the receiver argument, the method can access the properties of the receiver.

package main
import (
   "fmt" 
   "math" 
)
/* define a circle */
type Circle struct {
   x,y,radius float64
}
/* define a method for circle */
func(circle Circle) area() float64 {
   return math.Pi * circle.radius * circle.radius
}
func main(){
   circle := Circle{x:0, y:0, radius:5}
   fmt.Printf("Circle area: %f", circle.area())
}

Rust 

Some functions are connected to a particular type. These come in two forms: associated functions, and methods. Associated functions are functions that are defined on a type generally, while methods are associated functions that are called on a particular instance of a type.

Associated Functions or Static Methods

The structure_name :: syntax is used to access a static method.

struct Point {
    x: f64,
    y: f64,
}
// Implementation block, all `Point` associated functions & methods go in here
impl Point {
    // This is an "associated function" because this function is associated with
    // a particular type, that is, Point.
    //
    // Associated functions don't need to be called with an instance.
    // These functions are generally used like constructors.
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }
    // Another associated function, taking two arguments:
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

Methods or Instance Method

The first parameter of a method will be always self, which represents the calling instance of the structure. Methods operate on the data members of a structure.

struct Rectangle {
    p1: Point,
    p2: Point,
}
impl Rectangle {
    // This is a method. &self is sugar for `self: &Self`, where `Self` is the type of the
    // caller object. In this case `Self` = `Rectangle`
    fn area(&self) -> f64 {
        // `self` gives access to the struct fields via the dot operator
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;
        // `abs` is a `f64` method that returns the absolute value of the
        // caller
        ((x1 - x2) * (y1 - y2)).abs()
    }
    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;
        2.0 * ((x1 - x2).abs() + (y1 - y2).abs())
    }
    // This method requires the caller object to be mutable
    // `&mut self` desugars to `self: &mut Self`
    fn translate(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;
        self.p1.y += y;
        self.p2.y += y;
    }
}