Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Go, Rust Cheat Sheet 2

Download as pdf or txt
Download as pdf or txt
You are on page 1of 95

The snippets are under the CC-BY-SA license.

Programming-Idioms.org
Creative Commons Attribution-ShareAlike 3.0

1 Print Hello World


Print a literal string on import "fmt" println!("Hello World");
standard output
fmt.Println("Hello World")

2 Print Hello 10 times


Loop to execute some import "fmt" for _ in 0..10 { println!("Hello"); }
code a constant number
for i := 0; i < 10; i++ { 0..10 syntax creates range iterator.
of times
fmt.Println("Hello")
} The compiler doesn't report unused variables prefixed with
an underscore.

Alternative implementation: Alternative implementation:

import "fmt" print!("{}", "Hello\n".repeat(10));


import "strings"

fmt.Println(strings.Repeat("Hello\n", 1
0))

3 Create a procedure
Like a function which import "fmt" fn finish(name: &str) {
doesn't return any value,
println!("My job here is done. Good
thus has only side func finish(name string) { bye {}", name);
effects (e.g. Print to
fmt.Println("My job here is done. Goo }
standard output)
d bye " + name)
} The actual return type is Unit, typed '()' and can be omitted
from function signature.
There is no return type in the signature, before the { .

Alternative implementation:

import "fmt"

finish := func(name string) {


fmt.Println("My job here is don
e. Good bye " + name)
}

This is a closure.

finish is a variable of type func(string).


4 Create a function
Create a function which
func square(x int) int { fn square(x : u32) -> u32 { x * x }
returns the square of an
return x*x
} Last expression in block is used as a return value.
integer
The return type is after the parameter list
5 Create a 2D Point data
structure
type Point struct { struct Point {
Declare a container type
x, y float64 x: f64,
} y: f64,
for two floating-point
}
numbers x and y

Alternative implementation:
struct Point(f64, f64);

6 Iterate over list values


Do something with each
for _, x := range items { for x in items {
item x of the list (or
doSomething(x) do_something(x);
array) items, regardless
} }
indexes.
You have to explicitly ignore the index loop variable, with the
blank identifier _ Alternative implementation:

items.into_iter().for_each(|x| do_somet
hing(x));
7 Iterate over list indexes
and values import "fmt" for (i, x) in items.iter().enumerate()
Print each index i with its
{
value x from an array-
for i, x := range items { println!("Item {} = {}", i, x);
like collection items
fmt.Printf("Item %d = %v \n", i, x) }
}

The range clause gives you index i and value x at the same Alternative implementation:
time as loop variables items.iter().enumerate().for_each(|(i,
x)| {
println!("Item {} = {}", i, x);
})

8 Initialize a new map


(associative array)
x := map[string]int {"one": 1, "two": use std::collections::BTreeMap;
Create a new map object
2}
x, and provide some
let mut x = BTreeMap::new();
x.insert("one", 1);
(key, value) pairs as
initial content.
x.insert("two", 2);

Something different than a BTreeMap might be used,


depending on the usage.

The function new of the type BTreeMap returns a usable


map.
The map is stored mutable in the variable x.

Maps in Rust are generic and type safe at compile time.

Alternative implementation:

use std::collections::HashMap;

let x: HashMap<&str, i32> = [


("one", 1),
("two", 2),
].into_iter().collect();

9 Create a Binary Tree


data structure
type BinTree struct { struct BinTree<T> {
Label valueType value: T,
The structure must be
recursive because left
Left, Right *BinTree left: Option<Box<BinTree<T>>>,
child and right child are
} right: Option<Box<BinTree<T>>>,
binary trees too. A node
}
has access to children Alternative implementation:
nodes, but not to its
type BinTree[L any] struct {
parent.
Label L
Left, Right *BinTree[L]
}

The type parameter L is for arbitrary node label data


10 Shuffle a list
Generate a random import "math/rand" extern crate rand;
permutation of the use rand::{Rng, StdRng};
elements of list x
for i := range x {
j := rand.Intn(i + 1) let mut rng = StdRng::new().unwrap();
x[i], x[j] = x[j], x[i] rng.shuffle(&mut x);
}
Requires the rand crate (https://crates.io/crates/rand)
This alters the slice content.
This requires no extra allocation. Alternative implementation:

use rand::seq::SliceRandom;
Alternative implementation:
use rand::thread_rng;
import "math/rand"
let mut rng = thread_rng();
y := make([]T, len(x)) x.shuffle(&mut rng);
perm := rand.Perm(len(x))
for i, v := range perm { Requires the rand crate.
y[v] = x[i] (https://crates.io/crates/rand)
}

This allocates a temporary slice of int, and a new


destination slice y of type T.
x is left unchanged.

Alternative implementation:

import "math/rand"

rand.Shuffle(len(x), func(i, j int) {


x[i], x[j] = x[j], x[i]
})

Last argument is a swap func.

This works in Go ≥ 1.10

Alternative implementation:

import "math/rand"

for i := len(x) - 1; i > 0; i-- {


j := rand.Intn(i + 1)
x[i], x[j] = x[j], x[i]
}

Alternative implementation:

import "math/rand"

func shuffle[T any](x []T) {


rand.Shuffle(len(x), func(i, j
int) {
x[i], x[j] = x[j], x[i]
})
}

This helper function is generic, it works for any type


parameter T
11 Pick a random element
from a list import "math/rand" use rand::{self, Rng};
The list x must be non-
empty.
x[rand.Intn(len(x))] x[rand::thread_rng().gen_range(0..x.len
())]
Alternative implementation: gen_range returns a number between 0 (inclusive) and
import "math/rand" x.len() (exclusive)

Alternative implementation:
func pickT(x []T) T {
return x[rand.Intn(len(x))] use rand::seq::SliceRandom;
}
let mut rng = rand::thread_rng();
Without generics: if you decide to implement pickT, you will let choice = x.choose(&mut rng).unwrap
have to write it separately for each desired type T. ();
Alternative implementation: The choose method returns an Option which is None if x is
func pick[T any](x []T) T { empty.
return x[rand.Intn(len(x))]
}

This generic function works for any type parameter T


12 Check if list contains a
value
func Contains(list []T, x T) bool { list.contains(&x);
Check if the list contains
for _, item := range list {
if item == x { See also more general alternative implementations.
the value x.
list is an iterable finite
return true
Alternative implementation:
container.
}
} list.iter().any(|v| v == &x)
return false
This works for most iterable types.
}
Alternative implementation:
This func works only for one type T.
(&list).into_iter().any(|v| v == &x)
You may use any type T compatible with operator ==
This is the the truly general version, but it isn't the most
Alternative implementation: idiomatic.

import "golang.org/x/exp/slices" Alternative implementation:

slices.Contains(list, x) list.binary_search(&x).is_ok()

This generic func slices.Contains works for all slice types The list must be sorted!

13 Iterate over map keys


and values import "fmt" use std::collections::BTreeMap;
Access each key k with
its value x from an
for k, x := range mymap { for (k, x) in &mymap {
associative array
fmt.Println("Key =", k, ", Value =", println!("Key={key}, Value={val}",
mymap, and print them.
x) key=k, val=x);
} }

Do not rely on the order of the traversal ! The order is You can also print collections in a 'nice' way with `println!("
undefined and is intentionaly randomized by the Go runtime. {:?}", mymap);` which is the Debug-representation. You can
also use "{:#?}" for the pretty version.

This example works the same if you replace BTreeMap with


HashMap.
14 Pick uniformly a
random floating point import "math/rand" extern crate rand;
number in [a..b) use rand::{Rng, thread_rng};
Pick a random number
func pick(a, b float64) float64 {
greater than or equals to
return a + (rand.Float64() * (b thread_rng().gen_range(a..b);
-a))
a, strictly inferior to b.
} If you need to generate a lot of random stuff, save the
Precondition : a < b.
thread_rng as a variable so it is only initialized once.
Note that the package math/rand is not crypto-secure.
15 Pick uniformly a
random integer in [a..b] import "math/rand" extern crate rand;
Pick a random integer use rand::distributions::{Independent
greater than or equals to
func pick(a,b int) int { Sample, Range};
a, inferior or equals to b.
return a + rand.Intn(b-a+1)
Precondition : a < b.
} fn pick(a: i32, b: i32) -> i32 {
let between = Range::new(a, b);
(b-a+1) is needed to have upper bound b included. let mut rng = rand::thread_rng();
Note that the package math/rand is not crypto-secure. between.ind_sample(&mut rng)
}

Alternative implementation:

use rand::distributions::Distributio
n;
use rand::distributions::Uniform;

Uniform::new_inclusive(a, b).sample(&mu
t rand::thread_rng())

16 Depth-first traversal of
a binary tree
func (bt *BinTree) Dfs(f func(*BinTre struct BiTree<T> {
Call a function f on every
e)) { left: Option<Box<BiTree<T>>>,
node of binary tree bt, in
if bt == nil { right: Option<Box<BiTree<T>>>,
depth-first infix order
return value: T,
} }
bt.Left.Dfs(f)
f(bt) fn depthFirstTraverse<T>(bt: &mut BiTre
bt.Right.Dfs(f) e<T>, f: fn(&mut BiTree<T>)) {
} if let Some(left) = &mut bt.left {
f(left);
The function f is a parameter of the traversal method Dfs. }
It's legit to call a method on a nil receiver, and useful to
make code more concise with less checks for nil. f(bt);
Alternative implementation:
if let Some(right) = &mut bt.right
func (bt *BinTree[L]) Dfs(f func(*BinTr {
ee[L])) { f(right);
if bt == nil { }
return }
}
bt.Left.Dfs(f)
f(bt)
bt.Right.Dfs(f)
}

The type parameter L is for arbitrary node label data


17 Create a Tree data
structure
type Tree struct { struct Node<T> {
The structure must be
Key keyType value: T,
recursive. A node may
Deco valueType children: Vec<Node<T>>,
have zero or more
Children []*Tree }
children. A node has
}
access to its children
keyType should be easily comparable.
nodes, but not to its
valueType is a type of value associated with current node.
parent.
Children is a slice of pointers.

Note that in Go you can call methods of pointer type *Tree


even on a nil receiver (an empty tree).

Alternative implementation:

type Tree[L any] struct {


Label L
Children []*Tree[L]
}

The type parameter L is for arbitrary node label data.

A nil *Tree denotes the empty tree.


18 Depth-first traversal of
func (t *Tree) Dfs(f func(*Tree)) { pub struct Tree<V> {
a tree
if t == nil { children: Vec<Tree<V>>,
Call a function f on every
node of a tree, in depth-
return value: V
} }
first prefix order
f(t)
for _, child := range t.Childre impl<V> Tree<V> {
n { pub fn dfs<F: Fn(&V)>(&self, f: F)
child.Dfs(f) {
} self.dfs_helper(&f);
} }
fn dfs_helper<F: Fn(&V)>(&self, f:
The function f is a parameter of the traversal method Dfs . &F) {
The traversal is prefix because f is applied to current node (f)(&self.value);
first. for child in &self.children {
child.dfs_helper(f)
Alternative implementation:
}
func (t *Tree[L]) Dfs(f func(*Tree[L])) }
{ // ...
if t == nil { }
return
} The actual idiomatic way to do this is to implement an
f(t) iterator.
for _, child := range t.Childre
n {
child.Dfs(f)
}
}

The type parameter L is for arbitrary node label data


19 Reverse a list
Reverse the order of the
for i, j := 0, len(x)-1; i < j; i, j = let y: Vec<_> = x.into_iter().rev().col
elements of the list x.
i+1, j-1 { lect();
This may reverse "in-
x[i], x[j] = x[j], x[i]
} x is moved.
place" and destroy the
original ordering.
This loop reverts "in-place" (in the original list, not creating a Works with other data structures that implement Iterator.
new one).
Alternative implementation:
Alternative implementation:
x.reverse();
func reverse[T any](x []T) {
for i, j := 0, len(x)-1; i < j; x has type Vec.
i, j = i+1, j-1 {
x[i], x[j] = x[j], x[i] This reverses in place.
}
}

This generic function works for any type parameter T.

It operates in-place.
20 Return two values
Implement a function
func search(m [][]int, x int) (bool, in fn search<T: Eq>(m: &Vec<Vec<T>>, x: &
t, int) { T) -> Option<(usize, usize)> {
search which looks for
for i := range m { for (i, row) in m.iter().enumerate
item x in a 2D matrix m.
Return indices i, j of the
for j, v := range m[i] () {
{ for (j, column) in row.iter().e
matching cell.
Think of the most
if v == x { numerate() {
idiomatic way in the
return if *column == *x {
true, i, j return Some((i, j));
language to return the
two values at the same
} }
} }
time.
} }
return false, 0, 0
} None
}
Go functions may return multiple values.
This function returns 3 values : one to indicate if x was This returns an optional tuple.
found or not, and two for the coordinates.
21 Swap values
Swap the values of the
a, b = b, a std::mem::swap(&mut a, &mut b);
variables a and b
Alternative implementation:

let (a, b) = (b, a);

This uses pattern matching and destructuring of tuples to


swap values.
22 Convert string to
integer import "strconv" let i = s.parse::<i32>().unwrap();
Extract the integer value
i, err := strconv.Atoi(s) This panics if s is not a valid number.
i from its string
s is parsed to 32-bits signed integer here (change number
representation s (in radix
Atoi(s) is shorthand for ParseInt(s, 10, 0). It yields type int. type if needed).
10)
Alternative implementation: Alternative implementation:

import "strconv" let i: i32 = s.parse().unwrap_or(0);

i, err := strconv.ParseInt(s, 10, 0) This explicitly sets the value to 0 if it can't be parsed to an
integer.
Radix 10. The third argument 0 means "fit in
Alternative implementation:
implementation-specific int". But the result type is always
int64. let i = match s.parse::<i32>() {
Don't ignore the potential error err ! Ok(i) => i,
Err(_e) => -1,
};

s is parsed to 32-bits signed integer here (change number


type if needed).
-1 is used here as a fallback value, but any error handling
instructions can be used.
23 Convert real number to
string with 2 decimal import "fmt" let s = format!("{:.2}", x);
places
Given a real number x,
s := fmt.Sprintf("%.2f", x)
create its string
representation s with 2
decimal digits following
the dot.
24 Assign to string the
japanese word ネコ
s := "ネコ" let s = "ネコ";
Declare a new string s
UTF-8 literals are valid in Go. Make sure to always save your source code files as UTF-8.
and initialize it with the
literal value "ネコ"
Also the source code in Go is defined to be UTF-8 text; No
(which means "cat" in
other representation is allowed.
japanese)
25 Send a value to
another thread import "fmt" use std::thread;
Share the string value use std::sync::mpsc::channel;
"Alan" with an existing
go func() {
running process which
v := <-ch let (send, recv) = channel();
will then display "Hello,
fmt.Printf("Hello, %v\n", v)
Alan"
}() thread::spawn(move || {
loop {
ch <- "Alan" let msg = recv.recv().unwrap();
println!("Hello, {:?}", msg);
The receiver goroutine blocks reading the chan string }
named ch. });
The current goroutine sends the value to ch.
A goroutine is like a lightweight green thread. send.send("Alan").unwrap();

The message might not be printed if the main thread exits


before the thread has written to stdout.
26 Create a 2-dimensional
array
const m, n = 3, 4 let mut x = vec![vec![0.0f64; N]; M];
Declare and initialize a
var x [m][n]float64
matrix x having m rows Alternative implementation:
m, n must be constant for this syntax to be valid.
and n columns,
Here x is of type [3][4]float64, it is not a slice. let mut x = [[0.0; N] ; M];
containing real numbers.
Alternative implementation: This works only when M and N are constant.
func make2D(m, n int) [][]float64 { Elements have type f64
buf := make([]float64, m*n)

x := make([][]float64, m)
for i := range x {
x[i] = buf[:n:n]
buf = buf[n:]
}
return x
}

This works even when m, n are not compile-time constants.


This code allocates one big slice for the numbers, plus one
slice for x itself.
The same function would have to be rewritten, for types
other than float64.

Alternative implementation:

func make2D[T any](m, n int) [][]T {


buf := make([]T, m*n)

x := make([][]T, m)
for i := range x {
x[i] = buf[:n:n]
buf = buf[n:]
}
return x
}

This generic func works for any type parameter T.


m, n do not need to be compile-time constants.
This code allocates one big slice for the elements, plus one
slice for x itself.
27 Create a 3-dimensional
array
const m, n, p = 2, 2, 3 let x = vec![vec![vec![0.0f64; p]; n];
Declare and initialize a
var x [m][n][p]float64 m];
3D array x, having
m, n, p must be constant for this syntax to be valid. m, n, p don't have to be constants
dimensions boundaries
Here x is of type [2][2][3]float64, it is not a slice.
m, n, p, and containing Alternative implementation:
real numbers. Alternative implementation:
let x = [[[0.0f64; P]; N]; M];
func make3D(m, n, p int) [][][]float64
{ Stack-allocated array.
buf := make([]float64, m*n*p)
M, N, P are constants.
x := make([][][]float64, m)
for i := range x {
x[i] = make([][]float6
4, n)
for j := range x[i] {
x[i][j] = buf[:
p:p]
buf = buf[p:]
}
}
return x
}

This works even when m, n, p are not compile-time


constants.
This code allocates one big slice for the numbers, then a
few slices for intermediate dimensions.
To same function would be rewritten, for types other than
float64.

Alternative implementation:

func make3D[T any](m, n, p int) [][][]T


{
buf := make([]T, m*n*p)

x := make([][][]T, m)
for i := range x {
x[i] = make([][]T, n)
for j := range x[i] {
x[i][j] = buf[:
p:p]
buf = buf[p:]
}
}
return x
}

This generic func works for any type parameter T.


m, n, p do not need to be compile-time constants.
This code allocates one big slice for the elements, then a
few slices for intermediate dimensions.
28 Sort by a property
Sort the elements of the import "sort" items.sort_by(|a,b| a.p.cmp(&b.p));
list (or array-like
collection) items in
type ItemPSorter []Item
Alternative implementation:
ascending order of x.p,
func (s ItemPSorter) Len() int{ return
len(s) } items.sort_by_key(|x| x.p);
where p is a field of the
type Item of the objects
func (s ItemPSorter) Less(i,j int) bool
in items.
{ return s[i].p<s[j].p }
func (s ItemPSorter) Swap(i,j int) { s
[i],s[j] = s[j],s[i] }

func sortItems(items []Item){


sorter := ItemPSorter(items)
sort.Sort(sorter)
}

The standard way is to declare a new type ItemSorter as a


slice of Item, and carefully implement method Less.

Alternative implementation:

import "sort"

less := func(i, j int) bool {


return items[i].p < items[j].p
}
sort.Slice(items, less)

This is the diomatic way since Go 1.8.

Alternative implementation:

import "golang.org/x/exp/slices"

less := func(a, b Item) bool {


return a.p < b.p
}
slices.SortFunc(items, less)

SortFunc is generic and type-safe at compile time.


29 Remove item from list,
by its index
items = append(items[:i], items[i+ items.remove(i)
Remove i-th item from
1:]...)
list items.
If items elements are pointers or structs with pointers, then
This will alter the original
refer to the SliceTricks page to avoid memory leaks.
list or return a new list,
depending on which is Alternative implementation:
more idiomatic.
copy(items[i:], items[i+1:])
Note that in most
items[len(items)-1] = nil
languages, the smallest
items = items[:len(items)-1]
valid value for i is 0.
This code is for pointer value type, and has no memory
leak.

Alternative implementation:

import "golang.org/x/exp/slices"

items = slices.Delete(items, i, i+1)

This generic func slices.Delete works for all slice types.


If items contains pointers, then be aware that
items[len(s)-1] is not set to nil by Delete.
30 Parallelize execution of
1000 independent import "sync" use std::thread;
tasks
Launch the concurrent
wg := sync.WaitGroup{} let threads: Vec<_> = (0..1000).map(|i|
execution of procedure f
wg.Add(1000) {
with parameter i from 1
for i := 1; i <= 1000; i++ { thread::spawn(move || f(i))
to 1000.
go func(j int) { }).collect();
Tasks are independent
f(j)
and f(i) doesn't return
wg.Done() for thread in threads {
any value.
}(i) thread.join();
Tasks need not run all at
} }
the same time, so you
wg.Wait()
If you don't join the threads, the program will just exit and
may use a pool.
The current value of i is captured, and a goroutine is the threads will be killed.
launched
This would be better implemented with a thread pool but the
standard library doesn't include one.

Alternative implementation:

extern crate rayon;


use rayon::prelude::*;

(0..1000).into_par_iter().for_each(f);

Requires the rayon crate.


(https://crates.io/crates/rayon)
31 Recursive factorial
(simple)
func f(i int) int { fn f(n: u32) -> u32 {
Create the recursive
if i == 0 { if n < 2 {
function f which returns
return 1 1
the factorial of the non-
} } else {
negative integer i,
return i * f(i-1) n * f(n - 1)
calculated from f(i-1)
} }
}

Alternative implementation:

fn factorial(num: u64) -> u64 {


match num {
0 | 1 => 1,
_ => factorial(num - 1) * num,
}
}

match arm for 0|1 checks if the numbers are either 0 or 1


32 Integer exponentiation
func exp(x, n int) int { fn exp(x: u64, n: u64) -> u64 {
by squaring
Create function exp
switch { match n {
which calculates (fast)
case n == 0: 0 => 1,
return 1 1 => x,
the value x power n.
x and n are non-
case n == 1: i if i % 2 == 0 => exp(x * x, n
negative integers.
return x / 2),
case n%2 == 0: _ => x * exp(x * x, (n - 1) /
return exp(x*x, n/2) 2),
default: }
return x * exp(x*x, (n- }
1)/2)
}
Alternative implementation:
}
fn exp(x: u64, n: u32) -> u64 {
Warning: type int quickly overflows x.pow(n)
}
33 Atomically read and
update variable import "sync" let mut x = x.lock().unwrap();
Assign to the variable x
*x = f(x);
the new value f(x),
var lock sync.Mutex
Assuming x is created like this:
making sure that no
lock.Lock() `let x = Mutex::new(0);`
other thread may modify
x between the read and
x = f(x)
the write.
lock.Unlock()

You need to lock whenever accessing x.


34 Create a set of objects
Declare and initialize a
x := make(map[T]bool) use std::collections::HashSet;
set x containing unique There is no built-in Set type, but you can create a Map with
objects of type T.
let x: HashSet<T> = HashSet::new();
key type T and boolean value (which will be ignored).

Alternative implementation:

x := make(map[T]struct{})

The struct{} type is space efficient because it occupies zero


bytes in memory.
35 First-class function :
compose
func compose(f func(A) B, g func(B) C) fn compose<'a, A, B, C, G, F>(f: F, g:
Implement a function
func(A) C { G) -> Box<Fn(A) -> C + 'a>
compose (A -> C) with
return func(x A) C { where F: 'a + Fn(A) -> B, G: 'a
parameters f (A -> B)
return g(f(x)) + Fn(B) -> C
and g (B -> C), which
} {
returns the composition
} Box::new(move |x| g(f(x)))
function g ∘ f
}
Functions are first-class citizens in Go. They are passed as
arguments and as return values. Unfortunately, you'll need to implement another two variants
if you care about FnMut and FnOnce. Also, for now, you
need to box the returned function. In the future, this
shouldn't be necessary.

Alternative implementation:

fn compose<A, B, C>(f: impl Fn(A) -> B,


g: impl Fn(B) -> C) -> impl Fn(A) -> C
{
move |x| g(f(x))
}

36 First-class function :
generic composition
func composeIntFuncs(f func(int) int, g fn compose<'a, A, B, C, G, F>(f: F, g:
Implement a function
func(int) int) func(int) int { G) -> Box<Fn(A) -> C + 'a>
compose which returns
return func(x int) int { where F: 'a + Fn(A) -> B, G: 'a
composition function g ∘ 
return g(f(x)) + Fn(B) -> C
f for any functions f and
} {
g having exactly 1
} Box::new(move |x| g(f(x)))
parameter.
}
These specific functions take and return concrete types.
Unfortunately, you'll need to implement another two variants
It could be done with an empty interface, but that would if you care about FnMut and FnOnce. Also, for now, you
discard static type checks (the implementations of f and g need to box the returned function. In the future, this
can still be type-checked, though). shouldn't be necessary.

Alternative implementation: Alternative implementation:

func compose[T, U, V any](f func(T) U, fn compose<A, B, C>(f: impl Fn(A) -> B,


g func(U) V) func(T) V { g: impl Fn(B) -> C) -> impl Fn(A) -> C
return func(x T) V { {
return g(f(x)) move |x| g(f(x))
} }
}

compose is generic, it accepts any type parameters T, U,


V.
37 Currying
Transform a function that
type PayFactory func(Company, *Employe fn add(a: u32, b: u32) -> u32 {
takes multiple arguments
e, *Employee) Payroll a + b
into a function for which
}
some of the arguments
type CustomPayFactory func(*Employee) P
are preset.
ayroll let add5 = move |x| add(5, x);

func CurryPayFactory(pf PayFactory,comp


any Company, boss *Employee) CustomPayF
actory {
return func(e *Employee) Payrol
l {
return pf(company, bos
s, e)
}
}

The currying function is not generic, it must be written for


each type of currying needed.
38 Extract a substring
Find substring t
t := string([]rune(s)[i:j]) extern crate unicode_segmentation;
consisting in characters i convert to []rune because some characters are two or more use unicode_segmentation::UnicodeSegm
(included) to j (excluded) bytes. entation;
of string s.
Character indices start at
let t = s.graphemes(true).skip(i).take
0 unless specified
(j - i).collect::<String>();
otherwise.
Treats the 'character indexes' as indices of 'extended
Make sure that multibyte
grapheme clusters' as defined by Unicode.
characters are properly
handled. Alternative implementation:

use substring::Substring;

let t = s.substring(i, j);

39 Check if string
contains a word import "strings" let ok = s.contains(word);
Set the boolean ok to
ok := strings.Contains(s, word)
true if the string word is
contained in string s as a
substring, or to false
otherwise.
40 Graph with adjacency
lists
type Vertex struct{
Id int
Declare a Graph data
structure in which each
Label string
Vertex has a collection
Neighbours map[*Vertex]bool
}
of its neighbouring
vertices.
type Graph []*Vertex

The map is used as a Set of Vertex pointers.


Graph is a list of all the Vertex pointers.

Alternative implementation:

type Graph[L any] []*Vertex[L]

type Vertex[L any] struct {


Label L
Neighbours map[*Vertex[L]]bool
}

The map is used as a Set of Vertex pointers.


Graph is a list of all the Vertex pointers.
The type parameter L is for arbitrary node label data.
41 Reverse a string
Create string t
runes := []rune(s) let t = s.chars().rev().collect::<Strin
containing the same
for i, j := 0, len(runes)-1; i < j; i, g>();
characters as string s, in
j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes collect is a function with a generic return type, so we must
reverse order.
[i] explicitly specify that we want a String back, either by
Original string s must
} annotating t's type as a String, or by specifying with the so-
remain unaltered. Each
t := string(runes) called "turbofish" syntax.
character must be
handled correctly Alternative implementation:
This takes care of multi-byte runes, which count as a single
regardless its number of
character. let t: String = s.chars().rev().collect
bytes in memory.
();
Alternative implementation:

import (
"strings"
"unicode/utf8"
)

func reverse(s string) string {


if len(s) <= 1 {
return s
}
var b strings.Builder
b.Grow(len(s))
for len(s) > 0 {
r, l := utf8.DecodeLast
RuneInString(s)
s = s[:len(s)-l]
b.WriteRune(r)
}
return b.String()
}

This version of reverse takes care of multi-byte runes, but


performs a single allocation.
42 Continue outer loop
mainloop: 'outer: for va in &a {
Print each item v of list a
which is not contained in
for _, v := range a { for vb in &b {
list b.
for _, w := range b { if va == vb {
if v == w { continue 'outer;
For this, write an outer
loop to iterate on a and
continu }
an inner loop to iterate
e mainloop }
} println!("{}", va);
on b.
} }
fmt.Println(v)
} 'outer is a label used to refer to the outer loop. Labels in
Rust start with a '.
mainloop is a label used to refer to the outer loop.
43 Break outer loop
Look for a negative
mainloop: 'outer: for v in m {
value v in 2D integer
for i, line := range m { 'inner: for i in v {
matrix m. Print it and
for _, v := range line if i < 0 {
stop searching.
{ println!("Found {}", i);
if v < 0 { break 'outer;
fmt.Pri }
ntln(v) }
break m }
ainloop
} Loop label syntax is similar to lifetimes.
}
}

mainloop is a label used to refer to the outer loop.


44 Insert element in list
Insert the element x at
s = append(s, 0) s.insert(i, x);
position i in the list s.
copy(s[i+1:], s[i:])
Further elements must
s[i] = x
be shifted to the right.
Extend slice by 1 (it may trigger a copy of the underlying
array).
Then shift elements to the right.
Then set s[i].

Alternative implementation:

import "golang.org/x/exp/slices"

s = slices.Insert(s, i, x)

This generic func slices.Insert works for all slice types


45 Pause execution for 5
seconds import "time" use std::{thread, time};
Sleep for 5 seconds in
current thread, before
time.Sleep(5 * time.Second) thread::sleep(time::Duration::from_secs
proceeding with the next
(5));
Unit is Duration, an alias for int64 representing a number of
instructions.
nanoseconds.
The constant Second helps readability.
46 Extract beginning of
string (prefix)
t := string([]rune(s)[:5]) let t = s.char_indices().nth(5).map_or
Create string t consisting This "incurs a run-time cost" proportional to len(s).
(s, |(i, _)| &s[..i]);
of the 5 first characters
Rust strings are encoded in UTF-8, and can be multiple
of string s.
bytes wide, which text processing code must account for.
Make sure that multibyte
Naively slicing the string could cause it to panic if, for
characters are properly
example, the string contained 😁
handled.
It should be noted that these logical "characters" don't have
much semantic meaning either: Unicode characters are
combined into "graphemes" before being displayed to the
user, which would need to be identified using the unicode-
segmentation crate

Alternative implementation:

let t = s.chars().take(5).collect::<Str
ing>();

47 Extract string suffix


Create string t consisting
t := string([]rune(s)[len([]rune(s))- let last5ch = s.chars().count() - 5;
in the 5 last characters
5:]) let t: String = s.chars().skip(last5c
of string s.
h).collect();
Convert to []rune because some characters are two or more
Make sure that multibyte
bytes long.
characters are properly
handled.
48 Multi-line string literal
Assign to variable s a
s := `Huey let s = "line 1
string literal consisting in
Dewey line 2
several lines of text,
Louie` line 3";
including newlines.
This is a raw string literal (not "interpreted").
Alternative implementation:

let s = r#"Huey
Dewey
Louie"#;

Raw string literals do not process any escapes.


49 Split a space-
separated string import "strings" let chunks: Vec<_> = s.split_whitespace
Build list chunks
().collect();
consisting in substrings
chunks := strings.Split(s, " ")
This regards all whitespace as separators, including \t and
of the string s, separated
chunks has type []string. \n.
by one or more space
Warning: you may get empty strings as items in chunks
characters. Alternative implementation:
because of leading spaces, trailing spaces, and repeated
spaces. let chunks: Vec<_> = s.split_ascii_whit
espace().collect();
Alternative implementation:
This regards all ASCII whitespace as separators, including \t
import "strings"
and \n.
chunks := strings.Fields(s)
Alternative implementation:
chunks has type []string. let chunks: Vec<_> = s.split(' ').colle
Fields treats repeated spaces as a single separator. ct();

Warning: this returns some empty strings in chunks, in case


of multiple consecutive spaces in the s.
50 Make an infinite loop
Write a loop that has no
for { loop {
// Do something // Do something
end clause.
} }

No need to write loop variables nor end condition.


51 Check if map contains
key
_, ok := m[k] use std::collections::HashMap;
Determine whether the
ok is true if m contains a value for key k. The value itself is m.contains_key(&k)
map m contains an entry
ignored.
for the key k
Same method name for HashMap and BTreeMap.
52 Check if map contains
value
func containsValue(m map[K]T, v T) bool use std::collections::BTreeMap;
Determine whether the
{
map m contains an entry
for _, x := range m { let does_contain = m.values().any(|&val
with the value v, for
if x == v { | *val == v);
some key.
return true
} Works the same for HashMap.
}
return false
}

You have to iterate explicitly. In this implementation, the


types K, T are not generic.

Alternative implementation:

func containsValue[M ~map[K]V, K, V com


parable](m M, v V) bool {
for _, x := range m {
if x == v {
return true
}
}
return false
}

This generic function works for any type parameters K, V


that are comparable
53 Join a list of strings
Concatenate elements of import "strings" let y = x.join(", ");
string list x joined by the
y := strings.Join(x, ", ") Note that join() used to be named connect() .
separator ", " to create a
single string y.
This works only if x has type []string.
54 Compute sum of
integers
s := 0 x.iter().sum()
Calculate the sum s of
for _, v := range x {
the integer list or array x.
s += v
Alternative implementation:
}
let s = x.iter().sum::<i32>();
Such explicit loops are idiomatic in Go.
55 Convert integer to
string import "strconv" let s = i.to_string();
Create the string
s := strconv.Itoa(i) s has type String
representation s (in radix
10) of the integer value i. When i has type int. Alternative implementation:

let s = format!("{}", i);


Alternative implementation:
s has type String
import "strconv"

s := strconv.FormatInt(i, 10)

When i has type int64.

Alternative implementation:

import "fmt"

s := fmt.Sprintf("%d", i)

This works with all types of integers.

Sprintf does type assertions, and is slower than the


strconv flavors
56 Launch 1000 parallel
tasks and wait for import "sync" use std::thread;
completion
Fork-join : launch the
var wg sync.WaitGroup let threads: Vec<_> = (0..1000).map(|i|
concurrent execution of
wg.Add(1000) thread::spawn(move || f(i))).collect();
procedure f with
for i := 1; i <= 1000; i++ {
parameter i from 1 to
go func(i int) { for t in threads {
1000.
f(i) t.join();
Tasks are independent
wg.Done() }
and f(i) doesn't return
}(i)
any value.
}
Tasks need not run all at
wg.Wait()
the same time, so you
fmt.Println("Finished")
may use a pool.
It is necessary to capture the current value of loop variable
Wait for the completion
i. See https://github.com/golang/go/wiki/CommonMistakes
of the 1000 tasks and
then print "Finished".
57 Filter list
Create the list y
y := make([]T, 0, len(x)) let y: Vec<_> = x.iter().filter(p).coll
containing the items
for _, v := range x{ ect();
from the list x that satisfy
if p(v){
y = append(y, v) This collects into a vector (other collections are possible)
the predicate p. Respect
the original ordering.
}
Don't modify x in-place.
}

For item type T.


Note that this allocates memory for the new slice y.
Warning: y is allocated with as much memory as x, which
may in some cases be wasteful.

Alternative implementation:

n := 0
for _, v := range x {
if p(v) {
n++
}
}
y := make([]T, 0, n)
for _, v := range x {
if p(v) {
y = append(y, v)
}
}

This makes 2 passes: one to count the number n of


elements to be kept, and one to copy the elements in the
target slice created with the correct size n.
This is efficient if p is cheap and x is small.

Alternative implementation:

func filter[S ~[]T, T any](x S, p func


(T) bool) S {
var y S
for _, v := range x {
if p(v) {
y = append(y,
v)
}
}
return y
}

filter is a generic function with a type parameter T


58 Extract file content to a
string import "os" use std::io::prelude::*;
Create string lines from use std::fs::File;
the content of the file
b, err := os.ReadFile(f)
with filename f.
if err != nil { let mut file = File::open(f)?;
// Handle error... let mut lines = String::new();
} file.read_to_string(&mut lines)?;
lines := string(b)

In Go it is idiomatic to inspect an error value before moving Alternative implementation:


on. use std::fs;

lines is a single string. let lines = fs::read_to_string(f).expec


t("Can't read file.");

59 Write to standard error


import "os" eprintln!("{} is negative", x);
stream
Print the message "x is
negative" to standard
fmt.Fprintln(os.Stderr, x, "is negativ
error (stderr), with
e")
integer x value
substitution (e.g. "-2 is
negative").
60 Read command line
argument import "os" use std::env;
Assign to x the string
value of the first
x := os.Args[1] let first_arg = env::args().skip(1).nex
command line
t();
os.Args[0] is actually the executable name.
parameter, after the
program name.
let fallback = "".to_owned();
let x = first_arg.unwrap_or(fallback);

The first CLI argument may not be present. We fall back to


an empty string.

Alternative implementation:

use std::env;

let x = env::args().nth(1).unwrap_or
("".to_string());

We get the 1st element using the nth method and we


fallback to an empty string if no arg was found.
61 Get current date
Assign to the variable d import "time" extern crate time;
the current date/time
value, in the most
d := time.Now() let d = time::now();
standard type.
The type Time wraps a timestamp with nanosecond The current time in the local timezone in this format:
precision. http://doc.rust-lang.org/time/time/struct.Tm.html

Alternative implementation:

use std::time::SystemTime;

let d = SystemTime::now();

62 Find substring position


Set i to the first position import "strings" let i = x.find(y);
of string y inside string x,
i := strings.Index(x, y) i is an Option<usize>.
if exists.
Finds the byte index of y in x (not the character index).
i is the byte index of y in x, not the character (rune) index.
Specify if i should be
regarded as a character
i will be -1 if y is not found in x.
index or as a byte index.

Explain the behavior


when y is not contained
in x.
63 Replace fragment of a
string import "strings" let x2 = x.replace(&y, &z);
Assign to x2 the value of
x2 := strings.Replace(x, y, z, -1) Returns a string slice (&str). Add .to_string() or
string x with all
.to_owned() to get a String.
occurrences of y
-1 means "no limit on the number of replacements".
replaced by z.
This replaces non-overlapping instances of y.
Assume occurrences of
y are not overlapping.
64 Big integer : value 3
power 247 import "math/big" extern crate num;
Assign to x the value use num::bigint::ToBigInt;
3^247
x := new(big.Int)
x.Exp(big.NewInt(3), big.NewInt(247), n let a = 3.to_bigint().unwrap();
il) let x = num::pow(a, 247);

The nil argument means we don't want a modulo.


65 Format decimal
number import "fmt" let s = format!("{:.1}%", 100.0 * x);
From the real value x in
[0,1], create its
s := fmt.Sprintf("%.1f%%", 100.0*x)
percentage string
The literal % must be doubled.
representation s with
one digit after decimal
point. E.g. 0.15625 ->
"15.6%"
66 Big integer
exponentiation import "math/big" extern crate num;
Calculate the result z of
x power n, where x is a
nb := big.NewInt(int64(n)) let z = num::pow(x, n);
big integer and n is a var z big.Int
positive integer. z.Exp(x, nb, nil)

Exponentiation is already implemented in package math/big.


67 Binomial coefficient "n
choose k" import "math/big" extern crate num;
Calculate binom(n, k) =
n! / (k! * (n-k)!). Use an
z := new(big.Int) use num::bigint::BigInt;
integer type able to z.Binomial(n, k) use num::bigint::ToBigInt;
handle huge numbers. use num::traits::One;

fn binom(n: u64, k: u64) -> BigInt {


let mut res = BigInt::one();
for i in 0..k {
res = (res * (n - i).to_bigint
().unwrap()) /
(i + 1).to_bigint().unwra
p();
}
res
}

68 Create a bitset
Create an object x to import "math/big" let mut x = vec![false; n];
store n bits (n being
potentially large).
var x *big.Int = new(big.Int)

big.Int type makes a decent bitset.


It grows automatically when needed.

Alternative implementation:

x := make([]bool, n)

This makes a simple fixed-size bitset.


It uses more bits in memory than the useful size n.

Alternative implementation:

x := make([]uint64, (n+63)/64)

This compact bitset requires some extra logic to implement


get, set, clear (see demo).
69 Seed random
generator import "math/rand" use rand::{Rng, SeedableRng, rngs::St
Use seed s to initialize a dRng};
random generator.
rand.Seed(s)
let s = 32;
s is of type int64. let mut rng = StdRng::seed_from_u64(s);
If s is constant, the
This initializes the default Source.
generator output will be
the same each time the Alternative implementation:
program runs. If s is
based on the current
import "math/rand"
value of the system
r := rand.New(rand.NewSource(s))
clock, the generator
output will be different s is of type int64.
each time. r is of type *rand.Rand.
70 Use clock as random
generator seed import "math/rand" use rand::{Rng, SeedableRng, rngs::St
Get the current datetime import "time" dRng};
and provide it as a seed use std::time::SystemTime;
to a random generator.
rand.Seed(time.Now().UnixNano())
The generator sequence
let d = SystemTime::now()
This initializes the default Source. .duration_since(SystemTime::UNIX_EP
will be different at each
run. OCH)
Alternative implementation:
.expect("Duration since UNIX_EPOCH
import "math/rand" failed");
import "time" let mut rng = StdRng::seed_from_u64(d.a
s_secs());
r := rand.New(rand.NewSource(time.Now
().UnixNano()))

r is of type *rand.Rand.
71 Echo program
implementation import "fmt" use std::env;
Basic implementation of import "os"
the Echo program: Print import "strings" println!("{}", env::args().skip(1).coll
all arguments except the
ect::<Vec<_>>().join(" "));
program name, func main() {
separated by space, fmt.Println(strings.Join(os.Args
Alternative implementation:
followed by newline. [1:], " "))
The idiom demonstrates
} use itertools::Itertools;
how to skip the first
println!("{}", std::env::args().skip
argument if necessary,
(1).format(" "));
concatenate arguments
as strings, append
newline and print it to
stdout.
73 Create a factory
Create a factory named
type ParentFactory func(string) Parent use core::fmt::Debug;
fact for any sub class of use std::str::FromStr;
Parent and taking var fact ParentFactory = func(str strin
exactly one string str as g) Parent { fn fact<Parent: std::str::FromStr>(str:
constructor parameter. return Parent{ String, _: Parent) -> Parent where <Par
name: str, ent as FromStr>::Err: Debug
} {
} return str.parse::<Parent>().unwrap
();
A Factory is a function which returns an object. }

Go doesn't have subtyping, but Parent could be any type:


struct, interface, etc.
74 Compute GCD
Compute the greatest import "math/big" extern crate num;
common divisor x of big
integers a and b. Use an
x.GCD(nil, nil, a, b) use num::Integer;
integer type able to use num::bigint::BigInt;
The first two arguments can be ignored in this use case.
handle huge numbers.
let x = a.gcd(&b);
x, a, b have pointer type *big.Int .
Uses the num crate's Integer trait.
75 Compute LCM
Compute the least import "math/big" extern crate num;
common multiple x of big
integers a and b. Use an
gcd.GCD(nil, nil, a, b) use num::Integer;
integer type able to
x.Div(a, gcd).Mul(x, b) use num::bigint::BigInt;
handle huge numbers.
LCM is not in the standard library, but can be deduced from let x = a.lcm(&b);
GCD.
Part of the num crate's Integer trait.
gcd divides a, by definition.

Chaining is permitted and idiomatic.

a, b, gcd, x have pointer type *big.Int.


76 Binary digits from an
integer import "strconv" let s = format!("{:b}", x);
Create the string s of
s := strconv.FormatInt(x, 2) Formatting lets you choose another representation (e.g., `b`
integer x written in base
for binary, `X` for hex in upper case and `?` for debug
2.
Here x has the type int64. output).

E.g. 13 -> "1101" Alternative implementation:


For very big numbers, prefer the type *big.Int.
let s = format!("{x:b}");
Alternative implementation:

import "fmt"
import "math/big"

s := fmt.Sprintf("%b", x)

x has the type *big.Int.

This works because *big.Int implements the fmt.Formatter


interface.
77 Complex number
Declare a complex x and
x := 3i - 2 extern crate num;
initialize it with value (3i - x *= 1i use num::Complex;
2). Then multiply it by i.
complex128 is a built-in type. let mut x = Complex::new(-2, 3);
x *= Complex::i();
1i denotes the imaginary unit i.
78 "do while" loop
Execute a block once,
for{ loop {
someThing() doStuff();
then execute it again as
long as boolean
someOtherThing() if !c { break; }
condition c is true.
if !c { }
break
} Rust has no do-while loop with syntax sugar. Use loop and
} break.

Go has no do while loop, use the for loop, instead. Alternative implementation:

while {
Alternative implementation:
doStuff();
for done := false; !done; { c
someThing() } { /* EMPTY */ }
someOtherThing()
done = !c() Use compound expression for the while loop condition.
}

Explicit loop variable done shows the intent.


79 Convert integer to
floating point number y := float64(x) let y = x as f64;
Declare the floating point
The cast must be explicit.
number y and initialize it
with the value of the
integer x .
80 Truncate floating point
number to integer y := int(x) let y = x as i32;
Declare integer y and
initialize it with the value
of floating point number
x . Ignore non-integer
digits of x .
Make sure to truncate
towards zero: a negative
x must yield the closest
greater integer (not
lesser).
81 Round floating point
number to integer import "math" let y = x.round() as i64;
Declare the integer y
and initialize it with the
y := int(math.Floor(x + 0.5))
rounded value of the
floating point number x .
Ties (when the fractional
part of x is exactly .5)
must be rounded up (to
positive infinity).
82 Count substring
occurrences import "strings" let c = s.matches(t).count();
Find how many times
x := strings.Count(s, t) Disjoint matches: overlapping occurrences are not counted.
string s contains
substring t.
Count counts only the number of non-overlapping
Specify if overlapping
instances of t.
occurrences are
counted.
83 Regex with character
repetition import "regexp" extern crate regex;
Declare regular use regex::Regex;
expression r matching
r := regexp.MustCompile("htt+p")
strings "http", "htttp",
let r = Regex::new(r"htt+p").unwrap();
"httttp", etc.
In order to avoid compiling the regex in every iteration of a
loop, put it in a lazy static or something.
84 Count bits set in
integer binary
func PopCountUInt64(i uint64) (c int) { let c = i.count_ones();
representation
i -= (i >> 1) & 0x5555555555555
555 i must have an explicit type, i.e.
Count number c of 1s in 6i64 or 6usize
the integer i in base 2.
i = (i>>2)&0x3333333333333333 +
i&0x3333333333333333
E.g. i=6 → c=2
i += i >> 4
i &= 0x0f0f0f0f0f0f0f0f
i *= 0x0101010101010101
return int(i >> 56)
}

func PopCountUInt32(i uint32) (n int) {


i -= (i >> 1) & 0x55555555
i = (i>>2)&0x33333333 + i&0x333
33333
i += i >> 4
i &= 0x0f0f0f0f
i *= 0x01010101
return int(i >> 24)
}

This was useful only before go 1.9.


See math/bits.OnesCount instead.

Alternative implementation:

import "math/bits"

c := bits.OnesCount(i)

i is a uint.
All OnesCountX functions take unsigned integer types.
85 Check if integer
addition will overflow import "math" fn adding_will_overflow(x: usize, y: us
Write boolean function
ize) -> bool {
addingWillOverflow
func addingWillOverflow(x int, y int) b x.checked_add(y).is_none()
which takes two integers ool { }
x, y and return true if if x > 0 {
return y > math.MaxInt- checked_add is available for all integer types.
(x+y) overflows.
x
An overflow may be
}
above the max positive
return y < math.MinInt-x
value, or below the min
}
negative value.
86 Check if integer
multiplication will func multiplyWillOverflow(x, y uint64) fn multiply_will_overflow(x: i64, y: i6
overflow
bool { 4) -> bool {
Write boolean function
if x <= 1 || y <= 1 { x.checked_mul(y).is_none()
multiplyWillOverflow
return false }
which takes two integers }
d := x * y checked_mul is available on all integer types
x, y and return true if
(x*y) overflows. return d/y != x
}
An overflow may be
This holds for uint64, not for signed integers.
above the max positive
Note that the multiplication is performed, then its result is
value, or below the min
checked.
negative value.
87 Stop program
Exit immediately. import "os" std::process::exit(0);
If some extra cleanup
os.Exit(0) No destructors on the current stack or any other thread's
work is executed by the
stack will be run.
program runtime (not by
the OS itself), describe
it.
88 Allocate 1M bytes
Create a new bytes
buf := make([]byte, 1_000_000) let buf: Vec<u8> = Vec::with_capacity(1
buffer buf of size
000000);
This creates a slice with all values initialized at zero.
1,000,000.
This creates a simple but fast vector. There is also the
unstable alloc::heap::allocate if you want to go more low-
level.
89 Handle invalid
argument
return nil, fmt.Errorf("invalid value f enum CustomError { InvalidAnswer }
You've detected that the
or x: %v", x)
integer value of
fn do_stuff(x: i32) -> Result<i32, Cust
The last return parameter of the current function has type omError> {
argument x passed to error.
the current function is
if x != 42 {
It is the caller's responsibility to check if the error is nil, Err(CustomError::InvalidAnswer)
invalid. Write the
before using the function's other result values. } else {
idiomatic way to abort
the function execution
Ok(x)
and signal the problem.
}
}

A function that can have invalid inputs should not panic, but
return a Result. The calling function can then determine
whether to handle the Err value or unwrap the Result and
turn every Err into a panic.
90 Read-only outside
Expose a read-only
type Foo struct { struct Foo {
integer x to the outside
x int x: usize
world while being
} }
writable inside a
structure or a class Foo. func (f *Foo) X() int { impl Foo {
return f.x pub fn new(x: usize) -> Self {
} Foo { x }
}
x is private, because it is not capitalized.
(*Foo).X is a public getter (a read accessor). pub fn x<'a>(&'a self) -> &'a usize
{
&self.x
}

pub fn bar(&mut self) {


self.x += 1;
}
}

91 Load JSON file into


object import "encoding/json" #[macro_use] extern crate serde_deriv
Read from the file import "os" e;
data.json and write its extern crate serde_json;
buffer, err := os.ReadFile("data.json") use std::fs::File;
content into the object x.
Assume the JSON data
if err != nil {
is suitable for the type of
return err let x = ::serde_json::from_reader(Fil
x.
} e::open("data.json")?)?;
err = json.Unmarshal(buffer, &x)
if err != nil { Requires x implements Deserialize from serde.
return err Serde is used to create an object from data, rather than
} populate an existing object.

buffer is a []byte.
&x is the address of x.
You must check errors after each step.

Alternative implementation:

import "encoding/json"

r, err := os.Open(filename)
if err != nil {
return err
}
decoder := json.NewDecoder(r)
err = decoder.Decode(&x)
if err != nil {
return err
}

Create and use a *json.Decoder


92 Save object into JSON
file import "encoding/json" extern crate serde_json;
Write the contents of the import "os" #[macro_use] extern crate serde_deriv
object x into the file e;
data.json.
buffer, err := json.MarshalIndent(x,
"", " ") use std::fs::File;
if err != nil {
return err ::serde_json::to_writer(&File::create
} ("data.json")?, &x)?
err = os.WriteFile("data.json", buffer,
0644) This requires x to implement Deserialize from serde.

json.MarshalIndent is more human-readable than


json.Marshal.
93 Pass a runnable
procedure as
func control(f func()) { fn control(f: impl Fn()) {
parameter
f() f();
Implement the procedure } }
control which receives
Go supports first class functions, higher-order functions,
one parameter f, and
user-defined function types, function literals, and closures.
runs f.
94 Print the type of a
variable import "reflect" #![feature(core_intrinsics)]
Print the name of the
type of x. Explain if it is a fmt.Println(reflect.TypeOf(x)) fn type_of<T>(_: &T) -> &'static str {
static type or dynamic std::intrinsics::type_name::<T>()
This prints the dynamic type of x. }
type.
Alternative implementation:
This may not make
println!("{}", type_of(&x));
fmt.Printf("%T", x)
sense in all languages.
As of 2020-09 this is a nightly-only experimental API.
This prints the dynamic type of x.
95 Get file size
Assign to variable x the import "os" use std::fs;
length (number of bytes)
of the local file at path.
info, err := os.Stat(path) let x = fs::metadata(path)?.len();
if err != nil {
return err
Alternative implementation:
}
x := info.Size() let x = path.metadata()?.len();

info has type os.FileInfo . path has type &std::path::Path


96 Check string prefix
Set boolean b to true if import "strings" let b = s.starts_with(prefix);
string s starts with prefix
b := strings.HasPrefix(s, prefix)
prefix, false otherwise.

97 Check string suffix


Set boolean b to true if import "strings" let b = s.ends_with(suffix);
string s ends with string
suffix, false otherwise. b := strings.HasSuffix(s, suffix)

98 Epoch seconds to date


object import "time" extern crate chrono;
Convert a timestamp ts use chrono::prelude::*;
(number of seconds in
d := time.Unix(ts, 0)
epoch-time) to a date
let d = NaiveDateTime::from_timestamp(t
ts has type int64. s, 0);
with time d. E.g. 0 ->
The second argument is nanoseconds.
1970-01-01 00:00:00
99 Format date YYYY-MM-
DD import "time" extern crate chrono;
Assign to the string x the use chrono::prelude::*;
value of the fields (year,
x := d.Format("2006-01-02")
month, day) of the date
Utc::today().format("%Y-%m-%d")
d has type time.Time
d, in format YYYY-MM-
DD. Alternative implementation:

use time::macros::format_description;

let format = format_description!("[yea


r]-[month]-[day]");
let x = d.format(&format).expect("Faile
d to format the date");

time crate is better maintained.


100 Sort by a comparator
Sort elements of array- import "sort" items.sort_by(c);
like collection items,
using a comparator c. type ItemCSorter []Item
func (s ItemCSorter) Len() int
{ return len(s) }
func (s ItemCSorter) Less(i, j int) boo
l { return c(s[i], s[j]) }
func (s ItemCSorter) Swap(i, j int)
{ s[i], s[j] = s[j], s[i] }

func sortItems(items []Item) {


sorter := ItemCSorter(items)
sort.Sort(sorter)
}

c has type func(Item, Item) bool.

Alternative implementation:

import "sort"

type ItemsSorter struct {


items []Item
c func(x, y Item) bool
}

func (s ItemsSorter) Len() int


{ return len(s.items) }
func (s ItemsSorter) Less(i, j int) boo
l { return s.c(s.items[i], s.items[j])
}
func (s ItemsSorter) Swap(i, j int)
{ s.items[i], s.items[j] = s.items[j],
s.items[i] }

func sortItems(items []Item, c func(x,


y Item) bool) {
sorter := ItemsSorter{
items,
c,
}
sort.Sort(sorter)
}

ItemsSorter contains c, which can be any comparator


decided at runtime.

Alternative implementation:

import "sort"

sort.Slice(items, func(i, j int) bool {


return c(items[i], items[j])
})

Since Go 1.8, a single func parameter is sufficient to sort a


slice.

Alternative implementation:

import "golang.org/x/exp/slices"

slices.SortFunc(items, c)

SortFunc is generic and type-safe at compile time.


101 Load from HTTP GET
request into a string import "io" extern crate reqwest;
Make an HTTP request import "net/http" use reqwest::Client;
with method GET to the
URL u, then store the res, err := http.Get(u) let client = Client::new();
body of the response in
if err != nil { let s = client.get(u).send().and_then(|
the string s.
return err res| res.text())?;
}
buffer, err := io.ReadAll(res.Body)
Alternative implementation:
res.Body.Close()
if err != nil { [dependencies]
return err ureq = "1.0"
}
s := string(buffer) let s = ureq::get(u).call().into_string
()?;
res has type *http.Response.
buffer has type []byte.
Alternative implementation:
It is idiomatic and strongly recommended to check errors at
each step. [dependencies]
error-chain = "0.12.4"
reqwest = { version = "0.11.2", featu
res = ["blocking"] }

use error_chain::error_chain;
use std::io::Read;

let mut response = reqwest::blocking::g


et(u)?;
let mut s = String::new();
response.read_to_string(&mut s)?;

This is a synchronous (blocking) reqwest call.

The [dependencies] section goes to cargo.toml. The


optional feature blocking must be explicit.
102 Load from HTTP GET
request into a file import "fmt" extern crate reqwest;
Make an HTTP request import "io" use reqwest::Client;
with method GET to the import "net/http" use std::fs::File;
URL u, then store the
body of the response in out, err := os.Create("result.txt") let client = Client::new();
the file result.txt. Try to
if err != nil { match client.get(&u).send() {
save the data as it
return err Ok(res) => {
arrives if possible,
} let file = File::create("resul
without having all its defer out.Close() t.txt")?;
content in memory at ::std::io::copy(res, file)?;
once. resp, err := http.Get(u) },
if err != nil { Err(e) => eprintln!("failed to send
return err request: {}", e),
} };
defer func() {
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()
if resp.StatusCode != 200 {
return fmt.Errorf("Status: %v",
resp.Status)
}

_, err = io.Copy(out, resp.Body)


if err != nil {
return err
}

resp has type *http.Response.


It is idiomatic and strongly recommended to check errors at
each step, except for the calls to Close.
103 Load XML file into
struct import "encoding/xml"
Read from the file import "os"
data.xml and write its
contents into the object buffer, err := os.ReadFile("data.xml")
x.
if err != nil {
Assume the XML data is
return err
suitable for the type of x.
}
err = xml.Unmarshal(buffer, &x)
if err != nil {
return err
}

buffer is a []byte.
&x is the address of x.
You must check errors after each step.
104 Save object into XML
file import "encoding/xml"
Write the contents of the import "os"
object x into the file
data.xml.
buffer, err := xml.MarshalIndent(x, "",
" ")
if err != nil {
return err
}
err = os.WriteFile("data.xml", buffer,
0644)

xml.MarshalIndent is more human-readable than


xml.Marshal.
105 Current executable
name import "os" fn get_exec_name() -> Option<String> {
Assign to the string s the import "path/filepath" std::env::current_exe()
name of the currently
.ok()
executing program (but
path := os.Args[0] .and_then(|pb| pb.file_name().m
not its full path).
s = filepath.Base(path) ap(|s| s.to_os_string()))
.and_then(|s| s.into_string().o
The program path is its "0th argument". k())
}
Alternative implementation:

import ( fn main() -> () {


"os" let s = get_exec_name().unwrap();
"path/filepath" println!("{}", s);
) }

path, err := os.Executable()


Alternative implementation:
if err != nil {
panic(err) let s = std::env::current_exe()
} .expect("Can't get the exec path")
s = filepath.Base(path) .file_name()
.expect("Can't get the exec name")
Executable function is supported since 1.8 .to_string_lossy()
.into_owned();

106 Get program working


directory import "os" use std::env;
Assign to string dir the
path of the working dir, err := os.Getwd() let dir = env::current_dir().unwrap();
directory.
dir has type PathBuf
(This is not necessarily
the folder containing the
executable itself)
107 Get folder containing
current program import "os" let dir = std::env::current_exe()?
Assign to string dir the import "path/filepath" .canonicalize()
path of the folder .expect("the current exe should exi
containing the currently
programPath := os.Args[0] st")
running executable.
absolutePath, err := filepath.Abs(progr .parent()
(This is not necessarily
amPath) .expect("the current exe should be
the working directory, if err != nil { a file")
though.) return err .to_string_lossy()
} .to_owned();
dir := filepath.Dir(absolutePath)
Rust doesn't represent paths as Strings, so we need to
convert the Path returned from Path::parent. This code
chooses to do this lossily, replacing characters it doesn't
recognize with �
109 Number of bytes of a
type import "reflect" let n = ::std::mem::size_of::<T>();
Set n to the number of
var t T n is "the offset in bytes between successive elements in an
bytes of a variable t (of
tType := reflect.TypeOf(t) array with item type T"
type T).
n := tType.Size()

This run-time reflection works on a value of the type T.


Note that the size does not include the memory indirectly
taken by the reference fields: Strings, slices, etc.
Warning: for a given program, the size of a type is not the
same on a 32-bit machine or a 64-bit machine.
110 Check if string is blank
Set the boolean blank to import "strings" let blank = s.trim().is_empty();
true if the string s is
empty, or null, or
blank := strings.TrimSpace(s) == ""
Alternative implementation:
contains only whitespace
Trim s, then check if empty. let blank = s.chars().all(|c| c.is_whit
; false otherwise.
espace());

111 Launch other program


From current process, import "os/exec" use std::process::Command;
run program x with
command-line
err := exec.Command("x", "a", "b").Run let output = Command::new("x")
parameters "a", "b".
() .args(&["a", "b"])
.spawn()
x's output is ignored. .expect("failed to execute proces
To access it, see (*Cmd).Output, (*Cmd).StdoutPipe, etc. s");

spawn() executes x as a child process without waiting for it


to complete

Alternative implementation:

use std::process::Command;

let output = Command::new("x")


.args(&["a", "b"])
.output()
.expect("failed to execute proc
ess");

output() waits for x to complete and collects its output

Alternative implementation:

use std::process::Command;

let output = Command::new("x")


.args(&["a", "b"])
.status()
.expect("failed to execute proc
ess");

status() waits for x to complete and collects its exit status


112 Iterate over map
entries, ordered by import "fmt" for (k, x) in mymap {
keys import "sort" println!("({}, {})", k, x);
Print each key k with its
}
value x from an
keys := make([]string, 0, len(mymap))
for k := range mymap { This assumes mymap is a BTreeMap as it is sorted by the
associative array
keys = append(keys, k) keys.
mymap, in ascending
order of k. }
sort.Strings(keys)

for _, k := range keys {


x := mymap[k]
fmt.Println("Key =", k, ", Valu
e =", x)
}

First extract the keys, then sort them, then iterate.


Adapt for key types other than string.

Alternative implementation:

import "fmt"
import "golang.org/x/exp/maps"
import "golang.org/x/exp/slices"

keys := maps.Keys(mymap)
slices.Sort(keys)

for _, k := range keys {


x := mymap[k]
fmt.Println("Key =", k, ", Valu
e =", x)
}

This works for any map whose value type is in


constraints.Ordered : integers, floats, strings

Alternative implementation:

import "fmt"
import "golang.org/x/exp/maps"
import "golang.org/x/exp/slices"

keys := maps.Keys(mymap)
slices.SortFunc(keys, less)

for _, k := range keys {


x := mymap[k]
fmt.Println("Key =", k, ", Valu
e =", x)
}

less is a custom comparator


113 Iterate over map
entries, ordered by import "fmt" use itertools::Itertools;
values import "sort"
Print each key k with its
for (k, x) in mymap.iter().sorted_by_ke
value x from an
type entry struct { y(|x| x.1) {
associative array
key string println!("[{},{}]", k, x);
mymap, in ascending value int }
order of x. }
Requires the itertools crate
Multiple entries may
exist for the same value
type entries []entry
Alternative implementation:
x.
func (list entries) Len() int { return
len(list) } let mut items: Vec<_> = mymap.iter().co
func (list entries) Less(i, j int) bool llect();
{ return list[i].value < list[j].value items.sort_by_key(|item| item.1);
} for (k, x) in items {
func (list entries) Swap(i, j int) { li println!("[{},{}]", k, x);
st[i], list[j] = list[j], list[i] } }

entries := make(entries, 0, len(mymap))


for k, x := range mymap {
entries = append(entries, entry
{key: k, values: x})
}
sort.Sort(entries)

for _, e := range entries {


fmt.Println("Key =", e.key, ",
Value =", e.value)
}

Define custom types entry and entries.


Then create a flat list of entries, and sort it.

Alternative implementation:

import "fmt"
import "sort"

type entry struct {


key string
value int
}

entries := make([]entry, 0, len(mymap))


for k, x := range mymap {
entries = append(entries, entry
{key: k, value: x})
}
sort.Slice(entries, func(i, j int) bool
{
return entries[i].value < entri
es[j].value
})

for _, e := range entries {


fmt.Println("Key =", e.key, ",
Value =", e.value)
}

Using sort.Slice incurs slightly less boilerplate than


sort.Sort.
114 Test deep equality
Set boolean b to true if import "reflect" let b = x == y;
objects x and y contain
b := reflect.DeepEqual(x, y) The == operator can only be used by having a type
the same values,
implement PartialEq.
recursively comparing all
This uses run-time reflection.
referenced elements in x
DeepEqual correctly handles recursive types.
and y.
Tell if the code correctly
handles recursive types.
115 Compare dates
Set boolean b to true if import "time" extern crate chrono;
date d1 is strictly before use chrono::prelude::*;
date d2 ; false b := d1.Before(d2)
otherwise. let b = d1 < d2;
d1, d2 have type time.Time.
116 Remove occurrences
of word from string import "strings" s2 = s1.replace(w, "");
Remove all occurrences
of string w from string
s2 := strings.Replace(s1, w, "", -1) Alternative implementation:
s1, and store the result
Replaces w with empty string. -1 means "replace all let s2 = str::replace(s1, w, "");
in s2.
occurrences".

Alternative implementation:

import "strings"

s2 := strings.ReplaceAll(s1, w, "")

117 Get list size


Set n to the number of
n := len(x) let n = x.len();
elements of the list x.
x is a slice or an array.
118 List to set
Create the set y from the y := make(map[T]struct{}, len(x)) use std::collections::HashSet;
list x. for _, v := range x {
x may contain
y[v] = struct{}{} let y: HashSet<_> = x.into_iter().colle
duplicates. y is
} ct();
unordered and has no
Iterate to add each item to the map.
repeated values.
T is the type of the items.

Alternative implementation:
func sliceToSet[T comparable](x []T) ma
p[T]struct{} {
y := make(map[T]struct{}, len
(x))
for _, v := range x {
y[v] = struct{}{}
}
return y
}

sliceToSet is generic. Its type parameter T has a constraint:


must be comparable with ==.
119 Deduplicate list
Remove duplicates from y := make(map[T]struct{}, len(x)) x.sort();
the list x.
for _, v := range x { x.dedup();
Explain if the original
y[v] = struct{}{}
} Deduplication in place. Original order not maintained. Works
order is preserved.
x2 := make([]T, 0, len(y)) O(n*log(n))
for _, v := range x {
Alternative implementation:
if _, ok := y[v]; ok {
x2 = append(x2, v) use itertools::Itertools;
delete(y, v)
} let dedup: Vec<_> = x.iter().unique().c
} ollect();
x = x2

Original order is preserved.


T is the type of the items.
Iterate twice, from list to map, then from map to list.

This is O(n).

Alternative implementation:

seen := make(map[T]bool)
j := 0
for _, v := range x {
if !seen[v] {
x[j] = v
j++
seen[v] = true
}
}
x = x[:j]

The order is preserved.


Use this if T is not a pointer type or reference type.

This is O(n).

Alternative implementation:

seen := make(map[T]bool)
j := 0
for _, v := range x {
if !seen[v] {
x[j] = v
j++
seen[v] = true
}
}
for i := j; i < len(x); i++ {
x[i] = nil
}
x = x[:j]

Order is preserved.
Use this if T is a pointer type or reference type.
Discarded slots are set to nil, to avoid a memory leak.

This is O(n).

Alternative implementation:
func deduplicate[S ~[]T, T comparable]
(x S) S {
seen := make(map[T]bool)
j := 0
for _, v := range x {
if !seen[v] {
x[j] = v
j++
seen[v] = true
}
}
var zero T
for i := j; i < len(x); i++ {
// Avoid memory leak
x[i] = zero
}
return x[:j]
}

deduplicate is generic. Its type parameter T has a


constraint: must be comparable with ==.
The order is preserved.
120 Read integer from
stdin import "fmt" fn get_input() -> String {
Read an integer value
let mut buffer = String::new();
from the standard input
_, err := fmt.Scan(&n) std::io::stdin().read_line(&mut buf
into the variable n fer).expect("Failed");
Warning: if the input has a leading 0, it will be interpreted buffer
as octal! }
Alternative implementation:
let n = get_input().trim().parse::<i64>
import "fmt" ().unwrap();

_, err := fmt.Scanf("%d", &n) Change i64 to what you expect to get. Do not use unwrap()
if you're not sure it will be parsed correctly.

Alternative implementation:

use std::io;

let mut input = String::new();


io::stdin().read_line(&mut input).unwra
p();
let n: i32 = input.trim().parse().unwra
p();

Alternative implementation:

use std::io::BufRead;

let n: i32 = std::io::stdin()


.lock()
.lines()
.next()
.expect("stdin should be availabl
e")
.expect("couldn't read from stdin")
.trim()
.parse()
.expect("input was not an intege
r");

Alternative implementation:

#[macro_use] extern crate text_io;

let n: i32 = read!();

Can also parse several values and types and delimiters with
scan!()

Also see Rust RFC #3183


121 UDP listen and read
Listen UDP traffic on import ( use std::net::UdpSocket;
port p and read 1024 "fmt"
bytes into buffer b. "net" let mut b = [0 as u8; 1024];
"os" let sock = UdpSocket::bind(("localhos
) t", p)).unwrap();
sock.recv_from(&mut b).unwrap();
ServerAddr,err := net.ResolveUDPAddr("u
dp",p)
if err != nil {
return err
}
ServerConn, err := net.ListenUDP("udp",
ServerAddr)
if err != nil {
return err
}
defer ServerConn.Close()
n,addr,err := ServerConn.ReadFromUDP(b
[:1024])
if err != nil {
return err
}
if n<1024 {
return fmt.Errorf("Only %d byte
s could be read.", n)
}

122 Declare an
enumeration
type Suit int enum Suit {
Spades,
Create an enumerated
type Suit with 4 possible
const ( Hearts,
values SPADES,
Spades Suit = iota Diamonds,
HEARTS, DIAMONDS,
Hearts Clubs,
CLUBS.
Diamonds }
Clubs
)

Go doesn't have enumerations.


The 4 constants have values 0, 1, 2, 3.
123 Assert condition
Verify that predicate if !isConsistent() { assert!(is_consistent);
isConsistent returns panic("State consistency violat
true, otherwise report ed")
assertion violation. }
Explain if the assertion is
Go doesn't provide assertions.
executed even in
But it's still possible to crash when desired.
production environment
or not.
124 Binary search for a
value in sorted array
func binarySearch(a []T, x T) int { a.binary_search(&x).unwrap_or(-1);
Write the function
imin, imax := 0, len(a)-1
for imin <= imax { This only works if a is an array of signed integers.
binarySearch which
imid := imin + (imax-im Generally, a Result or Option would be more useful.
returns the index of an
element having the value in) / 2
x in the sorted array a,
switch {
or -1 if no such element
case a[imid] == x:
exists.
return imid
case a[imid] < x:
imin = imid + 1
default:
imax = imid - 1
}
}
return -1
}

Iterative algorithm.
It does not always return the smallest possible index.
You may implement this for any element type T that is
ordered.

Alternative implementation:

import "sort"

func binarySearch(a []int, x int) int {


i := sort.SearchInts(a, x)
if i < len(a) && a[i] == x {
return i
}
return -1
}

If the elements have type int, then use standard library's


sort.SearchInts.
It returns the smallest matching index.

Alternative implementation:

import "sort"

func binarySearch(a []T, x T) int {


f := func(i int) bool { return
a[i] >= x }
i := sort.Search(len(a), f)
if i < len(a) && a[i] == x {
return i
}
return -1
}

This uses the standard library generic-purpose sort.Search.


Read the documentation carefully.
It returns the smallest matching index.

Alternative implementation:

import "golang.org/x/exp/slices"

func binarySearch(a []T, x T) int {


if i, ok := slices.BinarySearch
(a, x); ok {
return i
} else {
return -1
}
}

This generic func slices.BinarySearch works for all slice


types
125 Measure function call
duration import "time" use std::time::{Duration, Instant};
measure the duration t,
in nanoseconds, of a call t1 := time.Now() let start = Instant::now();
to the function foo. Print foo() foo();
this duration.
t := time.Since(t1) let duration = start.elapsed();
ns := int64(t / time.Nanosecond) println!("{}", duration);
fmt.Printf("%dns\n", ns)

t1 has type time.Time.


t has type time.Duration.

Alternative implementation:

import "time"

t1 := time.Now()
foo()
t := time.Since(t1)
ns := t.Nanoseconds()
fmt.Printf("%dns\n", ns)

t1 has type time.Time.


t has type time.Duration.
ns has type int64.
126 Multiple return values
Write a function foo that func foo() (string, bool) { fn foo() -> (String, bool) {
returns a string and a return "Too good to be", true (String::from("bar"), true)
boolean value.
} }

127 Source code inclusion


Import the source code
fn main() {
include!("foobody.txt");
for the function foo body
from a file "foobody.txt".
}

"foobody.txt" must contain a single Rust expression. If you


need several, enclose them in braces.
128 Breadth-first traversing
of a tree func (root *Tree) Bfs(f func(*Tree)) { use std::collections::VecDeque;
Call a function f on every if root == nil {
node of a tree, in
return struct Tree<V> {
breadth-first prefix order
} children: Vec<Tree<V>>,
queue := []*Tree{root} value: V
for len(queue) > 0 { }
t := queue[0]
queue = queue[1:] impl<V> Tree<V> {
f(t) fn bfs(&self, f: impl Fn(&V)) {
queue = append(queue, let mut q = VecDeque::new();
t.Children...) q.push_back(self);
}
} while let Some(t) = q.pop_front
() {
Bfs is a method of type *Tree, and takes function f as an (f)(&t.value);
argument. for child in &t.children {
q.push_back(child);
The queue grows and shrinks during traversal, until all }
nodes have been visited. }
}
}
129 Breadth-first traversal
in a graph func (start *Vertex) Bfs(f func(*Verte use std::rc::{Rc, Weak};
Call the function f on x)) { use std::cell::RefCell;
every vertex accessible queue := []*Vertex{start}
from the vertex start, in seen := map[*Vertex]bool{start: struct Vertex<V> {
breadth-first prefix order
true} value: V,
for len(queue) > 0 { neighbours: Vec<Weak<RefCell<Ve
v := queue[0] rtex<V>>>>,
queue = queue[1:] }
f(v)
for next, isEdge := ran // ...
ge v.Neighbours {
if isEdge && !s fn bft(start: Rc<RefCell<Vertex<V>>>,
een[next] { f: impl Fn(&V)) {
queue = let mut q = vec![start];
append(queue, next) let mut i = 0;
seen[ne while i < q.len() {
xt] = true let v = Rc::clone(&q[i]);
} i += 1;
} (f)(&v.borrow().value);
} for n in &v.borrow().neighb
} ours {
let n = n.upgrade().exp
Bfs is a method of type *Vertex : the receiver is the start ect("Invalid neighbour");
node. if q.iter().all(|v| v.a
The function f is a parameter of the traversal method. s_ptr() != n.as_ptr()) {
q.push(n);
}
}
}
}

See demo for full example.


130 Depth-first traversal in
a graph func (v *Vertex) Dfs(f func(*Vertex), s use std::rc::{Rc, Weak};
Call th function f on
een map[*Vertex]bool) { use std::cell::RefCell;
every vertex accessible seen[v] = true
from the vertex v, in f(v) struct Vertex<V> {
depth-first prefix order for next, isEdge := range v.Nei value: V,
ghbours { neighbours: Vec<Weak<RefCell<Ve
if isEdge && !seen[nex rtex<V>>>>,
t] { }
next.Dfs(f, see
n) // ...
}
} fn dft_helper(start: Rc<RefCell<Vertex<
} V>>>, f: &impl Fn(&V), s: &mut Vec<*con
st Vertex<V>>) {
Dfs is a method of type *Vertex : the receiver is the start s.push(start.as_ptr());
node. (f)(&start.borrow().value);
The function f is a parameter of the traversal method. for n in &start.borrow().neighb
Start with an empty map as initial seen parameter. ours {
let n = n.upgrade().exp
Alternative implementation:
ect("Invalid neighbor");
func (v *Vertex[L]) Dfs(f func(*Vertex if s.iter().all(|&p| p
[L]), seen map[*Vertex[L]]bool) { != n.as_ptr()) {
seen[v] = true Self::dft_helpe
f(v) r(n, f, s);
for next, isEdge := range v.Nei }
ghbours { }
if isEdge && !seen[nex }
t] {
next.Dfs(f, see See demo for full example.
n)
}
}
}

Dfs is a method of type *Vertex : the receiver is the start


node.
The function f is a parameter of the traversal method.
Start with an empty map as initial seen parameter.
Vertex has a type parameter L as its node label.
131 Successive conditions
Execute f1 if condition
switch { if c1 { f1() } else if c2 { f2() } else
case c1: if c3 { f3() }
c1 is true, or else f2 if
condition c2 is true, or
f1()
case c2: Using if and else
else f3 if condition c3 is
f2()
true. Alternative implementation:
Don't evaluate a
case c3:
f3() match true {
condition when a
} _ if c1 => f1(),
previous condition was
_ if c2 => f2(),
true.
_ if c3 => f3(),
_ => (),
}

Using match and guards


132 Measure duration of
procedure execution import "time" use std::time::Instant;
Run the procedure f, and
return the duration of the func clock(f func()) time.Duration { let start = Instant::now();
execution of f. t := time.Now() f();
f() let duration = start.elapsed();
return time.Since(t)
} duration is a std::time::Duration, which can be converted
into seconds with as_secs()
You may use this clock function to time any piece of code,
by wrapping the code in a closure of type func().
133 Case-insensitive string
contains import "strings" extern crate regex;
Set boolean ok to true if use regex::Regex;
string word is contained
lowerS, lowerWord := strings.ToLower
in string s as a substring, (s), strings.ToLower(word) let re = Regex::new(&format!("(?i){}",
even if the case doesn't ok := strings.Contains(lowerS, lowerWor regex::escape(word))).unwrap();
match, or to false d) let ok = re.is_match(&s);
otherwise.
Package strings has no case-insensitive version of
Contains, so we have to convert to lowercase (or Alternative implementation:
uppercase) first. extern crate regex;
use regex::RegexBuilder;

let re =
RegexBuilder::new(&regex::escape(wo
rd))
.case_insensitive(true)
.build().unwrap();

let ok = re.is_match(s);

Alternative implementation:

let ok = s.to_ascii_lowercase().contain
s(&word.to_ascii_lowercase());

134 Create a new list


Declare and initialize a items := []T{a, b, c} let items = vec![a, b, c];
new list items,
This creates a slice of type T.
containing 3 elements a,
b, c.
135 Remove item from list,
by its value for i, y := range items { if let Some(i) = items.first(&x) {
Remove at most 1 item
if y == x { items.remove(i);
from list items, having items = append(items[: }
the value x. i], items[i+1:]...)
This will alter the original break
list or return a new list, }
depending on which is
}
more idiomatic.
First find a matching index i. Then remove at position i.
If there are several
occurrences of x in
Warning: you may have a memory leak at the last element
items, remove only one
of the original list, if the items have a pointer type.
of them. If x is absent,
keep items unchanged. Alternative implementation:

for i, y := range items {


if y == x {
copy(items[i:], items[i
+1:])
items[len(items)-1] = n
il
items = items[:len(item
s)-1]
break
}
}

First find a matching index i. Then remove at position i.


This code is for pointer value type, and has no memory
leak.

Alternative implementation:

import "golang.org/x/exp/slices"

func removeFirstByValue[S ~[]T, T compa


rable](items *S, x T) {
for i, y := range *items {
if y == x {
*items = slice
s.Delete(*items, i, i+1)
return
}
}
}

removeFirstByValue is generic. Its type parameter T has a


constraint: must be comparable with ==.

Alternative implementation:

import "golang.org/x/exp/slices"

func removeFirstByValue[S ~[]T, T compa


rable](items *S, x T) {
if i := slices.Index(*items,
x); i != -1 {
*items = slices.Delete
(*items, i, i+1)
}
}

removeFirstByValue is generic. Its type parameters S, T


have a constraint: T must be comparable with ==.
136 Remove all
occurrences of a value
items2 := make([]T, 0, len(items)) items = items.into_iter().filter(|&item
from a list for _, v := range items { | item != x).collect();
Remove all occurrences if v != x {
items2 = append(items2, This creates a new list.
of the value x from list
items. v)
Alternative implementation:
This will alter the original
}
} items.retain(|&item| item != x);
list or return a new list,
depending on which is items has type Vec.
This is simple and runs in linear time.
more idiomatic.
However, it allocates memory for the new slice items2.
T is the type of the elements. retain operates in place.

Alternative implementation:

j := 0
for i, v := range items {
if v != x {
items[j] = items[i]
j++
}
}
items = items[:j]

This filters items in-place in linear time.


But don't use it with pointer elements, because you would
have a memory leak at the end of the underlying array.

Alternative implementation:

j := 0
for i, v := range items {
if v != x {
items[j] = items[i]
j++
}
}
for k := j; k < len(items); k++ {
items[k] = nil
}
items = items[:j]

This filters items in-place in linear time.


The "tail" elements are set to nil to leverage garbage
collection, avoiding a memory leak.

Alternative implementation:

func removeAll[S ~[]T, T comparable](it


ems *S, x T) {
j := 0
for i, v := range *items {
if v != x {
(*items)[j] =
(*items)[i]
j++
}
}
var zero T
for k := j; k < len(*items); k+
+ {
(*items)[k] = zero
}
*items = (*items)[:j]
}

The type parameter T has a constraint: it must be


comparable with ==
In case T contains pointers, zeroing discarded elements
helps garbage collection.
137 Check if string
contains only digits b := true let chars_are_numeric: Vec<bool> = s.ch
Set the boolean b to for _, c := range s { ars()
true if the string s if c < '0' || c > '9' { .map(|c
contains only characters b = false |c.is_numeric())
in the range '0'..'9', false
break .collec
otherwise. } t();
} let b = !chars_are_numeric.contains(&fa
lse);
c has type rune.
Note that is_numeric is not just 0 -> 9.
Alternative implementation: See documentation for more info.
import "strings"
Alternative implementation:

isNotDigit := func(c rune) bool { retur let b = s.chars().all(char::is_numeri


n c < '0' || c > '9' } c);
b := strings.IndexFunc(s, isNotDigit) =
= -1
Alternative implementation:

let b = s.bytes().all(|c| c.is_ascii_di


git());

only return true for ASCII digits


138 Create temp file
Create a new temporary import "os" use tempdir::TempDir;
file on the filesystem. use std::fs::File;
tmpfile, err := os.CreateTemp("", "")
let temp_dir = TempDir::new("prefix")?;
tmpfile has type *os.File. let temp_file = File::open(temp_dir.pat
h().join("file_name"))?;
Use tmpfile.Name() if you need the path string.
TempDir deletes the directory and its contents when it is
Consider defer os.Remove(tmpfile.Name()) for cleanup. dropped.
139 Create temp directory
Create a new temporary import "os" extern crate tempdir;
folder on filesystem, for use tempdir::TempDir;
writing. dir, err := os.MkdirTemp("", "")
let tmp = TempDir::new("prefix")?;
dir is a string.

Consider defer os.RemoveAll(dir) for cleanup.


140 Delete map entry
Delete from map m the delete(m, k) use std::collections::HashMap;
entry having key k.
delete is a built-in function. m.remove(&k);
Explain what happens if
It's safe even if k is already absent from m. Returns the value at the key if the key was previously in the
k is not an existing key
map, and 'None' otherwise.
in m.
141 Iterate in sequence
over two lists for _, v := range items1 { for i in item1.iter().chain(item2.iter
Iterate in sequence over fmt.Println(v) ()) {
the elements of the list } print!("{} ", i);
items1 then items2. For
for _, v := range items2 { }
each iteration print the fmt.Println(v)
element.
}

No magic sugar. Write 2 loops.


142 Hexadecimal digits of
an integer import "strconv" let s = format!("{:X}", x);
Assign to string s the
s := strconv.FormatInt(x, 16) {:X} produces uppercase hex.
hexadecimal
{:x} produces lowercase hex.
representation (base 16)
of integer x. Alternative implementation:

import "fmt"
E.g. 999 -> "3e7"
import "math/big"

s := fmt.Sprintf("%x", x)

x has type *big.Int.

This works because *big.Int implements the fmt.Formatter


interface.

%x is the "verb" for base 16. Not to be confused with the


variable name x.
143 Iterate alternatively
over two lists
for i := 0; i < len(items1) || i < len extern crate itertools;
Iterate alternatively over (items2); i++ {
the elements of the lists
if i < len(items1) { for pair in izip!(&items1, &items2) {
items1 and items2. For fmt.Println(items1[i]) println!("{}", pair.0);
each iteration, print the } println!("{}", pair.1);
element. if i < len(items2) { }
fmt.Println(items2[i])
Explain what happens if
}
items1 and items2 have }
different size.
144 Check if file exists
Set boolean b to true if import "os" let b = std::path::Path::new(fp).exists
file at path fp exists on
();
filesystem; false _, err := os.Stat(fp)
otherwise.
b := !os.IsNotExist(err)

There's no specific existence check func in standard library,


Beware that you should
so we have to inspect an error return value.
never do this and then in
the next instruction
assume the result is still
valid, this is a race
condition on any
multitasking OS.
145 Print log line with
datetime import "log" eprintln!("[{}] {}", humantime::format_
Print message msg, rfc3339_seconds(std::time::SystemTime::
prepended by current
log.Println(msg) now()), msg);
date and time.
This prints to os.Stderr by default, with a datetime prefix. Writes an RFC3339 date to stderr with the message

Explain what behavior is


idiomatic: to stdout or
stderr, and what the
date format is.
146 Convert string to
floating point number import "strconv" let f = s.parse::<f32>().unwrap();
Extract floating point
value f from its string f, err := strconv.ParseFloat(s, 64)
Alternative implementation:
representation s
f has type float64. let f: f32 = s.parse().unwrap();
147 Remove all non-ASCII
characters import "regexp" let t = s.replace(|c: char| !c.is_ascii
Create string t from (), "");
string s, keeping only re := regexp.MustCompile("[[:^asci
ASCII characters i:]]")
Alternative implementation:
t := re.ReplaceAllLiteralString(s, "")
let t = s.chars().filter(|c| c.is_ascii
()).collect::<String>();
Alternative implementation:

import (
"fmt"
"strings"
"unicode"
)

t := strings.Map(func(r rune) rune {


if r > unicode.MaxASCII {
return -1
}
return r
}, s)

148 Read list of integers


from stdin import ( use std::{
Read a list of integer "bufio" io::{self, Read},
numbers from the "os" str::FromStr,
standard input, until "strconv" }
EOF. )
let mut string = String::new();
var ints []int io::stdin().read_to_string(&mut strin
s := bufio.NewScanner(os.Stdin) g)?;
s.Split(bufio.ScanWords) let result = string
for s.Scan() { .lines()
i, err := strconv.Atoi(s.Text .map(i32::from_str)
()) .collect::<Result<Vec<_>, _>>();
if err == nil {
ints = append(ints, i) result is a Result<Vec<i32>, ParseIntError>.
}
}
if err := s.Err(); err != nil {
return err
}

149 Rescue the princess


As an exception, this
content is not under
license CC BY-SA 3.0
like the rest of this
website.
150 Remove trailing slash
import "strings" if p.ends_with('/') { p.pop(); }
Remove the last
character from the string
p = strings.TrimSuffix(p, "/") p has type String
p, if this character is a
forward slash /
151 Remove string trailing
path separator import "fmt" let p = if ::std::path::is_separator(p.
Remove last character import "os" chars().last().unwrap()) {
from string p, if this import "strings" &p[0..p.len()-1]
character is the file path
} else {
separator of current sep := fmt.Sprintf("%c", os.PathSeparat p
platform.
or) };
p = strings.TrimSuffix(p, sep)
Note that this also Alternative implementation:
os.PathSeparator is a rune, it must be converted to string.
transforms unix root path
p = p.strip_suffix(std::path::is_separa
"/" into the empty string! Alternative implementation:
tor).unwrap_or(p);
import "fmt"
import "path/filepath"
import "strings"

sep := fmt.Sprintf("%c", filepath.Separ


ator)
p = strings.TrimSuffix(p, sep)

filepath.Separator is a rune, it must be converted to string.


152 Turn a character into a
string import "fmt" let s = c.to_string();
Create string s
containing only the s := fmt.Sprintf("%c", c)
character c.
153 Concatenate string
with integer import "fmt" let t = format!("{}{}", s, i);
Create the string t as the // or
concatenation of the t := fmt.Sprintf("%s%d", s, i) let t = format!("{s}{i}");
string s and the integer i.
Alternative implementation:

import "strconv"

t := s + strconv.Itoa(i)

This is faster than fmt.Sprintf.


154 Halfway between two
hex color codes import "fmt" use std::str::FromStr;
Find color c, the average import "strconv" use std::fmt;
between colors c1, c2.
r1, _ := strconv.ParseInt(c1[1:3], 16, "Too long for text box, see online dem
c, c1, c2 are strings of
0) o"
hex color codes: 7 chars, r2, _ := strconv.ParseInt(c2[1:3], 16,
beginning with a number 0)
sign # . r := (r1 + r2) / 2
Assume linear
computations, ignore
g1, _ := strconv.ParseInt(c1[3:5], 16,
gamma corrections. 0)
g2, _ := strconv.ParseInt(c2[3:5], 16,
0)
g := (g1 + g2) / 2

b1, _ := strconv.ParseInt(c1[5:7], 16,


0)
b2, _ := strconv.ParseInt(c2[5:7], 16,
0)
b := (b1 + b2) / 2

c := fmt.Sprintf("#%02X%02X%02X", r, g,
b)

For conciseness this assumes that input validity has


already been checked, so we omit some returned errors.

Alternative implementation:

import "fmt"
import "strconv"

var buf [7]byte


buf[0] = '#'
for i := 0; i < 3; i++ {
sub1 := c1[1+2*i : 3+2*i]
sub2 := c2[1+2*i : 3+2*i]
v1, _ := strconv.ParseInt(sub1,
16, 0)
v2, _ := strconv.ParseInt(sub2,
16, 0)
v := (v1 + v2) / 2
sub := fmt.Sprintf("%02X", v)
copy(buf[1+2*i:3+2*i], sub)
}
c := string(buf[:])

Loops over each component r, g, b.

For conciseness this assumes that input validity has


already been checked, so we omit some returned errors.
155 Delete file
Delete from filesystem import "os" use std::fs;
the file having path
filepath. err := os.Remove(filepath) let r = fs::remove_file(filepath);

r has type io::Result<()>


156 Format integer with
zero-padding import "fmt" let s = format!("{:03}", i);
Assign to the string s the
value of the integer i in 3 s := fmt.Sprintf("%03d", i)
decimal digits. Pad with
Flag 0 means "pad with zeroes, not with spaces".
zeros if i < 100. Keep all
Flag 3 is the width.
digits if i ≥ 1000.
157 Declare constant string
Initialize a constant
const planet = "Earth" const PLANET: &str = "Earth";
planet with string value Type string is inferred.
"Earth".
158 Random sublist
Create a new list y from import "math/rand" use rand::prelude::*;
randomly picking exactly
k elements from list x. y := make([]T, k) let mut rng = &mut rand::thread_rng();
perm := rand.Perm(len(x)) let y = x.choose_multiple(&mut rng, k).
It is assumed that x has for i, v := range perm[:k] { cloned().collect::<Vec<_>>();
at least k elements. y[i] = x[v]
} choose_multiple returns an Iterator.
Each element must have
same probability to be
Allocate a slice of T of size exactly k.
picked.
perm is a slice of int of size len(x).
Each element from x
This is O(len(x)) in space and runtime.
must be picked at most
once.
The original ordering is not preserved.
Explain if the original
ordering is preserved or
not.
159 Trie
Define a Trie data type Trie struct { struct Trie {
structure, where entries c rune val: String,
have an associated children map[rune]*Trie nodes: Vec<Trie>
value. isEntry bool }
(Not all nodes are
value V
entries) }

Using type rune, multi-byte characters are correctly


handled.
V is the type of the associated values.
160 Detect if 32-bit or 64-bit
import "strconv" match std::mem::size_of::<&char>() {
architecture
Execute f32() if platform
4 => f32(),
if strconv.IntSize==32 { 8 => f64(),
is 32-bit, or f64() if
platform is 64-bit.
f32() _ => {}
} }
This can be either a
if strconv.IntSize==64 {
compile-time condition Performed at run time.
(depending on target) or
f64()
}
a runtime detection.

161 Multiply all the


elements of a list for i := range elements { let elements = elements.into_iter().map
Multiply all the elements elements[i] *= c (|x| c * x).collect::<Vec<_>>();
of the list elements by a
}
constant c Alternative implementation:
It is idiomatic to write this explicit loop.
elements.iter_mut().for_each(|x| *x *=
c);

It is possible to multiply the elements of the vector in-place,


assuming you own the vector, or that you have mutably
borrowed it.
162 Execute procedures
depending on options import "flag" if let Some(arg) = ::std::env::args().n
execute bat if b is a th(1) {
program option and fox
var b = flag.Bool("b", false, "Do bat") if &arg == "f" {
if f is a program option. var f = flag.Bool("f", false, "Do fox") fox();
} else if &arg = "b" {
func main() { bat();
flag.Parse() } else {
if *b { eprintln!("invalid argument:
bar() {}", arg),
} }
if *f { } else {
fox() eprintln!("missing argument");
} }
}

It is idiomatic to use package flag, and pass options as -b -f Alternative implementation:


(with a dash). if let Some(arg) = ::std::env::args().n
th(1) {
match arg.as_str() {
"f" => fox(),
"b" => box(),
_ => eprintln!("invalid argumen
t: {}", arg),
};
} else {
eprintln!("missing argument");
}

163 Print list elements by


group of 2 import "fmt" for pair in list.chunks(2) {
println!("({}, {})", pair[0], pair
Print all the list
for i := 0; i+1 < len(list); i += 2 { [1]);
elements, two by two,
assuming list length is
fmt.Println(list[i], list[i+1]) }
}
even.

164 Open URL in the


default browser import "github.com/skratchdot/open-go use webbrowser;
Open the URL s in the lang/open"
default browser. webbrowser::open(s).expect("failed to o
Set the boolean b to b := open.Start(s) == nil pen URL");
indicate whether the
operation was Alternative implementation:
successful.
func openbrowser(url string) {
var err error

switch runtime.GOOS {
case "linux":
err = exec.Command("xdg
-open", url).Start()
case "windows":
err = exec.Command("run
dll32", "url.dll,FileProtocolHandler",
url).Start()
case "darwin":
err = exec.Command("ope
n", url).Start()
default:
err = fmt.Errorf("unsup
ported platform")
}
if err != nil {
log.Fatal(err)
}

}
165 Last element of list
Assign to the variable x x := items[len(items)-1] let x = items[items.len()-1];
the last element of the
items is a slice.
list items. Alternative implementation:
There is no shortcut, use len!
Panics if the list is empty. let x = items.last().unwrap();

x is a Vec.
last() returns an Option<&T>.
166 Concatenate two lists
Create the list ab
ab := append(a, b...) let ab = [a, b].concat();
containing all the Warning! a and ab may or may not share the same
elements of the list a, underlying memory.
followed by all the
elements of the list b. Alternative implementation:

var ab []T
ab = append(append(ab, a...), b...)

This ensures that ab is a new list (not sharing any memory


with a and b).
T is the type of the elements.

Alternative implementation:

ab := make([]T, len(a)+len(b))
copy(ab, a)
copy(ab[len(a):], b)

167 Trim prefix


Create string t consisting import "strings" let t = s.trim_start_matches(p);
of string s with its prefix
t := strings.TrimPrefix(s, p) Warning: this would remove several leading occurrences of
p removed (if s starts
p, if present.
with p).
See strip_prefix to remove only one occurrence.

Alternative implementation:

let t = if s.starts_with(p) { &s[p.len


()..] } else { s };

Alternative implementation:

let t = s.strip_prefix(p).unwrap_or(s);

Removes p at most once.


168 Trim suffix
import "strings" let t = s.trim_end_matches(w);
Create string t consisting
of string s with its suffix
t := strings.TrimSuffix(s, w) This may remove several occurrences of w at the end of s.
w removed (if s ends
with w). Alternative implementation:

let t = s.strip_suffix(w).unwrap_or(s);

Removes at most 1 occurrence of w


169 String length
Assign to the integer n import "unicode/utf8" let n = s.chars().count();
the number of characters
n := utf8.RuneCountInString(s) This is kind of roundabout because the default len method
of the string s.
gives bytes, not characters.
Make sure that multibyte
This assumes that s is encoded in UTF-8 (which is idiomatic
characters are properly
in Go).
handled.
n can be different from
the number of bytes of s.
170 Get map size
Set n to the number of n := len(mymap) let n = mymap.len();
elements stored in
mymap.

This is not always equal


to the map capacity.
171 Add an element at the
end of a list
s = append(s, x) s.push(x);
Append the element x to
the list s.
172 Insert an entry in a
map m[k] = v use std::collection::HashMap;
Insert value v for key k
If m[k] already exists, then it is overwritten. m.insert(k, v);
in map m.

173 Format a number with


grouped thousands import "golang.org/x/text/language" use separator::Separatable;
Number will be formatted import "golang.org/x/text/message"
with a comma separator println!("{}", 1000.separated_string
between every group of p := message.NewPrinter(language.Englis ());
thousands. h)
s := p.Sprintf("%d\n", 1000) Requires the separator crate

Alternative implementation:

import "github.com/floscodes/golang-t
housands"
import "strconv"

n := strconv.Itoa(23489)
s := thousands.Separate(n, "en")

This uses a third-pary package golang-thousands


174 Make HTTP POST
request import "net/http" [dependencies]
Make a HTTP request error-chain = "0.12.4"
with method POST to response, err := http.Post(u, contentTy reqwest = { version = "0.11.2", featu
the URL u
pe, body) res = ["blocking"] }

contentType is a string. use error_chain::error_chain;


body is a io.Reader which can be nil. use std::io::Read;
Alternative implementation:
let client = reqwest::blocking::Clien
import "net/http" t::new();
import "net/url" let mut response = client.post(u).body
("abc").send()?;
response, err := http.PostForm(u, formV
alues) This is a synchronous (blocking) reqwest call.

formValues has type net/url.Values The [dependencies] section goes to cargo.toml. The
optional feature blocking must be explicit.

response has type Result<Response>.


175 Bytes to hex string
From array a of n bytes, import "encoding/hex" use hex::ToHex;
build the equivalent hex
s := hex.EncodeToString(a) let s = a.encode_hex::<String>();
string s of 2n digits.
Each byte (256 possible This is faster than fmt.Sprintf
values) is encoded as Alternative implementation:
two hexadecimal Alternative implementation:
use core::fmt::Write;
characters (16 possible
import "fmt"
values per digit).
let mut s = String::with_capacity(2 *
s := fmt.Sprintf("%x", a) n);
for byte in a {
%x base 16, lower-case, two characters per byte. write!(s, "{:02X}", byte)?;
}
This is slower than hex.EncodeToString

Alternative implementation:

use data_encoding::HEXLOWER;

let s = HEXLOWER.encode(&a);
176 Hex string to byte
array import "encoding/hex" use hex::FromHex;
From hex string s of 2n
digits, build the a, err := hex.DecodeString(s) let a: Vec<u8> = Vec::from_hex(s).expec
equivalent array a of n if err != nil { t("Invalid Hex String");
bytes. log.Fatal(err)
Each pair of }
Alternative implementation:
hexadecimal characters
(16 possible values per
use hex::decode;
digit) is decoded into one
let a: Vec<u8> = decode(s).expect("Hex
byte (256 possible
string should be valid");
values).

Alternative implementation:

use data_encoding::HEXLOWER_PERMISSIV
E;

let a: Vec<u8> = HEXLOWER_PERMISSIVE.de


code(&s.into_bytes()).unwrap();

s has type String


177 Find files for a list of
filename extensions import "path/filepath" use std::path::{Path, PathBuf};
Construct a list L that import "strings"
contains all filenames let d = Path::new("/path/to/D");
that have the extension L := []string{} let l: Vec<PathBuf> = d
".jpg" , ".jpeg" or ".png" err := filepath.Walk(D, func(path strin .read_dir()?
in directory D and all its g, info os.FileInfo, err error) error { .filter_map(|f| f.ok())
subdirectories. if err != nil { .filter(|f| match f.path().extensio
fmt.Printf("failure acc n() {
essing a path %q: %v\n", path, err) None => false,
return err Some(ex) => ex == "jpg" || ex =
} = "jpeg" || ex == "png"
for _, ext := range []string{". })
jpg", ".jpeg", ".png"} { .map(|f| f.path())
if strings.HasSuffix(pa .collect();
th, ext) {
L = append(L, p The _? operator simplifies error handling. See
ath) https://doc.rust-lang.org/rust-by-
break example/std/result/question_mark.html
}
}
return nil
})

178 Check if point is inside


rectangle import "image" struct Rect {
Set boolean b to true if if x1: i32,
the point with p := image.Pt(x, y) x2: i32,
coordinates (x,y) is r := image.Rect(x1, y1, x2, y2) y1: i32,
inside the rectangle with
b := p.In(r) y2: i32,
coordinates }
Points on the edge of the rectangle are considered as in the
(x1,y1,x2,y2) , or to
rectangle. impl Rect {
false otherwise.
Describe if the edges are fn contains(&self, x: i32, y: i32)
considered to be inside
-> bool {
the rectangle. return self.x1 < x && x < self.
x2 && self.y1 < y && y < self.y2;
}
}
179 Get center of a
rectangle import "image" struct Rectangle {
Return the center c of x1: f64,
the rectangle with c := image.Pt((x1+x2)/2, (y1+y2)/2) y1: f64,
coördinates(x1,y1,x2,y2) x2: f64,
Implementation for x1, x2, y1 and y2 as int. y2: f64,
}

impl Rectangle {
pub fn center(&self) -> (f64, f64)
{
((self.x1 + self.x2) / 2.0,
(self.y1 + self.y2) / 2.0)
}
}

180 List files in directory


Create list x containing import "os" let x = std::fs::read_dir(d).unwrap();
the contents of directory x is a fs::ReadDir iterator over std::io::Result<fs::DirEntry>
d.
x, err := os.ReadDir(d)

x is a slice of os.FileInfo Alternative implementation:


x may contain files and
let x = std::fs::read_dir(d)?.collect::
subfolders.
<Result<Vec<_>, _>>()?;
No recursive subfolder
listing.
182 Quine program
Output the source of the
package main fn main() {
let x = "fn main() {\n let x =
program.
import "fmt" ";
let y = "print!(\"{}{:?};\n let
func main() { y = {:?};\n {}\", x, x, y, y)\n}\n";
fmt.Printf("%s%c%s%c\n", s, 0x6 print!("{}{:?};
0, s, 0x60) let y = {:?};
} {}", x, x, y, y)
}
var s = `package main
Alternative implementation:
import "fmt"
fn main(){print!("{},{0:?})}}","fn main
func main() { (){print!(\"{},{0:?})}}\"")}
fmt.Printf("%s%c%s%c\n", s, 0x6
0, s, 0x60) Alternative implementation:
}
fn main() {
var s = ` print!("{}", include_str!("main.r
s"))
}

183 Make HTTP PUT


request import "net/http"
Make a HTTP request
with method PUT to the
req, err := http.NewRequest("PUT", u, b
URL u ody)
if err != nil {
return err
}
req.Header.Set("Content-Type", contentT
ype)
req.ContentLength = contentLength
response, err := http.DefaultClient.Do
(req)

This assumes you know contentLength beforehand.


body is a io.Reader which can be nil.
184 Tomorrow
Assign to variable t a import "time" let t = chrono::Utc::now().date().succ
string representing the ().to_string();
day, month and year of t := time.Now().Add(24 * time.Hour).For
the day after the current mat("2006-01-02")
date.
185 Execute function in 30
seconds import "time" use std::time::Duration;
Schedule the execution use std::thread::sleep;
of f(42) in 30 seconds. timer := time.AfterFunc(
30*time.Second, sleep(Duration::new(30, 0));
func() { f(42);
f(42)
})

f is wrapped in an anonymous func having 0 arg and 0


return value.

The timer instance can be used to cancel the call.

Alternative implementation:

import "time"

go func() {
time.Sleep(30 * time.Second)
f(42)
}()

The code after the goroutine launch executes immediately.

Consider adding proper synchronization where needed.


Data races are forbidden!
186 Exit program cleanly
Exit a program cleanly import "os" use std::process::exit;
indicating no error to OS
os.Exit(0) exit(0);

Alternative implementation:

import "os"

defer os.Exit(0)

defer would be used in order to run subsequent deferred


statements before exiting
188 Matrix multiplication
Perform matrix import "gonum.org/v1/gonum/mat"
multiplication of a real
matrix a with nx rows c := new(mat.Dense)
and ny columns, a real
c.Mul(a, b)
matrix b with ny rows
and nz columns and
assign the value to a real
matrix c with nx rows
and nz columns.
189 Filter and transform
list
var y []Result let y = x.iter()
Produce a new list y for _, e := range x { .filter(P)
containing the result of if P(e) { .map(T)
the function T applied to y = append(y, T(e)) .collect::<Vec<_>>();
all elements e of the list }
x that match the
}
predicate P.
No functional style: just a regular loop.

y is not fully allocated upfront because the number of


matching elements is not known yet.
190 Call an external C
function // void foo(double *a, int n); extern "C" {
Declare an external C // double a[] = {0, 1, 2, 3, 4, 5, 6, /// # Safety
function with the 7, 8, 9}; ///
prototype import "C" /// `a` must point to an array of a
t least size 10
void foo(double *a, int n);
C.foo(C.a, 10) fn foo(a: *mut libc::c_double, n: l
ibc::c_int);
and call it, passing an }
array (or a list) of size 10
to a and 10 to n. let mut a = [0.0, 1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0, 9.0];
Use only standard let n = 10;
features of your
unsafe {
language. foo(a.as_mut_ptr(), n);
}

191 Check if any value in a


for _, v := range a { if a.iter().any(|&elem| elem > x) {
list is larger than a
limit
if v > x { f()
f() }
Given a one-dimensional
array a, check if any
break
}
value is larger than x,
}
and execute the
procedure f if that is the
case
192 Declare a real variable
with at least 20 digits import "math/big" use rust_decimal::Decimal;
Declare a real variable a use std::str::FromStr;
with at least 20 digits; if
a, _, err := big.ParseFloat("123456789.
123456789123465789", 10, 200, big.ToZer let a = Decimal::from_str("1234567890.1
the type does not exist,
issue an error at compile
o) 23456789012345").unwrap();
time. 2nd arg is the base.
3rd arg is the precision.
4th arg is the rounding mode.
The precision is the maximum number of mantissa bits
available to represent the value.
193 Transpose a two-
dimensional matrix use nalgebra::DMatrix;
Declare two two- use rand::prelude::*;
dimensional arrays a
and b of dimension n*m
let a = DMatrix::<u8>::from_fn(n, m, |
and m*n, respectively. _, _| rand::thread_rng().gen());
Assign to b the
let b = a.transpose();
transpose of a (i.e. the
DMatrix is an alias for Matrix which has dynamic
value with index
dimensions.
interchange).
195 Pass a two-
dimensional array import "fmt" #[macro_use] extern crate itertools;
Pass an array a of real
numbers to the func foo(a [][]int) { fn foo(a: Vec<Vec<usize>>) {
procedure (resp. fmt.Println("array is ", len(a) println!(
function) foo. Output the
[0], " x ", len(a)) "Length of array: {}",
size of the array, and the x := 0 a.clone()
sum of all its elements for i, v1 := range a { .into_iter()
when each element is for j, v2 := range v1 { .flatten()
multiplied with the array x += v2*(i+1)* .collect::<Vec<usize>>()
indices i and j (assuming (j+1) .len()
they start from one). } );
}
fmt.Println("result: ", x) let mut sum = 0;
} for (i, j) in izip!(&a[0], &a[1]) {
sum += i * j
}

println!("Sum of all products of in


dices: {}", sum);
}

By useing izip! macro we can chain itteration over elements


of array a
196 Pass a sub-array
Given an integer array a
fn foo(el: &mut i32) {
*el = 42;
of size n, pass the first,
third, fifth and seventh,
}
a.iter_mut().take(m).step_by(2).for_eac
... up to the m th element
h(foo);
to a routine foo which
sets all these elements
to 42.
197 Get a list of lines from
a file import "os" use std::io::prelude::*;
Retrieve the contents of import "strings" use std::io::BufReader;
file at path into a list of use std::fs::File;
strings lines, in which func readLines(path string) ([]string,
each element is a line of error) { let lines = BufReader::new(File::open(p
the file.
b, err := os.ReadFile(path) ath).unwrap())
if err != nil { .lines()
return nil, err .collect::<Vec<_>>();
}
lines := strings.Split(string
(b), "\n")
return lines, nil
}

198 Abort program


execution with error import "os" use std::process;
condition
os.Exit(x) process::exit(x);
Abort program execution
with error condition x
This does not run any destructors. Clean up is left to the
(where x is an integer OS.
value)
199 Truncate a file at the
current file position import "os" use std::io::Seek;
Truncate a file F at the
err := os.Truncate(F, position) let pos = f.stream_position()?;
given file position.
f.set_len(pos)?;

200 Return hypotenuse


Returns the hypotenuse import "math" fn hypot(x:f64, y:f64)-> f64 {
h of the triangle where let num = x.powi(2) + y.powi(2);
the sides adjacent to the h := math.Hypot(x, y) num.powf(0.5)
square angle have
}
lengths x and y.
201 Euclidean norm
Calculate n, the func Euclidean(data []float64) float64 use libm::sqrt;
Euclidean norm of data {
(an array or list of n := 0.0 fn euclidean(data: Vec<f64>) -> f64 {
floating point values).
for _, val := range data { let mut n = 0.0;
n += val * val for i in data {
} n += i*i;
return math.Sqrt(n) }
return sqrt(n as f64)
}
let n = euclidean(data);

202 Sum of squares


import "math" let s = data.iter().map(|x| x.powi(2)).
Calculate the sum of
sum::<f32>();
squares s of data, an
array of floating point var s float64
values. for _, d := range data {
s += math.Pow(d, 2)
}

203 Calculate mean and


standard deviation import "github.com/gonum/stat"
Calculate the mean m
m, s := stat.MeanStdDev(data, nil)
and the standard
deviation s of the list of
github.com/gonum/stat is a third party package, but well
floating point values established.
data.
204 Return fraction and
exponent of a real import "math"
number
fmt.Println(math.Frexp(a))
Given a real number a,
print the fractional part
and the exponent of the
internal representation of
that number. For 3.14,
this should print
(approximately)

0.785 2
205 Get an environment
variable import "os" use std::env;
Read an environment
variable with the name
foo, ok := os.LookupEnv("FOO") let foo = match env::var("FOO") {
"FOO" and assign it to if !ok { Ok(val) => val,
the string variable foo. If
foo = "none" Err(_e) => "none".to_string(),
it does not exist or if the } };
system does not support
environment variables, Alternative implementation: Alternative implementation:
assign a value of "none".
import "os" use std::env;

foo := os.Getenv("FOO") let foo = env::var("FOO").unwrap_or("no


if foo == "" { ne".to_string());
foo = "none"
}
Alternative implementation:
This is fine if empty string means "no value" in your use use std::env;
case.
let foo = match env::var("FOO") {
To distinguish between an empty value and an unset value, Ok(val) => val,
use os.LookupEnv. Err(_e) => "none".to_string(),
};

Alternative implementation:

use std::env;

if let Ok(tnt_root) = env::var("TNT_ROO


T") {
//
}

206 Switch statement with


strings switch str { match str {
Execute different case "foo": "foo" => foo(),
procedures foo, bar, foo() "bar" => bar(),
baz and barfl if the case "bar": "baz" => baz(),
string str contains the bar() "barfl" => barfl(),
name of the respective case "baz": _ => {}
procedure. Do it in a way
baz() }
natural to the language. case "barfl":
barfl()
}

207 Allocate a list that is


automatically a := make([]T, n) let a = vec![0; n];
deallocated
Elements have type T. Heap allocations are deallocated when the variable goes
Allocate a list a
a is garbage-collected after the program exits its scope, out of scope.
containing n elements (n
unless we let it "escape" by taking its reference.
assumed to be too large
The runtime decides if a lives in the stack on in the heap.
for a stack) that is
automatically
deallocated when the
program exits the scope
it is declared in.
208 Formula with arrays
Given the arrays a,b,c,d import "math" for i in 0..a.len() {
of equal length and the a[i] = e * (a[i] + b[i] * c[i] + d
scalar e, calculate a = e* func applyFormula(a, b, c, d []float64, [i].cos());
(a+b*c+cos(d)). e float64) { }
Store the results in a.
for i, v := range a {
a[i] = e * (v + b[i] + Should be sure that all the type of the variables should be
c[i] + math.Cos(d[i])) f32 or f64 in order to use the cos() method.
}
}
209 Type with automatic
deep deallocation type t struct { struct T {
Declare a type t which
s string s: String,
contains a string s and n []int n: Vec<usize>,
an integer array n with
} }
variable size, and
allocate a variable v of v := t{ fn main() {
type t. Allocate v.s and s: "Hello, world!", let v = T {
v.n and set them to the n: []int{1, 4, 9, 16, 25}, s: "Hello, world!".into
values "Hello, world!" for
} (),
s and [1,4,9,16,25], n: vec![1,4,9,16,25]
After v goes out of scope, v and all its fields will be garbage- };
respectively. Deallocate
collected, recursively }
v, automatically
deallocating v.s and v.n
When a variable goes out of scope, all member variables
(no memory leaks).
are deallocated recursively.
210 Compiler version and
options import "runtime"
Assign, at runtime, the
version := runtime.Version()
compiler version and the
options the program was
compilerd with to
variables version and
options, respectively,
and print them. For
interpreted languages,
substitute the version of
the interpreter.

Example output:

GCC version 10.0.0


20190914 (experimental)
-mtune=generic -
march=x86-64
211 Create folder
Create the folder at path import "os" use std::fs;
on the filesystem
err := os.Mkdir(path, os.ModeDir) fs::create_dir(path)?;

This works only if path's parent already exists. This doesn't create parent directories. fs::create_dir_all
does.
Alternative implementation:
Alternative implementation:
import "os"
use std::fs;
err := os.MkdirAll(path, os.ModeDir)
fs::create_dir_all(path)?;
MkdirAll creates any necessary parents.
create_dir_all creates intermediate parent folders as
needed
212 Check if folder exists
Set the boolean b to import "os" use std::path::Path;
true if path exists on the
info, err := os.Stat(path) let b: bool = Path::new(path).is_dir();
filesystem and is a
b := !os.IsNotExist(err) && info.IsDir
directory; false
otherwise.
()
213 Case-insensitive string
compare use itertools::Itertools;
Compare four strings in
pair-wise variations. The
for x in strings
string comparison can .iter()
be implemented with an .combinations(2)
equality test or a .filter(|x| x[0].to_lowercase() ==
containment test, must x[1].to_lowercase())
be case-insensitive and
{
must apply Unicode println!("{:?} == {:?}", x[0], x
casefolding.
[1])
}

214 Pad string on the right


Append extra character import "strings"
c at the end of string s to import "utf8"
make sure its length is at
least m.
if n := utf8.RuneCountInString(s); n <
The length is the number m {
of characters, not the
s += strings.Repeat(c, m-n)
number of bytes. }

c here is a one-character string


215 Pad string on the left
Prepend extra character import "strings" use unicode_width::{UnicodeWidthChar,
c at the beginning of import "utf8" UnicodeWidthStr};
string s to make sure its
if n := utf8.RuneCountInString(s); n < if let Some(columns_short) = m.checked_
length is at least m.
The length is the number
m { sub(s.width()) {
s = strings.Repeat(c, m-n) + s let padding_width = c
of characters, not the
number of bytes.
} .width()
.filter(|n| *n > 0)
c here is a one-character string .expect("padding character shou
ld be visible");
// Saturate the columns_short
let padding_needed = columns_short
+ padding_width - 1 / padding_width;
let mut t = String::with_capacity
(s.len() + padding_needed);
t.extend((0..padding_needed).map(|_
| c)
t.push_str(&s);
s = t;
}

This uses the Unicode display width to determine the


padding needed. This will be appropriate for most uses of
monospaced text.

It assumes that m won't combine with other characters to


form a grapheme.
216 Pad a string on both
sides import "encoding/utf8"
Add the extra character import "strings"
c at the beginning and
ending of string s to n := (m-utf8.RuneCountInString(s)+1)/2
make sure its length is at if n > 0 {
least m. pad := strings.Repeat(string
After the padding the (c), n)
original content of s s = pad + s + pad
should be at the center
}
of the result.
c is the rune (e.g. 'X')
The length is the number
of characters, not the
s is the string
number of bytes.

m is the minimum number of characters of the result


E.g. with s="abcd",
m=10 and c="X" the
result should be
"XXXabcdXXX".
217 Create a Zip archive
Create a zip-file with import "archive/zip" use zip::write::FileOptions;
filename name and add import "bytes"
the files listed in list to import "os" let path = std::path::Path::new(_name);
that zip-file. import "io" let file = std::fs::File::create(&pat
h).unwrap();
buf := new(bytes.Buffer) let mut zip = zip::ZipWriter::new(fil
w := zip.NewWriter(buf) e); zip.start_file("readme.txt", FileOp
for _, filename := range list { tions::default())?;
input, err := os.Open(filename) zip.write_all(b"Hello, World!\n")?;
if err != nil { zip.finish()?;
return err
} zip.finish() returns a Result.
output, err := w.Create(filenam
Alternative implementation:
e)
if err != nil { use zip::write::FileOptions;
return err
} fn zip(_name: &str, _list: Vec<&str>) -
_, err = io.Copy(output, input) > zip::result::ZipResult<()>
if err != nil { {
return err let path = std::path::Path::new(_na
} me);
} let file = std::fs::File::create(&p
ath).unwrap();
err := w.Close() let mut zip = zip::ZipWriter::new(f
if err != nil { ile);
return err for i in _list.iter() {
} zip.start_file(i as &str, FileO
ptions::default())?;
err = os.WriteFile(name, buf.Bytes(), 0 }
777) zip.finish()?;
if err != nil { Ok(())
return err }
}
Note: This function does not write any contents to the files.
list contains filenames of files existing in the filesystem.
In this example, the zip data is buffered in memory before
writing to the filesystem.
218 List intersection
Create the list c
seta := make(map[T]bool, len(a)) use std::collections::HashSet;
containing all unique for _, x := range a {
elements that are
seta[x] = true let unique_a = a.iter().collect::<HashS
contained in both lists a } et<_>>();
and b. setb := make(map[T]bool, len(a)) let unique_b = b.iter().collect::<HashS
c should not contain any for _, y := range b { et<_>>();
duplicates, even if a and setb[y] = true
b do.
} let c = unique_a.intersection(&unique_
The order of c doesn't b).collect::<Vec<_>>();
matter. var c []T
for x := range seta {
Alternative implementation:
if setb[x] {
c = append(c, x) use std::collections::HashSet;
}
} let set_a: HashSet<_> = a.into_iter().c
ollect();
Convert to sets, then iterate in one pass. let set_b: HashSet<_> = b.into_iter().c
The runtime cost is O(n). ollect();
Elements have type T. let c = set_a.intersection(&set_b);
The final order is indeterminate.

Alternative implementation:

func intersection[S ~[]T, T comparable]


(a, b S) S {
seta := make(map[T]bool, len
(a))
for _, x := range a {
seta[x] = true
}
setb := make(map[T]bool, len
(a))
for _, y := range b {
setb[y] = true
}

var c S
for x := range seta {
if setb[x] {
c = append(c,
x)
}
}
return c
}

Convert to sets, then iterate in one pass.


The runtime cost is O(n).
The final order is indeterminate.
Works for any type parameter T.

Alternative implementation:
func intersection[S ~[]T, T comparable]
(a, b S) S {
s, l := a, b
if len(b) < len(a) {
s, l = b, a
}

set := make(map[T]struct{}, len


(s))
for _, x := range s {
set[x] = struct{}{}
}

c := make(S, 0, len(s))
for _, x := range l {
if _, found := set[x];
found {
c = append(c,
x)
delete(set, x)
}
}
return c
}

Convert the smallest slices to a set, then iterate on the other


slice to see which elements are also in the set.
Duplicate elements are ignored.
The final order is indeterminate.
Works for any comparable type T.

Complexity: O(N) [N = len(a)+len(b)]


Memory: O(N) [N = min(len(a), len(b)]
219 Replace multiple
spaces with single import "regexp" use regex::Regex;
space
whitespaces := regexp.MustCompile(`\s+ let re = Regex::new(r"\s+").unwrap();
Create the string t from
the value of string s with
`) let t = re.replace_all(s, " ");
t := whitespaces.ReplaceAllString(s, "
each sequence of Replaces all whitespaces.
spaces replaced by a
")
single space. The whitespaces regexp can be reused.

Explain if only the space


characters will be
replaced, or the other
whitespaces as well:
tabs, newlines.
220 Create a tuple value
t := []interface{}{ let t = (2.5, "hello", -1);
Create t consisting of 3
values having different
2.5,
"hello", Tuples are like “fixed-length collections of values of different
types. types”.
make(chan int),
} They are strongly typed.
Explain if the elements
of t are strongly typed or A slice of empty interface may hold any values (not strongly
not. typed).

Alternative implementation:

a, b, c := 2.5, "hello", make(chan int)

a, b, c are strongly typed and could hold the multiple return


values of a func.

While a, b, c can most often be used like a tuple, they are


technically not a tuple named t.
221 Remove all non-digits
characters import "regexp" let t: String = s.chars().filter(|c| c.
Create string t from is_digit(10)).collect();
string s, keeping only re := regexp.MustCompile("[^\\d]")
digit characters 0, 1, 2, t := re.ReplaceAllLiteralString(s, "")
3, 4, 5, 6, 7, 8, 9.
222 Find the first index of
an element in list i := -1 let opt_i = items.iter().position(|y| *
Set i to the first index in
for j, e := range items { y == x);
list items at which the if e == x {
element x can be found, i = j
or -1 if items does not break let i = match opt_i {
contain x. } Some(index) => index as i32,
} None => -1
};
Explicit loop, for your own strongly typed helper func.
The first line is ideomatic Rust and allows you to work with
Alternative implementation: an Option.
import "golang.org/x/exp/slices"
The rest is some (potentially useless/ugly) implementation
i := slices.Index(items, x) of "returning -1"

This generic func slices.Index works for all slice types Alternative implementation:

let i = items.iter().position(|y| *y ==
x).map_or(-1, |n| n as i32);

Rust uses the usize type to index lists, but it can't be


negative. We need to manually convert it to an i32 to be
able to return -1
223 for else loop
Loop through list items items := []string{"foo", "bar", "baz", let mut found = false;
checking a condition. Do "qux"} for item in items {
something else if no if item == &"baz" {
matches are found. for _, item := range items { println!("found it");
if item == "baz" { found = true;
A typical use case is fmt.Println("found it") break;
looping through a series
goto forelse }
of containers looking for } }
one that matches a } if !found {
condition. If found, an { println!("never found it");
item is inserted; fmt.Println("never found it") }
otherwise, a new
}
forelse: Rust does not have a for...else construct, so we use a
container is created.
found variable.
Go does not have a for...else construct, but a structured
These are mostly used Alternative implementation:
goto label works well.
as an inner nested loop,
if let None = items.iter().find(|&&item
and in a location where
| item == "rockstar programmer") {
refactoring inner logic
println!("NotFound");
into a separate function
};
reduces clarity.

Alternative implementation:

items
.iter()
.find(|&&item| item == "rockstar pr
ogrammer")
.or_else(|| {
println!("NotFound");
Some(&"rockstar programmer")
});

find returns the first Some(T) that satisfies condition, or


returns None. We can use or_else to do action when None
is returned. If you'd like to do something with found element,
use and_then.

Alternative implementation:

if 'search: loop {
for i in items {
if i == &"qux" {
println!("found it");
break 'search false;
}
}
break 'search true
} {
println!("not found!");
}

for within a loop, which is only executed once

Alternative implementation:

'label: {
for &item in items {
if item == "baz" {
println!("foun
d");
break 'label;
}
}
println!("not found");
}

Rust allows you to label scopes, which can then be used


together with "break 'label". We can (ab)use this to emulate
"for else" loops.
224 Add element to the
beginning of the list items = append([]T{x}, items...) use std::collections::VecDeque;
Insert the element x at
items has type []T. items.push_front(x);
the beginning of the list
This implementation always allocates a full new slice.
items.
Alternative implementation:

items = append(items, x)
copy(items[1:], items)
items[0] = x

This implementation is verbose, but it will often not allocate,


when items has enough capacity.

Alternative implementation:

func prepend[S ~[]T, T any](items *S, x


...T) {
*items = append(x, *items...)
}

This generic func always allocates a full new slice.


The variadic argument x accepts one or more values to be
inserted at the beginning.

Alternative implementation:

func prepend[S ~[]T, T any](items *S, x


...T) {
*items = append(*items, x...)
copy((*items)[len(x):], *items)
copy(*items, x)
}

This generic func does not always allocate (depending on


the capacity of items).
The variadic argument x accepts one or more values to
insert at the beginning.
225 Declare and use an
func f(x ...int) { fn f(x: Option<()>) {
optional argument
Declare an optional
if len(x) > 0 { match x {
println("Present", x Some(x) => println!("Present
integer argument x to
procedure f, printing out
[0]) {}", x),
} else { None => println!("Not presen
"Present" and its value if
it is present, "Not
println("Not present") t"),
} }
present" otherwise
} }

Go does not have optional arguments, but to some extend,


they can be mimicked with a variadic parameter.
x is a variadic parameter, which must be the last parameter
for the function f.
Strictly speaking, x is a list of integers, which might have
more than one element. These additional elements are
ignored.
226 Delete last element
from list items = items[:len(items)-1] items.pop();
Remove the last element
If items is already empty, this will panic with "slice bounds items is a mutable Vec
from list items.
out of range".
Warning: the last element still exists beyond len(items),
thus it won't be garbage collected.

Alternative implementation:

import "golang.org/x/exp/slices"

items = slices.Delete(items, len(items)


-1, len(items))
227 Copy a list
Create the new list y y := make([]T, len(x)) let y = x.clone();
containing the same copy(y, x)
The elements type must implement the trait
elements as the list x.
Elements have type T std::clone::Clone
Note that the destination is the first argument of copy.
Subsequent
modifications of y must Alternative implementation:
not affect x (except for
import "golang.org/x/exp/slices"
the contents referenced
by the elements
y := slices.Clone(x)
themselves if they
contain pointers). This generic Clone func accepts x of any slice type
228 Copy a file
Copy the file at path src import "os" use std::fs;
to dst.
func copy(dst, src string) error { fs::copy(src, dst).unwrap();
data, err := os.ReadFile(src)
if err != nil {
return err
}
stat, err := os.Stat(src)
if err != nil {
return err
}
return os.WriteFile(dst, data,
stat.Mode())
}

This is fine if the file is small enough to fit in memory.


Warning: in Unix, the destination file's mode and
permission bits may be different from the source file's,
because umask is applied.

Alternative implementation:

import "os"

func copy(dst, src string) error {


data, err := os.ReadFile(src)
if err != nil {
return err
}
stat, err := os.Stat(src)
if err != nil {
return err
}
err = os.WriteFile(dst, data, s
tat.Mode())
if err != nil {
return err
}
return os.Chmod(dst, stat.Mode
())
}

This is fine if the file is small enough to fit in memory.


This preserves the source file's mode and permission bits
(overriding umask in Unix).

Alternative implementation:

import "io"
import "os"
func copy(dst, src string) error {
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return err
}
g, err := os.OpenFile(dst, os.O
_WRONLY|os.O_CREATE|os.O_TRUNC, stat.Mo
de())
if err != nil {
return err
}
defer g.Close()
_, err = io.Copy(g, f)
if err != nil {
return err
}
return os.Chmod(dst, stat.Mode
())
}

This can handle large files.


229 Cancel an operation
Interrupt an ongoing import "context"
processing p.
ctx, cancel := context.WithCancel(conte
xt.Background())
go p(ctx)

somethingElse()

cancel()

Pass a Context to p and execute p.


p is responsible for shutting down gracefully when ctx is
canceled
230 Timeout
Cancel an ongoing import "context"
processing p if it has not
finished after 5s. ctx, cancel := context.WithTimeout(cont
ext.Background(), 5*time.Second)
defer cancel()
p(ctx)

p is responsible for shutting down gracefully when ctx is


canceled.
231 Test if bytes are a valid
UTF-8 string import "unicode/utf8" let b = std::str::from_utf8(&bytes).is_
Set b to true if the byte ok();
sequence s consists b := utf8.Valid(s)
entirely of valid UTF-8
s is a []byte.
character code points,
false otherwise.
232 Read a command line
boolean flag import "flag" use clap::{Arg, App};
Print "verbose is true" if
the flag -v was passed to var verbose = flag.Bool("v", false, "ve let matches = App::new("My Program")
the program command
rbose") .arg(Arg::with_name("ve
line, "verbose is false" flag.Parse() rbose")
otherwise. fmt.Println("verbose is", *verbose) .short("v")
.takes_value(fals
verbose has pointer type *bool. e))
Call Parse only once, after all flags are defined and before .get_matches();
flags are read.
Flags must be passed before the non-flag arguments. if matches.is_present("verbose") {
println!("verbose is true")
} else {
println!("verbose is false")
}

233 Read a command line


string flag import "flag"
Print the value of the flag
-country passed to the var country = flag.String("country", "C
program command line, anada", "user home country")
or the default value flag.Parse()
"Canada" if no such flag fmt.Println("country is", *country)
was passed.
country has pointer type *string.
Call Parse only once, after all flags are defined and before
flags are read.
Flags must be passed before the non-flag arguments.
234 Encode bytes to
import "encoding/base64" let s = base64::encode(data);
base64
Assign to string s the
s := base64.StdEncoding.EncodeToString
standard base64
encoding of the byte
(data)
array data, as specified
by RFC 4648.
235 Decode base64
import "encoding/base64" let bytes = base64::decode(s).unwrap();
Assign to byte array
data the bytes
data, err := base64.StdEncoding.DecodeS
represented by the
tring(s)
base64 string s, as
specified by RFC 4648.
236 Large quotient
Initialize a quotient q = import "math/big"
a/b of arbitrary precision.
a and b are large
q := new(big.Rat)
q.SetString(str)
integers.
str is a quotient string including numerator, slash,
denominator.

Alternative implementation:

import "math/big"

q := new(big.Rat)
q.SetFrac(a, b)

a, b have type *big.Int

Alternative implementation:

import "math/big"

q := big.NewRat(a, b)

This creates a quotient from int64 values.


Subsequent computations have arbitrary precision.
237 Xor integers
Assign to c the result of c := a ^ b let c = a ^ b;
(a xor b)
a, b, c have the same integer type (signed or unsigned)

Alternative implementation:

import "math/big"

c := new(big.Int)
c.Xor(a, b)

a, b, c have big integer type *big.Int


238 Xor byte arrays
c := make([]byte, len(a)) let c: Vec<_> = a.iter().zip(b).map(|
Write in a new byte array
c the xor result of byte
for i := range a { (x, y)| x ^ y).collect();
c[i] = a[i] ^ b[i]
arrays a and b.
}
a and b have the same Byte slices []byte are more idiomatic than arrays.
size.
Alternative implementation:

var c T
for i := range a {
c[i] = a[i] ^ b[i]
}

T is a fixed-sized array type, e.g. [5]byte.


239 Find first regular
expression match import "regexp" use regex::Regex;
Assign to string x the
first word of string s re := regexp.MustCompile(`\b\d\d\d\b`) let re = Regex::new(r"\b\d\d\d\b").expe
consisting of exactly 3 x := re.FindString(s) ct("failed to compile regex");
digits, or the empty let x = re.find(s).map(|x| x.as_str()).
re may (and should) be reused. unwrap_or("");
string if no such match
\b matches word boundaries.
exists.
\d matches a single digit.

A word containing more


digits, or 3 digits as a
substring fragment, must
not match.
240 Sort 2 lists together
Lists a and b have the import "sort" let mut tmp: Vec<_> = a.iter().zip(b).c
same length. Apply the ollect();
same permutation to a
type sorter struct { tmp.as_mut_slice().sort_by_key(|(&x, _
and b to have them k []K y)| x);
sorted based on the t []T let (aa, bb): (Vec<i32>, Vec<i32>) = tm
values of a. } p.into_iter().unzip();

func (s *sorter) Len() int {


return len(s.k)
}

func (s *sorter) Swap(i, j int) {


s.k[i], s.k[j] = s.k[j], s.k[i]
s.t[i], s.t[j] = s.t[j], s.t[i]
}

func (s *sorter) Less(i, j int) bool {


return s.k[i] < s.k[j]
}

sort.Sort(&sorter{
k: a,
t: b,
})

The custom type sorter implements the 3 methods of


sort.Interface.
Swap affects the order of 2 slices at once.
241 Yield priority to other
threads import "runtime" ::std::thread::yield_now();
Explicitly decrease the
busywork();
priority of the current runtime.Gosched()
process, so that other
busywork()
execution threads have
After Gosched, the execution of the current goroutine
a better chance to
resumes automatically.
execute now. Then
resume normal
execution and call the
function busywork.
242 Iterate over a set
Call a function f on each for e := range x { use std::collections::HashSet;
element e of a set x. f(e)
} for item in &x {
f(item);
x is implemented as a map whose values are ignored. }

x is a HashSet
243 Print list
Print the contents of the import "fmt" println!("{:?}", a)
list or array a on the a is a Vec.
standard output. fmt.Println(a)
Vec<T> doesn't implement the Display trait, however it
a is a slice. implements the Debug trait.
This works fine for simple types and structs.
It won't dereference pointers.
244 Print a map
import "fmt" println!("{:?}", m);
Print the contents of the
map m to the standard
fmt.Println(m)
output: keys and values.
This works fine for simple types of keys and values.
It won't dereference pointers.

Alternative implementation:

import "fmt"

fmt.Printf("%q", m)

The verb %q prints strings with nice double-quotes.


It's not the best for all types of keys and values, though.
245 Print value of custom
type import fmt; println!("{:?}", x);
Print the value of object Implement fmt::Debug or fmt::Display for T
x having custom type T,
fmt.Println(x)
for log or debug. Will be more relevant if T implements fmt.Stringer
246 Count distinct
elements
distinct := make(map[T]bool) use itertools::Itertools;
Set c to the number of for _, v := range items {
distinct elements in the
distinct[v] = true let c = items.iter().unique().count();
list items. }
c := len(distinct)

This assumes the type T is comparable with ==

Alternative implementation:

func count[T comparable](items []T) int


{
distinct := make(map[T]bool)
for _, v := range items {
distinct[v] = true
}
return len(distinct)
}

The type parameter T has a constraint: it must be


comparable with ==
247 Filter list in-place
Remove all the elements
j := 0 let mut j = 0;
from list x that don't for i, v := range x { for i in 0..x.len() {
satisfy the predicate p,
if p(v) { if p(x[i]) {
without allocating a new x[j] = x[i] x[j] = x[i];
list. j++ j += 1;
Keep all the elements } }
that do satisfy p. } }
x = x[:j] x.truncate(j);
For languages that don't
Discarded elements are overwritten.
have mutable lists, refer Alternative implementation:
x is resliced to its new length.
to idiom #57 instead.
If the elements of x have a pointer type, then you should x.retain(p);
take care of a potential memory leak by setting all x[j:]
elements to nil. The predicate p takes as argument a reference to the
element.
Alternative implementation:

j := 0
for i, v := range x {
if p(v) {
x[j] = x[i]
j++
}
}
for k := j; k < len(x); k++ {
x[k] = nil
}
x = x[:j]

When elements of x have pointer type, it is necessary to set


discarded slice elements to nil, to avoid a memory leak.

Alternative implementation:

func Filter[S ~[]T, T any](x *S, p func


(T) bool) {
j := 0
for i, v := range *x {
if p(v) {
(*x)[j] = (*x)
[i]
j++
}
}
var zero T
for k := j; k < len(*x); k++ {
(*x)[k] = zero
}
*x = (*x)[:j]
}

S, T are type parameters.


In case T contains pointers, zeroing discarded elements
helps garbage collection.
248 Construct a 64-bit
floating-point value import "math"
Construct the "double
precision" (64-bit)
if s {
m = -m
floating point number d
}
from the mantissa m, the
exponent e and the sign
d := math.Ldexp(m, e)
flag s (true means the
sign is negative).
249 Declare and assign
multiple variables
a, b, c := 42, "hello", 5.0 let (a, b, c) = (42, "hello", 5.0);
Define variables a, b and a, b and c may have different types. a, b, and c may have different types.
c in a concise way.
Explain if they need to
have the same type.
250 Pick a random value
from a map import "math/rand" use rand::prelude::*;
Choose a value x from
map m. func pick(m map[K]V) V { let mut rng = rand::thread_rng();
m must not be empty. k := rand.Intn(len(m)) let x = m.values().choose(&mut rng).exp
Ignore the keys. i := 0 ect("m is empty");
for _, x := range m {
if i == k {
return x
}
i++
}
panic("unreachable")
}

Alternative implementation:

import "math/rand"

func pick(m map[K]V) V {


k := rand.Intn(len(m))
for _, x := range m {
if k == 0 {
return x
}
k--
}
panic("unreachable")
}

Alternative implementation:

func pick[K comparable, V any](m map[K]


V) V {
k := rand.Intn(len(m))
i := 0
for _, x := range m {
if i == k {
return x
}
i++
}
panic("unreachable")
}

The type parameter K has a constraint: it must be


comparable with ==

Alternative implementation:

import "sync"

var mu sync.RWMutex

func pick(m map[int]any) any {


mu.RLock()
defer mu.RUnlock()
for _, v := range m {
return v
}
return nil
}

251 Parse binary digits


Extract integer value i import "strconv" let i = i32::from_str_radix(s, 2).expec
from its binary string t("Not a binary number!");
representation s (in radix
i, err := strconv.ParseInt(s, 2, 0)
2)
i has type int64
E.g. "1101" -> 13
252 Conditional
assignment
if condition() { x = if condition() { "a" } else { "b"
Assign to the variable x x = "a" };
the value "a" if calling } else {
the function condition x = "b"
returns true, or the value }
"b" otherwise.
No syntactic sugar
253 Print stack trace
Print the stack frames of import "runtime/debug" use backtrace::Backtrace;
the current execution
debug.PrintStack() let bt = Backtrace::new();
thread of the program.
println!("{:?}", bt);
Prints to standard error
254 Replace value in list
Replace all exact for i, v := range x { for v in &mut x {
occurrences of "foo" with if v == "foo" { if *v == "foo" {
"bar" in the string list x x[i] = "bar" *v = "bar";
} }
} }

Alternative implementation:

func replaceAll[T comparable](s []T, ol


d, new T) {
for i, v := range s {
if v == old {
s[i] = new
}
}
}

replaceAll(x, "foo", "bar")

The type parameter T has a constraint: it must be


comparable with ==
255 Print a set
Print the values of the import "fmt" use std::collections::HashSet;
set x to the standard
output. for _, v := range x { println!("{:?}", x);
The order of the fmt.Println(v)
elements is irrelevant
}
and is not required to
note that this will only print the values of the set, not the
remain the same next
keys
time.
256 Count backwards
Print the numbers 5, 4, import "fmt" (0..=5).rev().for_each(|i| println!("
..., 0 (included), one line {}", i));
per number.
for i := 5; i >= 0; i-- {
fmt.Println(i) Use _(0..=5).rev()_.
} (5..=0) will not do anything.

257 Traverse list


import "fmt" for (i, item) in items.iter().enumerate
backwards
Print each index i and
().rev() {
for i := len(items) - 1; i >= 0; i-- { println!("{} = {}", i, *item);
value x from the list
x := items[i] }
items, from the last
down to the first. fmt.Printf("Item %d = %v \n",
i, x) Alternative implementation:
}
for (i, x) in items.iter().rev().enum
erate() {
println!("{i} = {x}");
}
258 Convert list of strings
to list of integers import "strconv" let b: Vec<i64> = a.iter().map(|x| x.pa
Convert the string values rse::<i64>().unwrap()).collect();
from list a into a list of b := make([]int, len(a))
var err error a has type Vec<&str>
integers b.
for i, s := range a {
Alternative implementation:
b[i], err = strconv.Atoi(s)
if err != nil { let b: Vec<i32> = a.iter().flat_map(|s|
return err s.parse().ok()).collect();
}
ok converts a Result to an Option. flat_map collects all
}
values of Some.
259 Split on several
separators import "regexp" let parts: Vec<_> = s.split(&[',', '-',
'_'][..]).collect();
Build the list parts
consisting of substrings re := regexp.MustCompile("[,\\-_]")
of the input string s,
parts := re.Split(s, -1)
separated by any of the
Square brackets mean "match any of these characters".
characters ',' (comma), '-'
The special character dash must be escaped with a
(dash), '_' (underscore).
backslash.
The backslash must be escaped with a backslash.
260 Create an empty list of
var items []string let items: Vec<String> = vec![];
strings
Declare a new list items items is nil, which is idiomatic for an empty slice
of string elements,
containing zero elements
261 Format time hours-
minutes-seconds import "time" use time::macros::format_description;
Assign to the string x the
x := d.Format("15:04:05") let format = format_description!("[hou
value of fields (hours,
r]:[minute]:[second]");
minutes, seconds) of the
date d, in format
let x = d.format(&format).expect("Faile
d to format the time");
HH:MM:SS.

262 Count trailing zero bits


Assign to t the number import "math/bits" let t = n.trailing_zeros();
of trailing 0 bits in the
binary representation of
t := bits.TrailingZeros(n)
the integer n.
n has type uint

E.g. for n=112, n is


1110000 in base 2 ⇒ t=4
263 Integer logarithm in
base 2 fn log2d(n: f64) -> f64 {
Write two functions
n.log2().floor()
log2d and log2u, which }
calculate the binary
logarithm of their fn log2u(n: f64) -> f64 {
argument n rounded n.log2().ceil()
down and up, }
respectively. n is
assumed to be positive.
fn main() {
Print the result of these for n in 1..=12 {
functions for numbers let f = f64::from(n);
from 1 to 12. println!("{} {} {}", n, log2d
(f), log2u(f));
}
}

Alternatively, you could use n as f64 instead of f64::from(n),


but that doesn't pass the Clippy pedantic lint cast_lossless.
264 Automated passing of
array bounds
fn foo(matrix: &[Vec<i32>]) {
Pass a two-dimensional let iter = matrix.iter();
integer array a to a let (vertical, _) = iter.size_hint
procedure foo and print ();
the size of the array in let horizontal = iter
each dimension. Do not
.max()
pass the bounds .expect("empty array!")
manually. Call the .len();
procedure with a two- println!("{horizontal} by {vertica
dimensional array. l}");
}

fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
];
foo(&matrix);
}

'&[Vec<i32>]' because we just read the Vec instead of


consuming it.
This is emphasised with the '&' in front of types inside the
functions signature.
'&Vec' can be coerced to '&[...]', which is a borrowed 'slice'.
A 'slice' is an 'array' with an unknown size at compile time.
'(vertical, _)' because 'size_hint()' returns a lower and a
possible upper bound (the '_' in this case).
'max()' may return 'None' if the iterator (in this case our
array) is empty.

Alternative implementation:

fn foo<const X: usize, const Y: usize>


(_: [[i32;X];Y]) {
println!("{} {}", Y, X);
}

let a = [
[1, 2, 3],
[4, 5, 6],
];
foo(a);

265 Even parity bit


Calculate the parity p of
let i = 42i32;
let p = i.count_ones() % 2;
the integer variable i : 0
if it contains an even
number of bits set, 1 if it
contains an odd number
of bits set.
266 Repeated string
Assign to the string s the import ( let s = v.repeat(n);
value of the string v "fmt"
repeated n times, and "strings"
write it out. )

E.g. v="abc", n=5 ⇒


s := strings.Repeat(v, n)
fmt.Println(s)
s="abcabcabcabcabc"
267 Pass string to
argument that can be import "fmt" use std::any::Any;
of any type
Declare an argument x func foo(x interface{}) { fn foo(x: &dyn Any) {
to a procedure foo that if s, ok := x.(string); ok { if let Some(s) = x.downcast_ref::<S
can be of any type. If the
fmt.Println(s) tring>() {
type of the argument is a } else { println!("{}", s);
string, print it, otherwise
fmt.Println("Nothing.") } else {
print "Nothing." } println!("Nothing")
} }
Test by passing "Hello, }
world!" and 42 to the func main() {
procedure.
foo("Hello, world!") fn main() {
foo(42) foo(&"Hello, world!".to_owned());
} foo(&42);
}
An argument of type interface{} may receive a value of any
type. Dynamic typing isn't idiomatic Rust.
We convert it with a type assertion.
268 User-defined operator
Define a type vector use std::ops::Mul;
containing three floating
point numbers x, y, and struct Vector {
z. Write a user-defined x: f32,
operator x that y: f32,
calculates the cross z: f32,
product of two vectors a
}
and b.
impl Mul for Vector {
type Output = Self;

fn mul(self, rhs: Self) -> Self {


Self {
x: self.y * rhs.z - self.z
* rhs.y,
y: self.z * rhs.x - self.x
* rhs.z,
z: self.x * rhs.y - self.y
* rhs.x,
}
}
}

269 Enum to String


let e = t::bike;
Given the enumerated
type t with 3 possible
let s = format!("{:?}", e);
values: bike, car, horse.
Set the enum value e to
println!("{}", s);
one of the allowed This requires the enum to derive the Debug trait.
values of t.
Set the string s to hold
the string representation
of e (so, not the ordinal
value).
Print s.
272 Play FizzBuzz
Fizz buzz is a children's import "fmt" for i in 1..101 {
counting game, and a import "strconv" match i {
trivial programming task i if (i % 15) == 0 => println!
used to affirm that a for n:=1; n<=100; n++ { ("FizzBuzz"),
programmer knows the
out:="" i if (i % 3) == 0 => println!
basics of a language: if n%3==0 { ("Fizz"),
loops, conditions and out=out+"Fizz" i if (i % 5) == 0 => println!
I/O. } ("Buzz"),
if n%5==0 { _ => println!("{i}"),
The typical fizz buzz
out=out+"Buzz" }
game is to count from 1 } }
to 100, saying each if out=="" {
number in turn. When out=out+strconv.Ito
the number is divisible a(n)
by 3, instead say "Fizz". }
When the number is fmt.Println(out)
divisible by 5, instead }
say "Buzz". When the
number is divisible by
both 3 and 5, say
"FizzBuzz"
273 Check if folder is
empty import "os" use std::fs;
Set the boolean b to true
if the directory at filepath dir, err := os.Open(p) let b = fs::read_dir(p).unwrap().count
p is empty (i.e. doesn't if err != nil { () == 0;
contain any other files panic(err)
and directories) }
defer dir.Close()
_, err = dir.Readdirnames(1)
b := err == io.EOF

Error may happen, and should be dealt with.

b is set to true if EOF was encountered before reading 1


contained file name.
274 Remove all white
import "strings" let t: String = s.chars().filter(|c| !
space characters
Create the string t from import "unicode" c.is_whitespace()).collect();
the string s, removing all
the spaces, newlines, t := strings.Map(func(r rune) rune {
tabulations, etc. if unicode.IsSpace(r) {
return -1
}
return r
}, s)

In this mapping, -1 means "drop this character"


275 Binary digits to byte
array import "strconv"
From the string s
consisting of 8n binary
n := len(s) / 8
digit characters ('0' or
a := make([]byte, n)
for i := range a {
'1'), build the equivalent
b, err := strconv.ParseInt(s[i*
array a of n bytes.
Each chunk of 8 binary
8:i*8+8], 2, 0)
digits (2 possible values
if err != nil {
per digit) is decoded into
log.Fatal(err)
}
one byte (256 possible
values).
a[i] = byte(b)
}

bytes are unsigned in Go (byte is an alias for uint8)

Consider handling the error appropriately, in case s is


malformed.
276 Insert an element in a
set x[e] = struct{}{} use std::collections::HashSet
Insert an element e into
x has type map[E]struct{} x.insert(e);
the set x.
Alternative implementation: x has type mut HashSet
x[e] = true
returns false if the set already had the value present, true
x has type map[E]bool otherwise
277 Remove an element
from a set
delete(x, e) use std::collections::HashSet
Remove the element e x has type map[E]struct{}
from the set x. x.remove(e);

If x is nil or there is no such element, delete is a no-op. x has type mut HashSet
Explains what happens if
e was already absent Alternative implementation: returns true if value was present.
from x.
delete(x, e)
Alternative implementation:
x has type map[E]bool use std::collections::HashSet;

If x is nil or there is no such element, delete is a no-op. x.take(e)

x has type mut HashSet

returns Some(e) if the value was present, None otherwise


278 Read one line from the
standard input import "bufio" let mut buffer = String::new();
Read one line into the import "os" let mut stdin = io::stdin();
stdin.read_line(&mut buffer).unwrap();
string line.
s := bufio.NewScanner(os.Stdin)
if ok := s.Scan(); !ok { String is empty if EOF
Explain what happens if
EOF is reached. log.Fatal(s.Err())
}
line := s.Text()

This handles any error (including EOF) by aborting the


program execution.

WARNING: this works only for lines smaller than 64kB


each.
279 Read list of strings
from the standard import "bufio" use std::io::prelude::*;
input import "os"
Read all the lines (until
let lines = std::io::stdin().lock().lin
EOF) into the list of
var lines []string es().map(|x| x.unwrap()).collect::<Vec<
s := bufio.NewScanner(os.Stdin) String>>();
strings lines.
for s.Scan() {
line := s.Text()
lines = append(lines, line)
}
if err := s.Err(); err != nil {
log.Fatal(err)
}

WARNING: this works only for lines smaller than 64kB


each.
280 Filter map
Remove all the elements for k, v := range m { m.retain(|_, &mut v| p(v));
from the map m that if !p(v) {
delete(m, k) Filtering on values happens in place.
don't satisfy the
} The keys are ignored.
predicate p.
Keep all the elements }
that do satisfy p.
It is safe to use delete while iterating.
m is filtered in-place.
Explain if the filtering
happens in-place, i.e. if Alternative implementation:
m is reused or if a new
import "golang.org/x/exp/maps"
map is created.

maps.DeleteFunc(m, func(k K, v V) bool


{
return !p(v)
})

maps.DeleteFunc is generic and type-safe at compile time.


281 Use a Point as a map
key
m := map[Point]string{} use std::collections::HashMap;
You have a Point with
p := Point{x: 42, y: 5}
m[p] = "Hello" let mut map: HashMap<Point, String> = H
integer coordinates x
and y. Create a map m Types comparable with == can be used as map keys. ashMap::new();
with key type Point (or map.insert(Point { x: 42, y: 5 }, "Hell
equivalent) and value o".into());
type string. Insert "Hello"
at position (42, 5).
282 Use a custom type as
type Foo struct {
map key
Declare a type Foo, and
name string
create a new map with
x, y int
Foo as key type.
}

m := make(map[Foo]string)
Mention the conditions
on Foo required to make Foo can be used as a key type if all of its fields are
it a possible map key comparable with ==
type.
283 Split with a custom
string separator import "strings" let parts = s.split(sep);
Build the list parts
parts := strings.Split(s, sep) split returns an iterator.
consisting of substrings
of input string s, s may have type &str or String.
parts has type []string.
separated by the string
sep. Alternative implementation:

let parts = s.split(sep).collect::<Vec<


&str>>();

s may have type &str or String.

Alternative implementation:

let parts: Vec<&str> = s.split(sep).col


lect();

s may have type &str or String.


284 Create a zeroed list of
integers
a := make([]int, n) let a = vec![0; n];
Create a new list a (or
All elements have the default value 0.
array, or slice) of size n,
where all elements are
integers initialized with
the value 0.
285 Set variable to NaN
Given two floating point let a: f64 = f64::NAN;
variables a and b, set a
to a to a quiet NaN and
b to a signalling NaN.
Use standard features of
the language only,
without invoking
undefined behavior.
286 Iterate over characters
of a string i := 0 for (i, c) in s.chars().enumerate() {
Print a line "Char i is c" for _, c := range s { println!("Char {} is {}", i, c);
for each character c of fmt.Printf("Char %d is %c\n", }
the string s, where i is i, c)
i++ s may have type &str or String.
the character index of c
} c has type char.
in s (not the byte index).
c is a rune.
Make sure that multi-
s is assumed encoded in UTF-8.
byte characters are
properly handled, and
This first range variable is ignored, as it provides positions
count for a single
in bytes, instead of runes count.
character.
287 Number of bytes of a
string n := len(s) let n = s.len();
Assign to n the number
len counts bytes (not runes). The len method counts the number of bytes, not the number
of bytes in the string s.
of characters.

This can be different


from the number of
characters. If n includes
more bytes than the
characters per se
(trailing zero, length
field, etc.) then explain it.
One byte is 8 bits.
288 Check if set contains a
value b := x[e] let b = x.contains(&e);
Set the boolean b to
x has type map[E]bool x has type HashSet
true if the set x contains
the element e, false Alternative implementation:
otherwise.
_, b := x[e]

x has type map[E]struct{}


289 Concatenate two
strings
s := a + b let s = format!("{}{}", a, b);
Create the string s by
This allocates a new String with a and b concatenated.
concatenating the strings
a and b. Alternative implementation:

let s = a + b;

This adds b to the current allocation of a, meaning that a


needs to be a mutable String.
290 Sort sublist
Sort the part of the list sub := items[i:j] items[i..j].sort_by(c);
items from index i sort.Slice(sub, func(a, b int) bool {
return c(sub[a], sub[b]) Sorts a slice of items.
(included) to index j
(excluded), in place, })
using the comparator c.
A slice can be sorted in place.

Elements before i and Alternative implementation:


after j must remain
unchanged.
import "golang.org/x/exp/slices"

slices.SortFunc(items[i:j], c)

SortFunc is generic and type-safe at compile time.


291 Remove sublist
Delete all the elements
copy(items[i:], items[j:]) items.drain(i..j)
from index i (included) to for k, n := len(items)-j+i, len(items);
index j (excluded) from k < n; k++ {
the list items. items[k] = nil
}
items = items[:len(items)-j+i]

Use this when the elements of items have a pointer type.

The for loop sets unused memory to nil, to avoid a memory


leak.

Alternative implementation:

items = append(items[:i], items[j:]...)

Use this when the elements don't have a pointer type.

Alternative implementation:

import "golang.org/x/exp/slices"

items = slices.Delete(items, i, j)

This generic func slices.Delete works for all slice types


292 Write "Ni Hao" in
Chinese to standard import "fmt" println!("Hello World and 你好")
output in UTF-8
Write "Hello World and fmt.Println("Hello World and 你好")
你好" to standard output
Strings are UTF-8 by default.
in UTF-8.
293 Create a stack
Create a new stack s,
type Stack[T any] struct { let mut s: Vec<T> = vec![];
push an element x, then
items []T s.push(x);
pop the element into the
} let y = s.pop().unwrap();
variable y. T is the type of the elements.
func (s *Stack[T]) Push(t T) {
s.items = append(s.items, t)
} pop() returns an Option<T>.

func (s *Stack[T]) Pop() T {


n := len(s.items)
t := s.items[n-1]
var zero T
s.items[n-1] = zero
s.items = s.items[:n-1]
return t
}

var s = new(Stack[string])
s.Push(x)
y := s.Pop()

The generic type Stack works for any type parameter T


294 Print a comma-
separated list of import "fmt" let a = [1, 12, 42];
integers
println!("{}", a.map(|i| i.to_string
Given an array a a := []int{1, 12, 42} ()).join(", "))
containing the three
values 1, 12, 42, print for i, j := range a {
out if i > 0 {
"1, 12, 42" with a comma
fmt.Print(", ")
and a space after each }
integer except the last fmt.Print(j)
one. }
296 Replace last
occurrence of import "strings"
substring
Assign to x2 the value of func replaceLast(x, y, z string) (x2 st
string x with the last ring) {
occurrence of y replaced i := strings.LastIndex(x, y)
by z. if i == -1 {
If y is not contained in x, return x
then x2 has the same }
value as x.
return x[:i] + z + x[i+len(y):]
}

A custom func replaceLast is appropriate here.


297 Sort a list of strings,
case-insensitively import (
Sort the string list data in "sort"
a case-insensitive "unicode"
manner. "unicode/utf8"
)
The sorting must not
destroy the original func lessCaseInsensitive(s, t string) b
casing of the strings.
ool {
for {
if len(t) == 0 {
return false
}
if len(s) == 0 {
return true
}
c, sizec := utf8.Decode
RuneInString(s)
d, sized := utf8.Decode
RuneInString(t)

lowerc := unicode.ToLow
er(c)
lowerd := unicode.ToLow
er(d)

if lowerc < lowerd {


return true
}
if lowerc > lowerd {
return false
}

s = s[sizec:]
t = t[sized:]
}
}

sort.Slice(data, func(i, j int) bool {


return lessCaseInsensitive(data[i], dat
a[j]) })

This is a verbose custom func, designed to avoid allocating


memory.

Alternative implementation:

import (
"sort"
"strings"
)

sort.Slice(data, func(i, j int) bool {


return strings.ToLower(data[i])
< strings.ToLower(data[j])
})

This code is convenient, however ToLower allocates new


strings for each comparison, which is expensive.

Alternative implementation:

import "golang.org/x/exp/slices"

slices.SortFunc(data, func(a, b string)


bool {
return strings.ToLower(a) < str
ings.ToLower(b)
})
SortFunc is generic and type-safe at compile time.

ToLower allocates new strings for each comparison, which


is expensive.
298 Copy a map
Create the map y by
y := make(map[K]V, len(x))
for k, v := range x {
cloning the map x.
y[k] = v
y is a shallow copy, not a
}
deep copy. K is the key type.
V is the value type.

Alternative implementation:

import "golang.org/x/exp/maps"

y := maps.Clone(x)

maps.Clone is generic and type-safe at compile time.


299 Comment out a single
line
// This is a comment // This is a comment
Write a line of
comments.

This line will not be


compiled or executed.
301 Recursive Fibonacci
sequence
func fibonacci(n int) int { fn fib(n: i32) -> i32{
Compute the Fibonacci if n <= 1 { if n < 2 {
sequence of n numbers return n 1
using recursion. } }else{
return fibonacci(n-1) + fibonac fib(n - 2) + fib(n - 1)
Note that naive recursion
ci(n-2) }
is extremely inefficient } }
for this task.
302 String interpolation
Given the integer x = 8, s := fmt.Sprintf("Our sun has %d planet let s = format!("Our sun has {} planet
assign to the string s the s", x) s", x);
value "Our sun has 8
Go doesn't have string interpolation, but it does have
planets", where the Alternative implementation:
functions of the printf family.
number 8 was evaluated
let s = format!("Our sun has {x} planet
from x.
s");

Rust >= 1.58


304 Encode string into
UTF-8 bytes
data := []byte(s) let data = s.into_bytes();
Create the array of bytes In Go, it is idiomatic that strings are already encoded in
data by encoding the UTF-8. So we can grab their raw bytes directly.
string s in UTF-8.
306 Ensure list capacity
if cap(x) < 200 { x.reserve(200);
Preallocate memory in
the list x for a minimum
y := make([]T, len(x), 200)
total capacity of 200
copy(y, x)
elements.
x = y
}
This is not possible in all x has type []T.
languages. It is only
meant as a performance x keeps the same length.
optimization, should not
change the length of x, Alternative implementation:
and should not have any
import "golang.org/x/exp/slices"
effect on correctness.

x = slices.Grow(x, 200)

This generic Grow func accepts x of any slice type


307 XOR encrypt/decrypt
string
fn xor(s: Vec<u8>, key: &[u8]) -> Vec<u
Create a function that 8> {
XOR encrypts/decrypts a let mut b = key.iter().cycle();
string s.into_iter().map(|x| x ^ b.next().
unwrap()).collect()
}

use into_bytes() for converting String to Vec<u8> and


str::from_utf8() for converting Vec<u8> to String
308 Integer to string in
base b import "strconv"
Create the string
s := strconv.FormatInt(n, b)
representation s of the
integer value n in base
b.

18 in base 3 -> "200"


26 in base 5 -> "101"
121 in base 12 -> "a1"

309 Clone a 2D array


Create the new 2-
buf := make([]T, m*n) let y = x.clone();
dimensional array y
y = make([][]T, m)
containing a copy of the
for i := range y {
y[i] = buf[:n:n]
elements of the 2-
dimensional array x.
buf = buf[n:]
copy(y[i], x[i])
x and y must not share
}
memory. Subsequent Allocate a large buffer, slice it, copy the data.
modifications of y must
not affect x. Alternative implementation:

func clone2D[M ~[][]T, T any](in M) (ou


t M) {
if len(in) == 0 {
return nil
}

m, n := len(in), len(in[0])

buf := make([]T, m*n)

out = make(M, m)
for i := range out {
out[i] = buf[:n:n]
buf = buf[n:]
copy(out[i], in[i])
}
return out
}

Allocate a large buffer, slice it, copy the data.


310 Fill array with random
bytes import "math/rand" use rand::prelude::*;
Fill the byte array a with
randomly generated rand.Read(a) let mut rng = rand::thread_rng();
bytes. rng.fill(&mut a);
Note that the package math/rand is not crypto-secure

Alternative implementation:

import "crypto/rand"

_, err := rand.Read(a)

The package crypto/rand is secure (but slower than


math/rand)
312 List equality
Set b to true if the lists p import "golang.org/x/exp/slices" b = p == q;
and q have the same
b := slices.Equal(p, q) p and q must be the same type otherwise it will not compile.
size and the same
elements, false
slices.Equal is generic and type-safe at compile time.
otherwise.
313 Map equality
Set b to true if the maps import "golang.org/x/exp/maps"
m and n have the same
key/value entries, false b := maps.Equal(m, n)
otherwise.
maps.Equal is generic and type-safe at compile time.
314 Fill array with value
Set all the elements in
for i := range x { x.fill(v);
x[i] = v
the array x to the same v must implement Clone.
}
value v

Alternative implementation:

func fill[T any](x []T, v T) {


for i := range x {
x[i] = v
}
}

fill is generic, it works for any type parameter T


315 Memoization
Given any function f, func memoize[T comparable, U any](f fun
create an object or c(T) U) func(T) U {
function m that stores memory := make(map[T]U)
the results of f, and calls
f only on inputs for which return func(t T) U {
the result is not stored if u, seen := memory
yet. [t]; seen {
return u
}
u := f(t)
memory[t] = u
return u
}
}

memoize is generic but requires that f accepts a single


argument of type T and returns a single result of type U.
316 Count occurrences in a
list
c := 0
Determine the number c for _, v := range x {
of elements in the list x if p(v) {
that satisfy the predicate c++
p. }
}

Alternative implementation:

func count[T any](x []T, p func(T) boo


l) int {
c := 0
for _, v := range x {
if p(v) {
c++
}
}
return c
}

This generic func works for any type parameter T


317 Random string
Create a string s of n import "math/rand" use rand::distributions::Alphanumeri
characters having c;
uniform random values const alphanum = "ABCDEFGHIJKLMNOPQRSTU use rand::Rng;
out of the 62
VWXYZabcdefghijklmnopqrstuvwxyz01234567
alphanumeric values A- 89" fn random_string(n: usize) -> String {
Z, a-z, 0-9 rand::thread_rng()
func randomString(n int) string { .sample_iter(Alphanumeric)
a := make([]byte, n) .take(n)
for i := range a { .map(char::from)
a[i] = alphanum[rand.In .collect()
tn(len(alphanum))] }
}
return string(a)
Alternative implementation:
}
use rand::distributions::{Alphanumeri
Each of these runes fits in a single byte. c, DistString};
The default RNG can be run concurrently, as it incurs the
cost of a Mutex. fn random_string(n: usize) -> String {
Note that the package math/rand is not crypto-secure Alphanumeric.sample_string(&mut ran
d::thread_rng(), n)
Alternative implementation:
}
import "math/rand"

const alphanum = "ABCDEFGHIJKLMNOPQRSTU


VWXYZabcdefghijklmnopqrstuvwxyz01234567
89"

func randomString(n int, rng *rand.Ran


d) string {
a := make([]byte, n)
for i := range a {
a[i] = alphanum[rng.Int
n(len(alphanum))]
}
return string(a)
}

Using a custom rand.Rand instance lets you control the


seed, and is also better for performance (lock-free).
Note that the package math/rand is not crypto-secure.

Alternative implementation:

import "math/rand"

var alphanum = []rune("ABCDEFGHIJKLMNOP


QRSTUVWXYZabcdefghijklmnopqrstuvwxyz012
3456789")

func randomString(n int, rng *rand.Ran


d) string {
a := make([]rune, n)
for i := range a {
a[i] = alphanum[rng.Int
n(len(alphanum))]
}
return string(a)
}

This version is slightly more generic: it works with an


alphabet of arbitrary runes, which don't need to fit in a
single byte each.

Note that the package math/rand is not crypto-secure.


318 Cryptographically
secure random number import "crypto/rand" use rand::prelude::*;
Assign to the integer x a import "math/big"
random number between let mut rng = rand::thread_rng();
0 and 17 (inclusive), bi, err := rand.Int(rand.Reader, big.Ne let x = rng.gen_range(0..18);
from a crypto secure wInt(18))
x := int(bi.Int64()) Any generator which implements https://rust-
random number
random.github.io/rand/rand/trait.CryptoRng.html is
generator.
crypto/rand.Int works with big ints, and the secure RNG cryptographically secure.
Reader.
319 Generator function
Write a function g that
func generator() chan int {
behaves like an iterator.
ch := make(chan int, 16)
Explain if it can be used
go func() {
defer close(ch)
directly in a for loop.
timeout := time.After(2
* time.Minute)

for i := 0; i < 1024; i


++ {
select {
case ch <- i:
case <-timeout:
return
}
}
}()
return ch
}

320 Test if string is empty


Set b to true if the string
b := s == "" b = s.is_empty()
s is empty, false
Strings cannot be nil Both &str and String have a method called is_empty
otherwise
321 Access character in
string, by index c := []rune(s)[i] let c = s.chars().nth(i).expect("s is t
Assign to c the value of oo short");
s is assumed valid UTF-8.
the i-th character of the
Convert s to a slice of rune.
string s.

Make sure to properly


handle multi-byte
characters. i is the
character index, which
may not be equal to the
byte index.
322 replace value of
variable with new one old, x = x, new std::mem::replace(&mut x, v);
and return old value
323 Set HTTP request
header import "io"
Make an HTTP request import "net/http"
with method GET to the
URL u, with the request req, err := http.NewRequest("GET", u, n
header "accept- il)
encoding: gzip", then
if err != nil {
store the body of the return err
response in the buffer }
data. req.Header.Set("accept-encoding", "gzi
p")
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
data, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return err
}

http.Request.Header is an exported field


324 Read HTTP response
header import "net/http"
Set the string c to the
(first) value of the header c := res.Header.Get("cache-control")
"cache-control" of the
http.Response.Header is an exported field
HTTP response res.
325 Create a queue
Create a new queue q,
type Queue[T any] struct { use std::collections::VecDeque;
items []T
then enqueue two
elements x and y, then
} let mut q = VecDeque::new();
dequeue an element into q.push_back(x);
the variable z.
func (q *Queue[T]) Enqueue(t T) { q.push_back(x);
q.items = append(q.items, t) let z = q.pop_front();
} println!("1st item ~> {}",z.unwrap());

func (q *Queue[T]) Dequeue() T {


t := q.items[0]
var zero T
q.items[0] = zero
q.items = q.items[1:]
return t
}

q := new(Queue[string])
q.Enqueue(x)
q.Enqueue(y)
z := q.Dequeue()

The generic type Queue works for any type parameter T


326 Milliseconds since
Unix epoch import "time"
Assign to t the number
of milliseconds elapsed t := time.Now().UnixMilli()
since 00:00:00 UTC on 1
January 1970.
327 Convert string to lower
case import "strings" let t = s.to_lowercase()
Assign to t the value of
t := strings.ToLower(s) works on &str, String and char.
the string s, with all
letters mapped to their
lower case.
328 Convert string to upper
case import "strings"
Assign to t the value of
the string s, with all t := strings.ToUpper(s)
letters mapped to their
upper case.
329 Read value in a map
Assign to v the value v := m[k]
stored in the map m for
If m doesn't have the key k, then v is set to the zero value of
the key k.
m's values type.

Explain what happens if Alternative implementation:


there is no entry for k in
v, ok := m[k]
m.
ok is set to true if m has an entry for the key k, false
otherwise.
330 Map to list
Create the list a
a := make([]V, 0, len(m))
containing all the values
for _, v := range m {
of the map m.
a = append(a, v)
}
Ignore the keys of m. The values have type V
The order of a doesn't
matter. a may contain Alternative implementation:
duplicate values.
import "golang.org/x/exp/maps"

a := maps.Values(m)

You might also like