The for
comprehension is a syntax shortcut to combine flatMap
and map in a way that's easy to read and reason about.
Let's simplify things a bit and assume that every class that provides both aforementioned methods can be called a monad and we'll use the symbol M[A] to mean a monad with an inner type A.
Some commonly seen monads
List[String]
whereM[_]: List[_]
A: String
Option[Int]
whereM[_]: Option[_]
A: Int
Future[String => Boolean]
whereM[_]: Future[_]
A: String => Boolean
Defined in a generic monad M[A]
/* applies a transformation of the monad "content" mantaining the
* monad "external shape"
* i.e. a List remains a List and an Option remains an Option
* but the inner type changes
*/
def map(f: A => B): M[B]
/* applies a transformation of the monad "content" by composing
* this monad with an operation resulting in another monad instance
* of the same type
*/
def flatMap(f: A => M[B]): M[B]
Examples:
val list = List("neo", "smith", "trinity")
//converts each character of the string to its corresponding code
val f: String => List[Int] = s => s.map(_.toInt).toList
list map f
>> List(List(110, 101, 111), List(115, 109, 105, 116, 104), List(116, 114, 105, 110, 105, 116, 121))
list flatMap f
>> List(110, 101, 111, 115, 109, 105, 116, 104, 116, 114, 105, 110, 105, 116, 121)
1. Each line in the expression using the <-
symbol is translated to a flatMap
call, except for the last line which is translated to a concluding map
call, where the "bound symbol" on the left-hand side is passed as the parameter to the argument function (what we previously called f: A => M[B]
):
// The following ...
for {
bound <- list
out <- f(bound)
} yield out
// ... is translated by the Scala compiler as ...
list.flatMap { bound =>
f(bound).map { out =>
out
}
}
// ... which can be simplified as ...
list.flatMap { bound =>
f(bound)
}
// ... which is just another way of writing:
list flatMap f
2. A for-expression with only one <-
is converted to a map
call with the expression passed as argument:
// The following ...
for {
bound <- list
} yield f(bound)
// ... is translated by the Scala compiler as ...
list.map { bound =>
f(bound)
}
// ... which is just another way of writing:
list map f
As you can see, the map
operation preserves the "shape" of the original monad
, so the same happens for the yield
expression: a List
remains a List
with the content transformed by the operation in the yield
On the other hand each binding line in the for
is just a composition of successive monads
, which must be "flattened" in order to maintain a single "external shape".
Suppose for a moment that each internal binding was translated to a map
call, but the right-hand was the same A => M[B]
function, you would end up with a M[M[B]]
for each line in the comprehension.
The intent of the whole for syntax is to easily "flatten" the concatenation of successive monadic operations (i.e. operations that "lift" a value in a "monadic shape": A => M[B]
), with the addition of a final map operation that possibly performs a concluding transformation.
I hope this explains the logic behind the choice of translation, which is applied in a mechanical way, that is: n
flatMap
nested calls concluded by a single map
call.
case class Customer(value: Int)
case class Consultant(portfolio: List[Customer])
case class Branch(consultants: List[Consultant])
case class Company(branches: List[Branch])
def getCompanyValue(company: Company): Int = {
val valuesList = for {
branch <- company.branches
consultant <- branch.consultants
customer <- consultant.portfolio
} yield (customer.value)
valueList reduce (_ + _)
}
As already said, the shape of the monad is mantained through the comprehension, so we start with a List
in company.branches
, and must end with a List
.
The inner type instead changes and is determined by the yield
expression: which is customer.value: Int
valueList
should be a List[Int]
When you have injected children in an injected parent actor, you might get deadLetters
when trying to access the sender from inside the created children.
This is because the sender of the message gets picked up via an implicit
parameter.
The signature is:
def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit
The sender gets picked up from this implicit parameter. When sending a message from within the parent actor, this parameter is set to the default value: Actor.noSender
which translates to deadLetters
when accessing sender from within the children.
In order to have access to the sender inside the child, we can use tell
:
final def tell(msg: Any, sender: ActorRef): Unit = this.!(msg)(sender)
This way, sender can be correctly set and passed to the child actor.
A "simple" way of extracting the fields from any case class:
def extractFieldNames[T<:Any](implicit m: Manifest[T]) = {
implicitly[Manifest[T]].runtimeClass.getDeclaredFields.map(_.getName).filter(!_.equals("$outer"))
}
The fallacies of distributed computing are a set of assertions made by L Peter Deutsch and others at Sun Microsystems describing false assumptions that programmers new to distributed applications invariably make.
These result either in the failure of the system, a substantial reduction in system scope, or in large, unplanned expenses required to redesign the system to meet its original goals.
Source: https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing
Docker images aparently have no connectivity. Issue resides with the dns resolvers.
Looks like when using ips, everything works; when using names, it doesn't work.
Two ways of doing this...
Edit the file: /etc/NetworkManager/NetworkManager.conf
Comment the line containing dns=dnsmasq
.
Restart networking: sudo systemctl restart network-manager
Restart docker: sudo systemctl restart docker
On elementary loki (ubuntu 16.04), docker configuration file is here: /lib/systemd/system/docker.service
Edit this config file and add to ExecStart like this: ExecStart=/usr/bin/docker daemon -H fd:// --bip=192.168.169.1/24
Run: sudo systemctl daemon-reload
Stop docker service: systemctl stop docker
Install brctl to control the bridge: sudo apt-get install bridge-utils
Bring down the bridge: sudo ip link set docker0 down
Delete the bridge: sudo brctl delbr docker0
Restart docker: systemctl start docker
Option #2 did not work for me. Option #1 did.
Source and more details: http://stackoverflow.com/a/35519951/3004463
Before all this, we must have ssh key added to gitlab / github
Check username and emailgit config user.name
git config user.email
Set username and emailgit config user.name Someone
git config user.email someone@something.com
Use option --global to set it globally, for all future projects
Go to folder where we want to init the repogit init #initializez a git repo
Add a new remote to be used.
For remote_name `origin` is usually used; url is taken from gitlab/github pagegit remote add <remote_name> <url>
Fetch everything (all branches) from remotegit fetch
Change to another branchgit checkout <branch_name>
Update a branch - usually done after moving to itgit pull <remote_name> <branch_name>
If already on a branch, short version can be usedgit pull
Add new/modified files to be commitedgit add <relative_path/to/file/or/folder>
Commit added filesgit commit -m "Commit message"
Push changesgit push -u <remote_name> <branch_name>
Change necessary files on the master branch (for example, since everything should be relative to master)
Create new branchgit checkout -b <new_branch_name>
This will create the new branch, add everything to it and move to the new branch
Add changes to be commitedgit add relative/path/to/files
Commit changes on the new branch, specifying what issue this commit fixesgit commit -m "Commit message. Fixes#<issue_number>"
Push everything (the new branch, changes, everything)git push -u <remote_name> <new_branch_name>
Now go to github / gitlab and create a merge request.
docker images
docker ps -a
docker ps -aq | xargs docker stop && docker ps -aq | xargs docker rm
docker build . -t <image_tag>
docker network create -d <network_type> --subnet x.x.x.x/mask --ip-range x.x.x.x/mask <network_name>
Example: docker network create -b bridge --subnet 192.168.10.0/28 --ip-range 192.168.10.1/29 net1
docker run [OPTIONS] <image_name> [COMMAND] [ARG...]
Where OPTIONS can be:
-i
- interactive, keep stdin open even if not attached-t
- allocate a pseudo tty-d
- detach, run dontainer in background and print container id-h <host_name>
- container host name string-p host_port:container_port
- publish container's ip to host; host will forward requests to the container on the specified port; can be used multiple times--network <network_name>
- specify a custom network to run this container in--name <custom_container_name>
- assign a name to this container--ip <set_ip_value>
- assign a fixed ip value to the docker containerExample:
docker run -d --network net1 -p 9000:9000 --name my_image -h my_image_host my_local_image
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}' <container_name>
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container_name>
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RouteExtractor {
//something like "/foo/$id<[^/]+>/edit/$james<[^/]+>"
private String routePattern;
private String path;
//something like /$id<[^/]+>
private static final String INDEX_PATTERN = "\\$(.+?)<\\[\\^/]\\+>";
public RouteExtractor(String routePattern, String path) {
this.routePattern = routePattern;
this.path = path;
}
private Map<Integer, String> extractPositions() {
Pattern pattern = Pattern.compile(INDEX_PATTERN);
Matcher matcher = pattern.matcher(this.routePattern);
Map<Integer, String> results = new HashMap<>();
int index = 0;
while (matcher.find()) {
results.put(index++, matcher.group(1));
}
return results;
}
private String replaceRoutePatternWithGroup() {
Pattern pattern = Pattern.compile(INDEX_PATTERN);
Matcher matcher = pattern.matcher(this.routePattern);
return matcher.replaceAll("([^/]+)");
}
public Map<String, String> extract() {
Pattern pattern = Pattern.compile(this.replaceRoutePatternWithGroup());
Matcher matcher = pattern.matcher(this.path);
final Map<String, String> results = new HashMap<>();
if (matcher.find()) {
this.extractPositions().forEach((key, value) -> results.put(value, matcher.group(key + 1)));
}
return results;
}
}
Source here.
Here is a small code for generating random alphanumeric strings of specified length:
import java.math.BigInteger;
import java.security.SecureRandom;
public class KeyGenerator {
private static final SecureRandom secureRandom = new SecureRandom();
public static String generate(int stringLength) {
return new BigInteger(stringLength * 5, secureRandom).toString(32);
}
}
This works by choosing a multiple of 5 bits from a cryptographically secure random bit generator and encoding them in base-32.
Each digit in a base-32 number can encode 5 bits. So the multiplier would give the number of resulting characters.
This encoding is compact and efficient, with 5 random bits per character. Compare this to a random UUID, which only has 3.4 bits per character in standard layout, and only 122 random bits in total.
Note that SecureRandom objects are expensive to initialize so you'll want to keep one around and reuse it.
Based on this answer.