From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Michael Heerdegen Newsgroups: gmane.emacs.devel Subject: Re: A generalization of `thunk-let' Date: Tue, 12 Dec 2017 15:41:47 +0100 Message-ID: <87r2s0nh3o.fsf@web.de> References: <87infp9z6j.fsf@web.de> <87r2s5ez0t.fsf@web.de> <87374kfaw9.fsf@web.de> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1513089730 24718 195.159.176.226 (12 Dec 2017 14:42:10 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 12 Dec 2017 14:42:10 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Dec 12 15:42:03 2017 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eOlkw-00064O-FK for ged-emacs-devel@m.gmane.org; Tue, 12 Dec 2017 15:42:02 +0100 Original-Received: from localhost ([::1]:58784 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eOll3-0004Ev-N5 for ged-emacs-devel@m.gmane.org; Tue, 12 Dec 2017 09:42:09 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:52509) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eOlkv-0004EY-JH for emacs-devel@gnu.org; Tue, 12 Dec 2017 09:42:02 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eOlkr-0005RI-J1 for emacs-devel@gnu.org; Tue, 12 Dec 2017 09:42:01 -0500 Original-Received: from mout.web.de ([212.227.15.14]:61740) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eOlkr-0005QW-7t for emacs-devel@gnu.org; Tue, 12 Dec 2017 09:41:57 -0500 Original-Received: from drachen.dragon ([92.74.165.17]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0M9MDO-1eC4xe3euM-00Cgba; Tue, 12 Dec 2017 15:41:49 +0100 In-Reply-To: (Stefan Monnier's message of "Sat, 09 Dec 2017 23:47:18 -0500") X-Provags-ID: V03:K0:+2O/esCa7aZXA+u1ISZW5QSjbXPW7EX9Yv6XPSucqIiXGyirfCS UFD9XCaL/3JY0BXUmGYAjNbrIU5wHfujmpV/FmEi3mDxc74gZLvZBBjvsYUcsIGqJZ86pwv uC491j1Of7dKSIusLM8DNUe+IdEVJhcgMh0tdyV8keLNpjStNWSSXAhCShZin6UR2X7d96R W/J2G4YXzET7gNOWgE5dA== X-UI-Out-Filterresults: notjunk:1;V01:K0:DBetgdkpt4k=:rCHW8LTATqgW5Q1XqA6gby 4/CbPeOXtAEiRnYXsSd5jGEty6g4F1u0vBHyGNnTvS5nNcDsB4J/VoPccTu3Q4r4DGwSBfPf5 BM1a+Ptl+dbxvs0Ftg1lrMVHm2SatvuFTWiTJLd+46MgCjL8BfFqdMZDntkI5WXUDwIa/BgkS FPMMxC+WUyhZ+g6sV5p6DmrlVZwDItz3iCV+l4WvgiULwQJfNpOESQ11CJ7/EM8931vgxGMqI EOJu/435h3tUnVVrP/C3ufa+LiggM/asgj2bzVN+6fpF5zQeUu2X97lO/dZxYXQTeHVenabYP 3rxxb0OiAhcvdG+PFy3tubQ4egCNGtw5LgejBKs6NW3bCC7aNiXyHW7zIjdHo/dbGbGYz3U1z Wm9POFeheEJuMNb03rbbYj+rHc7QFkGgV4BeK6rFw+mbDITvO2MxKWotf3OicPT3uGOt6Sroa bSNYK5tGtNDHnJvWmprjyvJqpsK6mLKIeZRstB96eG/R0lAGsU7olJ7JltgWYD4LljL1ujU5V tvsk+shz/kXvXZusmZWTLQX5M9fafbtTeQllySY0rAfU6WhkySCYYmMqvSrEhsYu++P9QrEC4 TrxpjXLceVxT1vOLH76g+JnqvarJFhjN74GGK9dCItTfa2zrfJHsS1FCKqL0jBxNrJ5cStZ2G Im23GdgzJqQRCKf12KUkdMFWfXenpM0gVGrGOahRn8SlIdFyVtnHUv17tnqUNzCszwZMH7bJK t/uhTjz+lyC53nSDu9HDBpvEIqizHfDT8S3tCzfx9uN+JjYvR1Zo9gapowIs6RukLq7NlBKD X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.14 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:220925 Archived-At: --=-=-= Content-Type: text/plain Stefan Monnier writes: > There wasn't enough space in the margin for it, sorry, Very funny, ehm - here is a proof of concept. It is not exactly what you suggested: you have to declare dependencies explicitly (I think this would even make code better readable). But dependencies do not need to be sscells - I made it so that dependencies can be arbitrary expressions (this includes variables as major case), and an equivalence predicate for testing can be optionally specified, defaulting to #'eq. You can make an sscell B depend on the value of sscell A by making B depend on the expression (sscell-get A). These sscell objects are a generalization of thunks as in thunk.el, and sscell-let is a generalization of thunk-let. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=sscell.el Content-Transfer-Encoding: quoted-printable ;;; sscell.el --- Attach notes to messages -*- lexical-binding: t -*- ;; Copyright (C) 2017 Free Software Foundation, Inc ;; Author: Michael Heerdegen ;; Maintainer: Michael Heerdegen ;; Created: 2017_12_11 ;; Keywords: lisp ;; Version: 0.1 ;; Package-Requires: () (defvar sscell--tag (make-symbol "sscell")) (defun sscell-p (object) (eq (car-safe object) sscell--tag)) (defmacro sscell-make (deps &rest body) "Make an sscell. DEPS is a list of the dependencies of the sscell. A dependency is either: EXPR or (:test TESTFUN EXPR) The return value is an sscell object..." (cl-callf or deps '(t)) (let ((last-result (make-symbol "last-result")) (last-dep-results (make-symbol "last-dep-results")) (new-dep-results (make-symbol "new-dep-results")) (get-deps (make-symbol "get-deps")) (instruction (make-symbol "instruction")) (test-validity-p (make-symbol "test-validity-p")) (old (make-symbol "old")) (new (make-symbol "new")) (tests (cl-maplist (lambda (more-deps) (let ((dep (car more-deps))) (if (not (eq (car-safe dep) :test)) '#'eq (prog1 (nth 1 dep) (setcar more-deps (nth 2 dep)))))) deps))) `(let* (,last-result (,last-dep-results nil) (,get-deps (lambda () (list ,@deps))) (,test-validity-p (lambda (,old ,new) (and ,last-dep-results (cl-every #'identity (cl-mapcar #'funcall (list ,= @tests) ,old ,new)))))) (cons sscell--tag (lambda (,instruction) (pcase ,instruction ('test (and ,last-dep-results (funcall ,test-validity-p ,last-dep-results (f= uncall ,get-deps)))) ('get (let ((,new-dep-results (funcall ,get-deps))) (if (funcall ,test-validity-p ,last-dep-results ,n= ew-dep-results) ,last-result (setq ,last-dep-results ,new-dep-results ,last-result (progn ,@body))))))))))) (defun sscell-get (sscell) (cl-assert (sscell-p sscell)) (funcall (cdr sscell) 'get)) (defun sscell-valid-p (sscell) (cl-assert (sscell-p sscell)) (funcall (cdr sscell) 'test)) (defmacro sscell-let (bindings &rest body) (declare (indent 1) (debug fixme)) (cl-callf2 mapcar (pcase-lambda (`(,var ,deps ,binding)) (list (make-symbol (concat (symbol-name var) "-sscell")) var deps binding)) bindings) `(let ,(mapcar (pcase-lambda (`(,helper-var ,_var ,deps ,binding)) `(,helper-var (sscell-make ,deps ,binding))) bindings) (cl-symbol-macrolet ,(mapcar (pcase-lambda (`(,helper-var ,var ,_deps ,_binding)) `(,var (sscell-get ,helper-var))) bindings) ,@body))) (defmacro sscell-let* (bindings &rest body) (declare (indent 1) (debug fixme)) (cl-reduce (lambda (expr binding) `(sscell-let (,binding) ,expr)) (nreverse bindings) :initial-value (macroexp-progn body))) --=-=-= Content-Type: text/plain Regards, Michael. --=-=-=--