Explain this implementation of the Y combinator in Scala?
<p>This is a implementation of the Y-combinator in Scala:</p>

<pre><code>scala&gt; def Y[T](func: (T =&gt; T) =&gt; (T =&gt; T)): (T =&gt; T) = func(Y(func))(_:T)
Y: [T](func: (T =&gt; T) =&gt; (T =&gt; T))T =&gt; T

scala&gt; def fact = Y {
     |           f: (Int =&gt; Int) =&gt;
     |             n: Int =&gt;
     |               if(n &lt;= 0) 1
     |               else n * f(n - 1)}
fact: Int =&gt; Int

scala&gt; println(fact(5))
120
</code></pre>

<p>Q1: How does the result <code>120</code> come out, step by step? Because the <code>Y(func)</code> is defined as <code>func(Y(func))</code>, the Y should become more and more,Where is the Y gone lost and how is the <code>120</code> come out in the peform process?</p>

<p>Q2: What is the difference between</p>

<pre><code>def Y[T](func: (T =&gt; T) =&gt; (T =&gt; T)): (T =&gt; T) = func(Y(func))(_:T)
</code></pre>

<p>and</p>

<pre><code>def Y[T](func: (T =&gt; T) =&gt; (T =&gt; T)): (T =&gt; T) = func(Y(func))
</code></pre>

<p>They are the same type in the scala REPL, but the second one can not print the result <code>120</code>?</p>

<pre><code>scala&gt; def Y[T](func: (T =&gt; T) =&gt; (T =&gt; T)): (T =&gt; T) = func(Y(func))
Y: [T](func: (T =&gt; T) =&gt; (T =&gt; T))T =&gt; T

scala&gt; def fact = Y {
     |           f: (Int =&gt; Int) =&gt;
     |             n: Int =&gt;
     |               if(n &lt;= 0) 1
     |               else n * f(n - 1)}
fact: Int =&gt; Int

scala&gt; println(fact(5))
java.lang.StackOverflowError
  at .Y(&lt;console&gt;:11)
  at .Y(&lt;console&gt;:11)
  at .Y(&lt;console&gt;:11)
  at .Y(&lt;console&gt;:11)
  at .Y(&lt;console&gt;:11)
</code></pre>