I think it is worth to point out another one peculiarity of `With` as compared to `Module` and `Block` which is little-known: `With` doesn't evaluate it's last argument at all, while both `Module` and `Block` evaluate their last arguments. In other words, the last argument of `With` will be evaluated only after leaving the `With` construct. This can be easily proven as follows:

 With[{}, Stack[_]]
 Module[{}, Stack[_]]
 Block[{}, Stack[_]]
 

> {}
> 
> Module[{}, Stack[_]]
> 
> Block[{}, Stack[_]]

One can see that in the case of `With` the stack is empty because evaluation of `With` is already finished when `Stack[_]` is being evaluated, while in the case of `Module` and `Block` the `Stack[_]` is evaluated inside of the scoping construct. 


----------


Another thing which is useful to know is that all these constructs support **delayed assignments** for local variables:

 With[{a := Random[]}, {a, a, a}]
 Module[{a := Random[]}, {a, a, a}]
 Block[{a := Random[]}, {a, a, a}]
 

> {0.637223, 0.284761, 0.180292}
> 
> {0.139856, 0.55708, 0.585556}
> 
> {0.888018, 0.961141, 0.451441}

An example of use:

- [Using `With[…]` with a list specification as a variable](https://mathematica.stackexchange.com/a/204119/280)