help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [External] : Re: Advantage using mapc over dolist


From: Tomas Hlavaty
Subject: RE: [External] : Re: Advantage using mapc over dolist
Date: Mon, 02 Dec 2024 22:58:30 +0100

On Mon 02 Dec 2024 at 21:15, Drew Adams <drew.adams@oracle.com> wrote:
> OOTB Lisp isn't really made for such streaming-style programming.

Lisp is great for streaming-style programming:

;; -*- lexical-binding: t -*-

(defun stream (x)
  (cl-etypecase x
    (list
     (lambda ()
       (pop x)))
    (array
     (let ((n (length x))
           (i 0))
       (lambda ()
         (when (< i n)
           (prog1 (aref x i)
             (setq i (1+ i)))))))))

(defun collect (stream)
  (cl-loop
   with x
   while (setq x (funcall stream))
   collect x))

(collect (stream '(1 2 3 4))
(collect (stream [1 2 3 4]))

(defun random-stream (&optional limit)
  (lambda ()
    (random limit)))

(defun head-stream (stream n)
  (lambda ()
    (when (<= 0 (setq n (1- n)))
      (let ((z (funcall stream)))
        (unless z
          (setq n 0))
        z))))

(collect (head-stream (stream '(1 2 3 4)) 3))
(collect (head-stream (stream '(1 2)) 3))
(collect (head-stream (random-stream 6) 10))

(defun map-stream (stream fn)
  (lambda ()
    (let ((x (funcall stream)))
      (when x
        (funcall fn x)))))

(collect (map-stream (head-stream (random-stream 6) 10) #'1+))

(defun message-stream (stream)
  (lambda ()
    (let ((x (funcall stream)))
      (message "%s" (prin1-to-string x))
      x)))

(defun sleep-stream (stream seconds)
  (lambda ()
    (let ((z (funcall stream)))
      (when z
        (sleep-for seconds)
        z))))

(collect (sleep-stream (message-stream (head-stream (random-stream 6) 10)) 1))

(defun fibonacci-stream ()
  (let ((a 0)
        (b 1))
    (lambda ()
      (cl-shiftf a b (+ a b)))))

(collect (head-stream (fibonacci-stream) 10))

Now lots of things can be such a stream.

(defun deadline-stream (stream deadline)
  (lambda ()
    ;; what is the Emacs replacement for get-universal-time?
    (if (< (get-universal-time) deadline)
        (funcall stream)
        (error "deadline ~s reached" deadline))))

Imagine a web application.  It can be seen as such a stream where users
funcall the stream with their clicks and keystrokes.  A widget is also
just another stream and can also contain other widgets which are also
just another stream.

The nice thing about these streams is how declaratively their
definitions feel.  Almost like a declarative reactive dataflow
synchronous language.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]