May 09, 2015
On 05/09/2015 10:45 AM, Russel Winder via Digitalmars-d-learn wrote:
> On Sat, 2015-05-09 at 09:49 -0700, Ali Çehreli via Digitalmars-d-learn wrote:
>>
> […]
>> BigInt factorial(size_t n)
>> {
>>       return bigInts(1).take(n).reduce!((a, b) => a *= b);
>> }
>
> I wonder if that should be a * b rather than a *= b?

Yes. :) Luckily, the difference is an unused side-effect to parameter 'a' in my wrong version.

Ali

May 09, 2015
On 05/09/2015 05:52 PM, Dennis Ritchie wrote:
> On Saturday, 9 May 2015 at 14:15:21 UTC, Ali Çehreli wrote:
>> On 05/09/2015 04:59 AM, Dennis Ritchie wrote:
>>> On Saturday, 9 May 2015 at 11:49:48 UTC, Timon Gehr wrote:
>>>> assert((function int(int
>>>> x)=>x?x*__traits(parent,{})(x-1):1)(10)==3628800);
>>>
>>> Thanks. Yes, it is similar to what I wanted :)
>>
>> Also interesting:
>>
>>   http://rosettacode.org/wiki/Y_combinator#D
>>
>> I think that code was improved by Timon Gehr as well.
>>
>> Ali
>
> Yes, it's much better.

Well, it is much slower due to all the allocated closures, owed to the fact that the implementations of 'fix' on that page are expected to mirror a particular famous implementation in untyped lambda calculus.

In case you have a use for 'fix', a more efficient implementation might be:

auto fix(S,T...)(S delegate(T) delegate (S delegate(T)) f){
    S delegate(T) g=(T a){ assert(0,"f is too eager."); };
    return g=f((T a)=>g(a));
}

(In particular, this will only allocate two closures for the plumbing instead of a number of them linear in the number of recursive invocations.)


> Even something like Common Lisp.

(Be aware that Common Lisp implementations typically have better garbage collectors than what is available for D.)
May 09, 2015
On Saturday, 9 May 2015 at 21:48:05 UTC, Timon Gehr wrote:
> Well, it is much slower due to all the allocated closures, owed to the fact that the implementations of 'fix' on that page are expected to mirror a particular famous implementation in untyped lambda calculus.
>
> In case you have a use for 'fix', a more efficient implementation might be:
>
> auto fix(S,T...)(S delegate(T) delegate (S delegate(T)) f){
>     S delegate(T) g=(T a){ assert(0,"f is too eager."); };
>     return g=f((T a)=>g(a));
> }
>
> (In particular, this will only allocate two closures for the plumbing instead of a number of them linear in the number of recursive invocations.)
>
>
>> Even something like Common Lisp.
>
> (Be aware that Common Lisp implementations typically have better garbage collectors than what is available for D.)

Maybe in the future, that D will be added to optimize tail recursion delegates?
And why garbage collectors in Lisp is better?
1 2
Next ›   Last »