this
in javascript is always a mysterious thing. Some programmers who have written a lot of javascript code still cannot tell the value of this
every now and then. So today, I decided to write an article about it to solve the problem once and for all. I think you would be able to fully understand what this
refers to in almost all situations after you read this article.
this
is used in a normal function(i.e. not an arrow function), this
refers to the object that calls the function.This is the most important rule, let’s use several examples to illustrate what it means.
1  var obj = { 
this
is in a normal function foo
, and foo
is called by obj
. So this
refers to obj
here.
1  function foo() { 
This is different, nothing calls foo()
, right? Well, not exactly. In fact, foo()
is the same as window.foo()
, so this
refers to window
here, which is the global object in javascript.
1  var obj = { 
This time the function that gets executed is not obj.foo
, it’s bar
, because obj.foo
is assigned to bar
.
this
refers to object that calls bar
instead of obj.foo
in this case, because obj.foo
has been assigned to bar
. Who calls bar
? window
. So this
refers to window
here.
this
is only injected into context when the function which contains this
is called. We cannot determine the value of this
only by its definition. We have to see who calls this
to determine its value. You can find it in the above code that the value of this
may be different when it’s called in different ways.this
remains unchanged when evaluated using eval
directly, and is equal to window
when evaluated using eval
indirectly.Using eval
directly means something like: eval('this')
.
Using eval
indirectly means something like (1, eval)('this')
.
Let’s look at the code first.
1  var obj = { 
To solve the problem, let’s first insert another line in the above code.
1  var obj = { 
Do you know what this
in the inserted line refers to? Of course it’s obj
, we have talked about it a while before. So what’s the value of eval('this')
? It’s exactly the same, obj
! It doesn’t change.
What if we use eval
indirectly?
1  var obj = { 
When eval
is used indirectly, this
in it refers to window
, simple rule.
this
in arrow functions is the same as this
in the outer context.Still, code first.
1  function bar() { 
OK, this time, this
is used in an arrow function. According to Rule 3, we have to find out what this
is in the outer context with respect to the arrow function obj.foo
. Some people don’t know what outer context is. Actually, the outer context can be seen as the context where obj.foo
gets executed.
Let’s insert another line in the above code.
1  function bar() { 
Do you know what this
refers to in the inserted line? Of course, it refers to window
, because it’s window
that calls bar
. So what this
refers to in the original code(the 4th line)? It’s the same! Because the outer context of obj.foo
is exactly the context where the inserted line is in.
this
refers to window
when used an inline event handler, and refers to the attached DOM element when used in a separate event hanlder.1  <html> 
this
is used in an inline event handler foo
here, so this
refers to window
.
1  <html> 
this
is used in a separate event handler foo
here. So it refers to the DOM element button
according to Rule 4. In fact, we can also use Rule 1 to get the same answer. Because each time the button is clicked, button.onclicked
is executed. Who calls the onclick
function? button
. So the answer is button
.
this
in most JQuery callbacks refers to the attached JQuery element1  <html> 
According to Rule 5, this
refers to $("button")
here. You may wonder why it is the case. In fact, JQuery calls the callback using something like this:
1  function click(callback) { 
callback.call($("button"))
is the same as callback()
, except that it sets the this
in callback
as $("button")
, so you can happily use this
as the JQuery element inside the callback function.
Now today, which is about a month later, I decided to abandon WordPress altogether. WordPress is an excellent blogging platform, I have to admit it. But I cannot find a reliable way to use markdown in WordPress, and I also noticed some odd behaviors of the visual editor used in WordPress. Nothing is more convenient and portable than writing my blogs in vim using markdown. So finally I decided to abandon it and embrace hexo and hueman again.
I will consider moving some of the blogs written in WordPress back in here.
]]>Heaps are divided into two parts in Java, one is called the Young Generation, and the other one is called the Old Generation. You may have seen something called the Permanent Generation in other tutorials/documentations. It exists in Java 7 and before, Oracle removed it in Java 8.
The Young Generation is also divided into three parts:
The whole picture in Heap is as follows.
Basically, there are two types of garbage collections for most collectors:
Young Generation Collection is meant to be timeefficient and frequent, this is different from the Old Generation Collection, which could take a long time, and it’s done less frequently. The Old Generation usually has larger heap space.
Young Generation Collection Using the Serial Collector
When you new
an object in the Java code, the space for that object will be allocated in the Eden Area. After a while, the Eden Area may be filled up, so live objects in it will be copied into one of the Survivor Space, let’s say it’s Survivor Space 1. Some large objects that won’t be fit in the Survivor Space will be copies into the Old Generation.
After a while, some live objects in Survivor Space 1 become dead, i.e., they are not referenced by any other objects anymore, and some more space is allocated in the Eden Area for newly initiated objects.
Now you can see, objects exist in Eden and Survivor Space 1, and Survivor Space 2 is empty. This is where the interesting thing begins. Because from now on, what the Young Generation does is to repeat the following process.
When the Eden Area is filled up again. live objects in it will be copied into Survivor Space 2(Some large objects that are too large to fit in Survivor Space will be copied into the Old Generation). The live objects that are relatively young are copied into the Survivor Space 2, live objects that are relatively old(i.e., they survived through several Young Generation Collections) are copied into the Old Generation.
Then all dead objects in the Eden and Survivor Space 1 will be garbage collected, the two survivor spaces swap roles, the Survivor Space 1 is empty while the Survivor Space 2 is not, and the above process will be repeated.
Old Generation Collection Using the Serial Collector
Old Generation Collection is divided into three steps, marksweepcompact. In the mark phase, the collector identifies live objects, the sweep phase sweeps over the generation and frees space taken by dead objects. Then the collector moves all live objects to the beginning of the old generation, which is called compaction. The compaction is for quick space allocation in the old generation later on.
When to Use the Serial Collector
The Serial Collector is done in a singlethreaded way, so it’s meant to be run on clientstyle machines that do not require low pause times. And since it only takes a small amount of memory, the serial collector can perform very well with only 64MB heaps in most cases.
Young Generation Collection Using the Parallel Collector
Young Generation collection in the parallel collector is the same as the Serial Collector, except that it’s done in parallel. The Parallel Collector fully utilizes the power of multiple threads and make the process of Young Generation Collection faster. Although the Young Generation Collection is still a stoptheworld action, the process would take less time and make less impact to the running program.
Old Generation Collection Using the Parallel Collector
Old Generation Collection using the Parallel Collector is the same as the Serial Collector.
When to Use the Parallel Collector
You can use the Parallel Collector when you have multiple CPU cores, whose power could be unleashed and utilized by it. But also notice that the Parallel Collector wouldn’t help you a lot if you need a much shorter pause time in GC, because it still takes a long time to finish the Old Generation Collection, which is done in a singlethreaded way in the Parallel Collector.
Young Generation Collection Using the Parallel Collector
Young Generation Collection using the Parallel Compacting Collector is the same as the Parallel Collector.
Old Generation Collection Using the Parallel Collector
Old Generation Collection in the Parallel Compacting Collector is done in a multithreaded way, this is different from the Parallel Collector, whose uses only a single thread to complete Old Generation Collection.
There are in total three phases regarding Old Generation Collection.
1. Mark(multithread)
First of all, the old generation is divided into several regions of the same fixed sizes. Then live objects that are directly reachable from the code are divided equally among multiple threads. Those threads work concurrently to mark all live objects in the old generation, storing the size and location of each live object.
2. Summary(singlethread)
Due to previous compactions, some portions on the left side of the old generation are typically denser than those on the right side of it. So the collector will search from the left side, calculate the density of live objects in each region until it reaches a point where the density is small enough to be considered eligible for garbage collection. All the regions to the left of the point are not worth garbage collecting, and they will not be moved, those regions are called dense prefix. All the regions to the right of the point will be garbage collected. After collection, the collector will store the location of the first live object in each region, which would be helpful in the compaction phase.
3. Compaction(multithread)
Live objects on the right side will be moved to the left side of the old generation, leaving a huge chunk of contiguous free memory on the right side. This process is called compaction.
When to Use the Parallel Compacting Collector
You can use the Parallel Compacting Collector if you have multiple CPU cores that could be utilized. The collector will take advantage of those CPU cores and make the total pause time shorter.
Young Generation Collection Using the CMS Collector
Young Generation Collection using the CMS Collector is the same as the Parallel Collector.
Old Generation Collection Using the CMS Collector
There are four phases in total in the Old Generation Collection using the CMS Collector.
1. Initial Mark(single thread)
All live objects that are directly reachable from the code are marked as alive. It takes a short pause to do it.
2. Concurrent Mark(multithread)
While the application is running, the collector marks live objects that are transitively reachable from the above set obtained from the Initial Mark.
3. Remark(multithread)
Because the Concurrent Mark is conducted while the application is still running, some live objects cannot be detected in the second phase. So the application stops for a while, and the collector checks all objects that are modified during the Concurrent Mark phase, and mark all objects that turned garbage during the previous phase. After the Remark phase, all live objects are marked.
4. Sweep(multithread)
The collector conducts a Sweep operation to eliminate all garbage in the Old Generation.
Disadvantages of the CMS Collector
The CMS Collector is the only collector that has no compact phase, which means it cannot use the bumpthepointer strategy(see reference below) to find free space.
bumpthepointer strategy: This is a strategy used to allocate new space in the Old Generation. With this strategy, you only need to store the position of the last live object after each Old Generation Collection. When you need to allocate a space to store a new object, what you need to do is just to allocate the space right after the position and update the position to the new one. There are no live objects after that position because the Old Generation has been compacted before. The strategy is used in all above collectors except the CMS Collector because the CMS Collector doesn’t compact the Old Generation.
So how does the CMS Collector find new space to allocate? Basically, it maintains a linked list internally, which connects all free space together. When an allocation is needed, the collector will traverse through the list and find the appropriate region to allocate the space.
Another disadvantage of the CMS Collector is that it needs a bigger heap size because the Concurrent Mark phase proceeds while the application is still running, which means more space needs to be allocated when some garbage cannot be collected in time. So enough heap size must be prepared to store both uncollected garbage and newly allocated space.
When to Use the CMS Collector
The CMS Collector is typically used in the server side application, where large heap size and multiple CPU cores could be utilized. Those applications usually require a smaller pause time, which is exactly what the CMS Collector is good at.
G1 Collector is different from previous collectors. All the previous collectors have a young generation and an old generation of fixedsize. This is the not the case for the G1 Collector. For the G1 Collector, the entire heap is divided into approximately 2000 areas, the size of each area is around 1MB ~ 32MB. The type of these areas may be different, it may be eden, survivor area, or the old generation. The whole picture is as follows.
Although the size of each region is the same in the above picture, in reality, this may not be the case. The size of each region usually depends on how the collector optimizes the collection algorithm, and they are changing constantly.
Notice that Humongous Region is used to store objects that are larger than 50% of the normal region size. Currently, no optimization is applied to this type of region, so avoid using objects that are too large.
Young Generation Collection Using the G1 Collector
Old Generation Collection Using the G1 Collector
I’m almost 27, I told my self. And it is 2017, 17 years after 2000, I could never figure out where those years went. So many years, I’m getting older every day. Does the performance in the work really matter? Not sure, maybe not that important. So what really matters? I know it, I always know it, but I’m always afraid to face it.
I started trying to solve problems on leetcode, that was for my career. Sometimes I thought maybe I just needed to choose a life and went with it, but I really hoped the life I chose would be perfect, or at least full of happiness and fulfillment, but actually it was not.
I often think of the Sergeant in Forrest Gump, he lost his legs during the war, he didn’t know what to do. He cursed his life, joked about God, but when he finally got a normal life, he didn’t say anything. He never mentioned whether God existed or not, maybe he still didn’t know. I often pondered over the same question, but I had no answer to it. Why wouldn’t God give me a better life? Maybe he has his reason, I just need to go with it.
It’s already late, I have to go to bed and sleep. I wrote some nonsense here, whatever.
]]>As what is called, Configuration
is used to store all kinds of configurations in the hadoop platform, either they are from files(like coredefault.xml
) or from users(set via conf.setInt("dfs.replication", 1)
). It would also warn you if you use a deprecated key. So how does it work? I will try to explain it in the source code level.
Configuration can be serialized in the file system and deserialized again into an instance. It implements the Writable
interface to achieve this. There are only two methods in the Writable
interface, write
and readFields
, just as follows.
1  public interface Writable { 
As you can see, we call write
when we need to serialize a Configuration
instance into file, and we call readFields
when we need to deserialize it from file. In fact, I wrote several lines to show how to serialize and deserialize a Configuration
instance.
1  package com.example; 
To run it, you have to create a maven project and add hadoopcommon
as a dependency.
1  <dependency> 
Run it, and you will notice that a file confi.ser
is created out of it, it stores the instance of Configuration
, then we load it(aka deserialize it) from the file and get the instance. We can look through the source code of write
and readFields
implemented in Configuration
to know more about it.
1  public class Configuration implements Iterable<Map.Entry<String,String>>, 
As you can see, the fields that serialization and deserialization apply to are this.properties
and this.updateResource
, the former stores all the configurations, which is the most important field in Configuration
, and the latter stores the mapping of key to the resource which modifies or loads the key most recently. For example, if Configuration
loads a file configuration.xml
, which modifies the configuration dfs.replication
, a new item will be added to this.updateResource
:
1  this.updateResource.put("dfs.replication", new String[]{"configuartion.xml"}); 
When Configuartion
is loaded, a default list of deprecated keys will be loaded into defaultDeprecations
too.
1  private static DeprecationDelta[] defaultDeprecations = 
When you try to set a configuration via something like configuration.set("name", "value")
, it will first check if the key provided is deprecated, and if it is, it will store both deprecated and new keys in itself with the given value, and warn once to the user that the key should not be used.
1  public void set(String name, String value, String source) { 
When Configuration
is loaded, it will try to find two files in the classpath: coredefault.xml
and coresite.xml
, then load them if they are found.
1  static{ 
I downloaded the movie Passenger
from the Internet and watched it last night. To my suprise, although there were lots of negative comments on douban
, I found the movie pretty interesting and compelling. Maybe it was due to the unbeatable charm of Jennifer Lawrence
, she was so beautiful. That being said, the plot was not bad, and the film’s special effects were amazing! I really loved it. I even loved it to the extent that I couldn’t decide whether Arrival
or Passenger
was better, even though the former got a much higher mark on douban
and IMDB
.
Another thing. I decided to use Wechat
as few as possible. I watched a Ted talk yesterday and the speaker said that falling into social media was really a bad thing for us. It might cause more anxiety and depression and made us even more lonely, no matter how many friends we had ONLINE. I thought that was absolutely correct. I felt more lonely when I talked in social media, our brain wasn’t designed to talk like this. We have to communicate face to face, use our gestures and expressions to create a better conversation and relax ourselves. Really, few people care about what I post on moments, what is the purpose of that!
Modify /etc/opkg.conf
to the following lines.
1  dest root / 
1  sudo aptget install fcitx fcitxtable fcitxgooglepinyin fcitxmodulecloudpinyin 
Search for language support
, and check Keyboard input method system
is fcitx
Reboot.
Go to the configuration of fcitx –> Addon –> Cloud Pinyin –> Configure –> Cloud Pinyin Source –> Change from google to baidu.
]]>Create a file brightness.service
in /lib/systemd/system
with the following contents(Change 100 to whatever brightness you want, roughly it’s between 0 ~ 1000).
1  [Unit] 
Enable it.
1  sudo systemctl enable brightness. 
Restart. It will work.
]]>To make it work, modify /etc/default/keyboard, change
1  XKBOPTIONS="" 
to
1  XKBOPTIONS="caps:ctrl_modifier" 
Then add the following line in ~/.xsessionrc
1  #!/usr/bin/env zsh 
Reboot.
]]>shadowsocks
globally(You have to add sudo
here)
1  sudo pip install shadowsocks 
Create a new file called shadowsocks@.service
in /lib/systemd/system
1  [Unit] 
Put all your shadowsocks config files in /etc/shadowsocks, like this.
1  ls /etc/shadowsocks 
Start
1  sudo systemctl start shadowsocks@bandwagonhost.service 
Then enable all of them.
1  sudo systemctl enable shadowsocks@bandwagonhost.service 
I enjoy using i3wm, big time. You can switch to different windows/apps conveniently with it. The only problem to me is that it’s not beautiful enough, and it’s ridiculously small in my highresolution screen. So I decided to change it a little bit.
Here is what you would get after applying the method.
To change the appearance, you only need to modify the config file, usually it’s ~/.config/i3/config
. Add the following lines.
1  font pango:nimbus sans 18 
Remove those lines.
1  font pango:DejaVu Sans Mono 10 (Or whatever the font is) 
Then install conky
and fontawesome
, create a new file ~/.i3/conky/conkyrc
, put the following lines in it.
1  ### lovelybacon.deviantart.com #### 
Restart i3, the shortcut of mine is Shift+$mod+r
, $mod
could either be Alt
or Super key
The above contents are from lovelybacon.deviantart.com, thanks for your amazing work. I only did a few modifications.
]]>According to the definition of $\subset$,
$\varnothing\subset A\Leftrightarrow$
$\forall x$, if $x\in\varnothing$, then $x\in A$.
This is a vacuous truth, because the antecedent ($x\in\varnothing$) could never be true, so the conclusion always holds ($x\in A$). So $\varnothing\subset A$ holds.
Maybe you are thinking, OK, this is a vacuous truth, so maybe I can change it so that the following expression is also true.
$\forall x$, if $x\in\varnothing$, then $x\not\in A$.
Then you could say, $\varnothing\subset A$ is false.
This is what I asked on math.stackexchange.com the other day, and I read through all the answers and comments in it. Then I realized the above expression doesn’t mean $\varnothing\not\subset A$, it just means $\varnothing\subset A^c$.
I think what $\varnothing\not\subset A$ means is
$\exists x, x\in\varnothing$ and $x\not\in A$
Since you can never find $x$ such that $x\in\varnothing$, so the condition could never be correct, so we don’t have enough evidence to make the conclusion($\varnothing\not\subset A$).
Notice the whole expression itself(If there exists $x\in\varnothing$ such that $x\not\in A$, then we say $\varnothing\not\subset A$) is correct since it’s a vacuous truth(the condition could never be true).
In fact
$\exists x, x\in\varnothing$ and $x\not\in A\Leftrightarrow$ $\varnothing\not\subset A$
Because
$\exists x, x\in\varnothing$ and $x\not\in A$
is false, so
$\varnothing\not\subset A$
is false, which makes $\varnothing\subset A$ true.
]]>Poisson distribution can be derived from Binomial distribution when $\lim\limits_{n\to\infty}np = \lambda(\lambda\in\mathbb R)$, in which $n$ is the number of trials, $p$ is the probability of success in each trial. But how is the formula of poisson distribution obtained? Why is $p$ getting smaller when $n$ approaches infinity? I will try to answer these questions in this post.
Imagine there’s a call center in your local city, it receives a certain amount of calls per day. Let’s say the expected value of the number of the received calls is $\lambda$. Now we need to calculate the probability of the number of received calls equaling $x$. How can we do it?
Let’s split one day into $n$ periods. So there could exist the two following cases for each period of time.
Whether there being calls received in each period of time is independent. Let’s define the following symbols:
It can be easily found out that $P(X=x)$ follows Binomial distribution, so
$$P(X=x) = \binom n x {p_n}^x(1p_n)^{(n  x)}\tag1$$
The expected value of $X$ is
$$E(X) = np_n$$
Notice that we have another information: the average number of received calls per day is $\lambda$, which means the expected value of the number of received calls per day is $\lambda$. It’s going to come in handy later on.
Increase $n$, we will notice that the amount of time each period contains decreases, so some periods in which there exist two or more calls before only exist one or even zero call now. So the expected value of $X$ increases(because some periods in which two or more calls exists is split into multiple periods in which only one call exists), which means $np_n$ increases as $n$ increases. When $n$ is large enough, so that each period of time is so short that no more than one call can exist in one period of time, the following equation would hold in this case.
$$p_n = {p_n}’$$
So that
$$E(X) = np_n = n{p_n}’ = \lambda\tag2$$
Let’s define another variable Y
When $n$ is large enough, no more than one call exists in one period of time, so the number of periods of time in which one or more calls received($X$) equals the number of total calls received per day($Y$).
So
$$P(Y=x) = P(X=x) = \binom n x {p_n}^x(1p_n)^{(nx)}\tag3$$
How large should $n$ be to hold the above equation? 100, 10000, 10000000000? The larger, the better, so we set $n \to\infty$, so $\delta t \to 0$. In this case, no more than one call exists in one period of time.
Let’s prove that no more than one call exists in $\delta t$ when $\delta t \to 0$. Assuming more than one call exist in $\delta t$, because $\delta t \to 0$, so $\delta t$ should be smaller than $\forall \varepsilon>0$. So we can futher split $\delta t$ into several parts so each part only contains one call or no call, so no more than one call could exist in $\delta t$ when $\delta t \to\infty$. But is there a possibility that one call exists in $\delta t$? Yes. Notice that $\delta t\to 0$ doesn’t mean $\delta t = 0$. It just means $\delta t$ is smaller than any positive real number. Just like the figure of $y=\frac 1 x$ below. While $y\to0$ when $x\to \infty$, but $y$ could be smaller than any positive real number, but $y$ can never be 0.
So $p_n$ becomes the possibility of there existing only one call in each period of time, so $np_n$ becomes the total number of calls per day, i.e.
$$\lim\limits_{n\to\infty}np_n = \lambda$$
To make it work, the following equation must hold.
$$\lim\limits_{n\to\infty}p_n = 0$$
So the possibility of there existing only one call in $\delta t$ is 0. Does it mean there exists no call in any period of time? Of course not. The probability being 0 doesn’t mean it’s not possible. There will always be some calls falling into some periods of time, $p_n\to 0$ only means $p_n$ could be smaller than any positive real number. In the real world, you cannot actually make $n = \infty$, so you cannot actually make $p_n = 0$. To better illustrate what I mean, let’s define the two following events.
The number of event1 can never be 0 as long as we receive at least one call in a day. But when $n$ gets larger and larger, event2 will finally be 0. This is different although the possibility of both events is 0 when $n\to\infty$.
Let’s add $n\to\infty$, so $(3)$ becomes
$$P(Y=x) = P(X=x) = \lim\limits_{n\to\infty}\binom n x {p_n}^x(1p_n)^{(nx)}\tag4$$
Let
$$\lambda_n = np_n$$
According to $(2)$
$$\lim\limits_{n\to\infty}np_n = \lambda$$
So
$$\lim\limits_{n\to\infty}\lambda_n = \lambda$$
Put $p_n = \frac{\lambda_n} n$ into $(4)$, we get
\begin{equation}\begin{split} &P(Y=x) \\
&= \lim\limits_{n\to\infty}\binom n x(\frac{\lambda_n} n)^x(1\frac{\lambda_n}n)^{(nx)}\\
&=\lim\limits_{n\to\infty}\frac{n(n1)\cdots(nx+1)}{x!\cdot n^x}\cdot{\lambda_n}^x\cdot(1\frac{\lambda_n} n)^n\cdot(1\frac{\lambda_n} n)^{x}\\
&=\lim\limits_{n\to\infty}\frac 1 {x!} \cdot 1 \cdot \underbrace{(1\frac 1 n)\cdot(1\frac 2 n)\cdots(1\frac{x1} n)}_1\cdot\underbrace{ {\lambda_n}^x}_{\lambda}\cdot\underbrace{(1\frac{\lambda_n} n)^n}_{e^{\lambda}}\cdot\underbrace{(1\frac{\lambda_n} n)^{x}}_1\\
&=\frac{e^{\lambda}{\lambda}^x}{x!}\end{split}\end{equation}
You can find out why $\lim\limits_{n\to\infty}(1\frac{\lambda_n} n)^n = e^{\lambda}$ in this post
Q: If I was given $n$ and $p_n$, and I got $\lambda$ using $\lambda = np_n$, then I calculate the probability of there exising $x$ events in the total amount of time using the following equation.
$$P(X=x) = \frac{e^{\lambda}{\lambda}^x}{x!}$$
Is it the exact value I want or just an approximation?
A: This is just an approximation. The value you get is the number of pieces where events exist. There could be one event in a piece, there could be two or more events in a piece. So $P(X=x)$ not only includes the some of the cases where we want, but also the case where we don’t want, e.g. it also includes the case where $x+1$ events occur, but it doesn’t include the case where $x$ events fall into $x1$ or less pieces.
Q: If I was given the expected value $\lambda$, and I calculate the probability using the following equation, then I calculate the probability of there exising $x$ events in the total amount of time using the following equation.
$$P(X=x) = \frac{e^{\lambda}{\lambda}^x}{x!}$$
Is it the exact value I want or just an approximation?
A: It’s the value you want. When $n$ is not large, the reason why there is a difference between $\binom n x{p_n}^x(1p_n)^{(nx)}$ and $\frac{e^{\lambda}{\lambda}^x}{x!}$ is that $p_n$ is not exactly the value we want. That is, when $n$ is not large and we calculate the probability using $(1)$, the answer we get is
$$P(X=x) = P_1 + P_2$$
The value we want would be
$$P(Y = x) = P_1 + P_3$$
As $n\to\infty$, $P_2\to 0$, $P_3\to 0$, so $P(X=x) \to P(Y=x)$
So
$$\lim\limits_{n\to\infty}P(X=x) = \lim\limits_{n\to\infty}P(Y=x) = P_1$$
Because
$$P(X=x) = \binom n x {p_n}^x(1p_n)^{(nx)}$$
So
$$\lim\limits_{n\to\infty}P(Y=x) = \frac{e^{\lambda}{\lambda}^x}{x!}$$
Because P(Y=x) has nothing to do with what $n$ is, so $\lim\limits_{n\to\infty}P(Y=x) = P(Y=x)$
So
$$P(Y=x) = \frac{e^{\lambda}{\lambda}^x}{x!}$$
That is, the number of total events is $\frac{e^{\lambda}{\lambda}^x}{x!}$.
]]>$$c, d\in {\bf R}, \lim_{x\rightarrow \infty} f(x)=c>0, \lim_{x\rightarrow \infty} g(x) =d>0$$
then
$$\lim_{x\rightarrow \infty} f(x)^{g(x)} = c^d$$
Proof: Because
$y(x)=ln(x)$ is continuous at $x = c > 0$
$\lim\limits_{x\to \infty}f(x) = c$
according to the composition law, we have
$$\lim\limits_{x \to \infty}lnf(x) = ln\lim\limits_{x \to \infty}f(x) = lnc$$
Because $\lim\limits_{x \to \infty}g(x) = d$, we have
$$\lim\limits_{x\to \infty}g(x)lnf(x) = \lim\limits_{x\to \infty}g(x)\cdot\lim\limits_{x \to \infty}lnf(x) = dlnc$$
Apply composition law again, we get
$$\lim\limits_{x\to \infty}f(x)^{g(x)} = \lim\limits_{x\to \infty}e^{g(x)lnf(x)} = e^{\lim\limits_{x\to \infty}g(x)lnf(x)} = e^{dlnc} = c^d$$
]]>The original answer fails on some mathjax expressions. So don’t use it. Currently changing marked.js
works for me. Just use the method below. It works for me.
First introduce mathjax
into our blog. Create a new file called mathjax.ejs
in themes/hueman/layout/plugin
, and add the following contents in it.
1  <! mathjax config similar to math.stackexchange > 
Then add the following line before the end of the last div
tag in themes/hueman/layout/layout.ejs
1  <% partial('plugin/mathjax') %> 
The whole layout.ejs
file looks like this:
1  <% partial('common/head') %> 
Open ./node_modules/marked/lib/marked.js
in your blog’s root directory
Replace
1  escape: /^\\([\\`*{}\[\]()# +\.!_>])/, 
with
1  escape: /^\\([`*\[\]()# +\.!_>])/, 
The above step is used to avoid the escaping of \\
, \{
, \}
. Then replace
1  em: /^\b_((?:[^_]__)+?)_\b^\*((?:\*\*[\s\S])+?)\*(?!\*)/, 
with
1  em:/^\*((?:\*\*[\s\S])+?)\*(?!\*)/, 
Then run the following command to deploy your blog
1  hexo clean && hexo g d 
It should work now.
But today I found a new problem. You cannot write two successive curly braces.
I guess it’s because hexo tries to takes curly braces as part of a tag. I don’t have enough time to figure out how to let hexo accept it as a math expression rather than a tag. Currently I will just add a space between two curly braces. Just like { {
. It works great. If you have better idea how to deal with it, you can leave it in the comment below.
Hexo doesn’t support mathjax by default. To make it work, we need to introduce mathjax to our theme. Take my current theme hueman
as an example.
Create a new file called mathjax.ejs
in themes/hueman/layout/plugin
, and add the following contents in it.
1  <! mathjax config similar to math.stackexchange > 
Then add the following line before the end of the last div
tag in themes/hueman/layout/layout.ejs
1  <% partial('plugin/mathjax') %> 
The whole layout.ejs
file looks like this:
1  <% partial('common/head') %> 
Then mathjax would be introduced into our blog. Our work should be done. But unfortunately this is not the case, because the default markdown rendering engine would accidently render some of our mathjax code, which would of course disturb the rendering of mathjax later on. To solve this problem, we need to replace hexo’s rendering engine as pandoc
. First install pandoc on your system. I’m using arch, so the command is
1  sudo pacman S pandoc 
Then install hexorenderpandoc
. Run the following command in your blog’s root directory.
1  npm install hexorendererpandoc save 
OK, everything is done. Write a blog containing any mathjax formula and run the following command to deploy it to your server.
1  hexo clean && hexo g d 
$$\lim\limits_{x \to \infty}f(g(x)) = f(b) = f(\lim\limits_{x\to \infty}g(x))\tag1$$
Proof: Because $f(x)$ is continous at $b$, so
$$\lim\limits_{x\to b}f(x) = f(b)\tag2$$
Because $$\lim\limits_{x\to\infty}g(x) = b \tag3$$
Combine $(1)$ and $(2)$, we get
$$\lim\limits_{x\to\infty}f(g(x)) = f(b)$$
Thus we proved the right side of equation $(1)$
Now we need to prove $$\lim\limits_{x \to \infty}f(g(x)) = f(b)\tag 4$$
Because
$$\lim\limits_{x\to b}f(x) = f(b)$$
according to the definition of limit, $\forall \varepsilon > 0$, there exists a $\delta’$ such that for all $xb<\delta’$, we have
$$f(x)  f(b) < \varepsilon\tag5$$
Replace $x$ with $g(x)$ in the above conclusion, we get
$\forall \varepsilon’ > 0$, there exists a $\delta’$ such that for all $g(x)b<\delta’$, we have
$$f(g(x))  f(b) < \varepsilon’\tag6$$
Note that although $f(x)$ needs to be defined and has a limited value (6) around $b$, $g(x)$ doesn’t need to be so. For example, $g(x)$ may never be larger than $b$. But every time we get a $g(x)$ that meets the condition $g(x)  b < \delta’$, $f(g(x))  f(b) < \varepsilon$ is guaranteed.
Because
$$\lim\limits_{x \to \infty}g(x) = b$$
according to the definition of limit, $\forall \varepsilon > 0$, there exists a $\delta$ such that for all $x > \delta$ we have $g(x) b < \varepsilon$
Let $\varepsilon = \delta’$, so $\forall x>\delta$, we have
$$g(x)  b < \delta’$$
Combine this with $(6)$, $\forall \varepsilon’ > 0$, there exists $\delta$, whenever $x > \delta$, we have
$$f(g(x))  f(b) < \varepsilon’$$
Which is exactly the definition of the limit
$$\lim\limits_{x \to \infty}f(g(x)) = f(b)$$
So we proved the left side of $(1)$ equation. So equation
$$\lim\limits_{x \to \infty}f(g(x)) = f(b) = f(\lim\limits_{x\to \infty}g(x))$$
holds.
]]>So how to calculate it? The first thought that came to my mind was that
$$\lim\limits_{n\to\infty}(1 + \frac1 n)^n = e \tag 1$$
So replace $n$ with $n$, I got
$$\lim\limits_{n\to\infty}(1  \frac1 n)^n = \frac1 e \tag 2$$
Then I have no clue about what to do next, I’m not even sure whether (2) is right or not. So I started digging from the calculation of $\lim\limits_{n\to\infty}(1 + \frac1 n)^n$.
Here is how I solve the problem.
Let $t$ be any number in the interval $[1\frac{\lambda_n}n, 1]$, then we get
$$1\frac{\lambda_n} n\leq t\leq1$$
Therefore
$$\frac 1{1\frac{\lambda_n} n} \leq \frac 1 t \leq 1$$
Therefore
$$\int_{1\frac{\lambda_n}n}^1\frac 1{1\frac{\lambda_n} n}dt \leq \int_{1\frac{\lambda_n}n}^1\frac 1 t dt\leq \int_{1\frac{\lambda_n}n}^1 1dt$$
The first integral equals $\frac{\lambda_n}n$, the second integral equals $ln(1\frac{\lambda_n} n)^{1}$, the third integral equals $\frac{\lambda_n}{n\lambda_n}$, so we get
$$\frac{\lambda_n}n\leq ln(1\frac{\lambda_n} n)^{1} \leq \frac{\lambda_n}{n\lambda_n}$$
Exponentiating, we find that
$$e^{\frac{\lambda_n} n}\leq(1\frac{\lambda_n}n)^{1}\leq e^{\frac{\lambda_n}{n\lambda_n}}$$
Taking the $(n)^{st}$ power of the left inequality gives us
$$e^{{\lambda_n}}\geq (1\frac{\lambda_n} n)^n\tag{3}$$
Taking the $(\lambda_n  n)^{th}$ power of the right inequality gives us
$$(1\frac{\lambda_n} n)^{(n\lambda_n)}\geq e^{\lambda_n}$$
Why was $\geq$ replaced with $\leq$? Because $\lambda_n = np_n, n\geq 0, 0\leq p_n\leq 1$($p_n$ denotes the probability), so $\lambda_nn = np_n  n = n(p_n  1)\leq 0$, the power is less or equal to 0, so we need change the direction of the sign.
Multiply each side of the inequality by $(1\frac{\lambda_n} n)^{\lambda_n}$, we get
$$(1\frac{\lambda_n} n)^n\geq {e^{\lambda_n}} {(1\frac{\lambda_n} n)^{\lambda_n}}\tag 4$$
Combine (3) and (4), we get
$$e^{\lambda_n}(1\frac{\lambda_n} n)^{\lambda_n}\leq (1\frac{\lambda_n} n)^n \leq e^{\lambda_n}$$
According to this theorem, because $1  \frac{\lambda_n} n > 0, \lambda_n > 0, \lim\limits_{n\to\infty}\lambda_n = \lambda$, we have
$\lim\limits_{n \to \infty}(1\frac{\lambda_n} n)^{\lambda_n} = [\lim\limits_{n \to \infty}(1\frac{\lambda_n} n)]^{\lim\limits_{n\to\infty}\lambda_n}$
$ = \lim\limits_{n\to\infty}(1\lambda_n\cdot\frac 1 n)^\lambda$
$ = (\lim\limits_{n\to\infty}1  \lim\limits_{n\to\infty}\lambda_n\cdot\lim\limits_{n\to\infty}\frac 1 n)^\lambda$
$ = (1 \lambda\cdot0)^\lambda = 1$
So
$$\lim\limits_{n\to\infty}e^{\lambda_n}(1\frac{\lambda_n} n)^{\lambda_n} = e^{\lambda}$$
$$\lim\limits_{n\to\infty}e^{\lambda_n} = e^{\lambda}$$
According to squeeze theorem, we get
$$\lim\limits_{n\to\infty}(1\frac{\lambda_n} n)^n = e^{\lambda}$$
Which is the answer.
Hexo is an excellent static blog generator, I read its source code recently, and I think it’s worth sharing the inner mechanism of its source code.
When you run the command hexo generate
, hexo will generate all the static files for you. This is the part we are going to start with. The directory where hexo generate
is executed is /home/searene/Development/hexotwentysixteen
in this tutorial.
First, we can find the location of the tool hexo
with the command which
.
1  which hexo 
My output is
1  /home/searene/.nvm/versions/node/v5.0.0/bin/hexo 
This is a soft link, we get the location of the original file with ll
1  ll ~/.nvm/versions/node/v5.0.0/bin/hexo 
The contents of hexo
are as follows.
1 

It requires a js file called hexo
, which is located in /home/searene/.nvm/versions/node/v5.0.0/lib/node_modules/hexocli/lib/hexo.js
in my case. The beginning part of the file is as follows.
1  ; 
It requires several packages.
chalk
is used for colorful outputs,.tildify
is used to convert an absolute path to a tilde path:, like /Users/sindresorhus/dev
→ ~/dev
.context
is used to //TODOfind_pkg
is used to find the local hexo directory that contains node_modules
goodbye
is used to generate a random goodbye sentence.minimist
is used to parse argument options.camelCaseKeys
is used to convert keys in parameters to the camelCased onesLet’s continue to read the file.
1  function entry(cwd, args) { 
Notice the last part
1  module.exports = entry; 
Remember the contents of hexo.js
?
1  require('../lib/hexo')(); 
So what hexo.js
does is calling the entry
function. Here comes the question, what does entry
do?
It searched upwards from the working directory looking for package.json
containing the key hexo
.
1  function findPkg(cwd, args) { 
Then it loads the local hexo package.
1  function loadModule(path, args) { 
new
a Hexo
object. The souce code of Hexo
is as follows:
1  function Hexo(base, args) { 
Hexo
gets several directories such as public_dir
, source_dir
, etc. Then it defines the this.extend
object, which contains console
, deployer
, etc. The format of each instance in the this.extend
object is as follows:
1  function Console() { 
All of them contain the same object this.store
, which is used to map the name to the corresponding function. For example, this.store
in Console
is as follows:
Each key in the object such as clean
, config
is of type string. What they are mapped to are functions that implement them.
Then it creates several instances, logger
, Render
, Router
, Post
, Scaffold
, database
etc. logger
is used to log information on the console and the file, Render
is used to render files(e.g. render markdownf files to html), Router
is used to save all paths used in the site, Post
is used to //TODO, Scaffold
is used to //TODO, database
is a JSONbased database.
It then registered following schemas using registerModels(this)
.
1  exports.Asset = require('./asset'); 
Afterwards, two instances are initiated, Source
, Theme
,which represents source
and theme
folders respectively. They are both being processed by Box
.
First, let’s look at source
.js.
1  ; 
ctx
refers to Hexo
, Source
function calls Box
and gets the processor list, then it inherits Box
. Box
is used to read and render files in source
or theme
folder. To find out what’s going on, we need to look into the source code of Box
.
1  function Box(ctx, base, options) { 
It sets several variables, then it gets the Cache
model. The source code of ctx.model
function is as follows.
1  Hexo.prototype.model = function(name, schema) { 
If the model was created before, this.database.model
will just return the model, or it will create the model with the specified name
and schema
.
1  Database.prototype.model = function(name, schema) { 
Note that We have created the model in the register_model
function, which is located in the Hexo
function. When the code new Hexo
is run, all the models are registered.
1  ; 
The models created here were as follows.
1  ; 
Which includes cache
. So we can get the created cache
model with this.Cache = ctx.model('Cache');
. This model is used to cache generated posts and stuff, and store a hashed value for all of them. If the hash value is identical, hexo will not generate the post again, which reduces the generation time to a degree.
Now we only have a line left in the box
function.
1  this.File = this._createFileClass(); 
this.File
is used to read file contents and render it. The source code of _createFileClass()
function is as follows.
1  Box.prototype._createFileClass = function() { 
File.call(this, data)
sets _File
‘s source
, path
, params
and type
as the same as ones in data
. You can see it in the source of the File
constructor.
1  function File(data) { 
_File
inherits File
afterwards. Then it sets render
and renderSync
function of _File
and returns it. As you can tell from their names, they are used to render files or strings, like this:
1  hexo.render.render({text: 'example', engine: 'swig'}).then(function(result){ 
1  hexo.render.render({path: 'path/to/file.swig'}).then(function(result){ 
Let’s look into the Render
object.
1  function Render(ctx) { 
Still remember renderer
? It’s used to store all the information about rendering.
1  function Renderer() { 
The most important function in render.js
is Render.prototype.render
, the function is used to render text or files, the source code of it is as follows.
1  Render.prototype.render = function(data, options, callback) { 
First, it checks if data
exists or not, data
contains text(data.text
) or file(data.path
) that is going to be rendered, it throws an error if it doesn’t exist.
1  if (!data) return reject(new TypeError('No input file or string!')); 
Then if data.text
exists, it will try to render the text first.
1  if (data.text != null) return resolve(data.text); 
If data.path
exists, it will try to analyze the file specified by data.path
.
1  if (!data.path) return reject(new TypeError('No input file or string!')); 
It tries to find out if the rendering engine exists in renderer.store
, which maps the rendering engine’s name to the corresponding rendering function. If the engine exists, it will call the corresponding function to render it, return the original text if the engine doesn’t exist.
1  }).then(function(text) { 
renderer
refers to the function that is used to render text or files. What renderer.call()
returns is usually of JSON format. For example, if the file to be rendered is like this:
1  archive_dir: archives 
The rendered result will be an object like this:
1  {archive_dir: "archives", author: "John Doe"} 
Some files are not rendered in this way, e.g. md
. The rendering results of markdown files are of type string. Hexo
creates a toString
function to make the conversion happen.
1  result = toString(result, data); 
The source code of toString
function is as follows.
1  function toString(result, options) { 
Because md
files’s rendering results are of type string. so toString
returns the original result directly in this case. Sometimes it needs to be further processed.
Afterwards, onRenderEnd
is followed in order to modify some contents of result
after rendering.
1  if (data.onRenderEnd) { 
Then the result is transferred to the next then
function, and the after_render
filter is executed.
1  }).then(function(result) { 
To make it even clearer about how to use execFilter
, Here I give an example from the official Hexo website, the following code is used to uglify js files.
1  var UglifyJS = require('uglifyjs'); 
This is the source code of register
function.
1  Filter.prototype.register = function(type, fn, priority) { 
As you can see, it stores type
(e.g. after_post_render:js
) and the corresponding processing function in the this.store
object. After the registration is over, Filter.prototype.exec
executes the specified filter (after_post_render:js
in this case).
1  Filter.prototype.exec = function(type, data, options) { 
OK, this part is over, let’s look into the theme/index.js
file next.
1  ; 
The function Theme
also calls Box()
, then it adds several processors and sets languages and views.
Then it bind locals.
1  Hexo.prototype._bindLocals = function() { 
After loading module is over, it calls console
to execute the provided command
1  return loadModule(path, args).catch(function() { 
Let’s look through the source code of ./console
.
1  ; 
It registers several commands using console.register
, let’s look through its source code.
1  Console.prototype.register = function(name, desc, options, fn) { 
大体扫了一下频道视频列表，主要应该是以科普为主，不过都是一些比较有趣的话题。可以没事看看。
频道地址：https://www.youtube.com/DNews/featured
频道截图：
]]>