Kaz Kylheku
4/10/2015 5:29:00 AM
On 2015-04-09, Paul Rubin <no.email@nospam.invalid> wrote:
> Kaz Kylheku <kaz@kylheku.com> writes:
>> (do ((sum 0 (+ sum (if (even? b) b 0)))
>> (a 0 b)
>> (b 1 (+ a b)))
>> ((>= b limit) sum))
>>
>> The "what can you do me for" way, rather than the silly "curse again, and
>> again" way.
>
> I'd be interested in seeing an SRFI-45 or force/delay version that
> separates generating the unbounded Fibonacci sequence, chopping it at
> 1000000, filtering to the evens, and adding up the truncating stream.
> The Haskell equivalent is very natural:
>
> fibs a b = a : fibs b (a+b)
> main = print . sum . filter even . takeWhile (< 1000000) $ fibs 0 1
>
> *Main> main
> 1089154
That code has just given me a realization: I am missing a "lcons" macro
wrapper around the make-lazy-cons constructor in TXR Lisp:
With that, I can just use (lcons x y) to do the rough equivalent of Haskell's
lazy x : y, thereby expressing the fib in essentially the same way:
Code:
@(do
(defmacro lcons (car-form cdr-form)
(let ((lc (gensym)))
^(make-lazy-cons (lambda (,lc)
(rplaca ,lc ,car-form)
(rplacd ,lc ,cdr-form)))))
(defun fib2 (a b)
(lcons a (fib2 b (+ a b))))
(prinl [reduce-left + [keep-if evenp (first (partition-by (op < 1000000) (fib2 0 1)))]]))
Run:
$ txr fib2.txr
1089154
I don't have takeWhile, but partition-by for lazily partitioning a list will
do the job, followed by taking the first partition.
The last expr rewritten using a pipeline of partial application operations:
[(opip (partition-by (op < 1000000)) first (keep-if evenp) (reduce-left +) prinl)
(fib2 0 1)]
This lcons macro is definitely going into the language.