From 6a7670f4c31707706f81542476320165d20371cd Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Wed, 22 Jun 2016 18:43:09 -0700 Subject: [PATCH] Use help-function-arglist in imalison:compose This allows use to automatically detect the signature of a function/macro and take arguments accordingly in the composition. --- dotfiles/emacs.d/README.org | 49 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/dotfiles/emacs.d/README.org b/dotfiles/emacs.d/README.org index f03a4f53..86e006b6 100644 --- a/dotfiles/emacs.d/README.org +++ b/dotfiles/emacs.d/README.org @@ -5,6 +5,7 @@ This README is a literate commentary on my emacs configuration, but it also serv This makes it so that the file that is produced from tangling this file uses lexical scoping #+BEGIN_SRC emacs-lisp ;;; -*- lexical-binding: t -*- +(setq lexical-binding t) #+END_SRC ** User Info #+BEGIN_SRC emacs-lisp @@ -19,6 +20,7 @@ This makes it so that the file that is produced from tangling this file uses lex This is here because it needs to be activated as early as possible #+BEGIN_SRC emacs-lisp (use-package auto-compile + :ensure t :config (progn (auto-compile-on-load-mode) @@ -389,17 +391,17 @@ The packages in this section provide no functionality on their own, but provide thing (list thing))) - (defmacro imalison:compose (&rest funcs) + (defmacro imalison:compose-with-apply (&rest funcs) "Build a new function with NAME that is the composition of FUNCS." `(lambda (&rest args) - (imalison:compose-helper ,funcs))) + (imalison:compose-with-apply-helper ,funcs))) - (defmacro imalison:compose-helper (funcs) + (defmacro imalison:compose-with-apply-helper (funcs) "Builds funcalls of FUNCS applied to the arg." (if (equal (length funcs) 0) (quote args) `(apply ,(car funcs) - (imalison:make-list (imalison:compose-helper ,(cdr funcs)))))) + (imalison:make-list (imalison:compose-with-apply-helper ,(cdr funcs)))))) #+END_SRC **** Simpler Unary version #+BEGIN_SRC emacs-lisp @@ -416,25 +418,35 @@ The packages in this section provide no functionality on their own, but provide #+END_SRC **** A Version Supporting Macros #+BEGIN_SRC emacs-lisp - (defmacro imalison:compose-2 (arguments &rest funcs) - (when (numberp arguments) - (setq arguments - (cl-loop for i from 97 to (+ arguments 96) - collect (intern (char-to-string i))))) - `(imalison:compose-2-argspec ,arguments ,arguments ,@funcs)) + (defun imalison:args-expander (function-name) + (lambda (args) + (apply function-name args))) - (defmacro imalison:compose-2-argspec + (defmacro imalison:compose (&rest funcs) + (let* ((last-function (car (last funcs))) + (arguments (help-function-arglist last-function)) + (call-arguments (delq '&optional arguments))) + (when (memq '&rest arguments) + (setq arguments '(&rest args)) + (setq call-arguments '(args)) + (setq funcs + (-replace-at (- (length arguments) 1) + (imalison:args-expander last-function) + funcs))) + `(imalison:compose-argspec ,arguments ,call-arguments ,@funcs))) + + (defmacro imalison:compose-argspec (arguments call-arguments &rest funcs) "Build a new function with NAME that is the composition of FUNCS." `(lambda ,arguments - (imalison:compose-2-helper ,funcs ,call-arguments))) + (imalison:compose-helper ,funcs ,call-arguments))) - (defmacro imalison:compose-2-helper (funcs arguments) + (defmacro imalison:compose-helper (funcs arguments) "Builds funcalls of FUNCS applied to the arg." (if (equal (length funcs) 1) `(,(car funcs) ,@arguments) `(,(car funcs) - (imalison:compose-2-helper ,(cdr funcs) ,arguments)))) + (imalison:compose-helper ,(cdr funcs) ,arguments)))) #+END_SRC *** Prefix Alternatives Prefix alternatives is a macro that builds a function that selects one of a collection of functions that are provided to the macro based on the value of the prefix argument. @@ -492,7 +504,7 @@ imalison:named-build is a way to invoke a macro in such a way that the lambda th For composing functions with an apply so that they can be used with the ~:around~ keyword of advice-add #+BEGIN_SRC emacs-lisp (defmacro imalison:advice-add-around-builder (&rest functions) - `(imalison:compose-2-argspec + `(imalison:compose-argspec (function &rest args) (function args) ,@functions apply)) #+END_SRC **** Kill New @@ -642,7 +654,7 @@ Get route information #+BEGIN_SRC emacs-lisp (defun imalison:muni-get-route-ids (route-name &optional direction) (delete-dups - (mapcar (imalison:compose-2 1 intern car) + (mapcar (imalison:compose intern car) (s-match-strings-all "^\\([[:digit:]]\\{1,10\\}\\)" (shell-command-to-string @@ -784,13 +796,12 @@ A macro for composing functions together to build an interactive command to copy (defmacro imalison:compose-copy-builder (name &rest funcs) `(imalison:named-build ,name imalison:make-interactive - (imalison:compose-2 0 kill-new ,@funcs))) + (imalison:compose kill-new ,@funcs))) #+END_SRC - *** Copy portions of the buffer file name #+BEGIN_SRC emacs-lisp (defmacro imalison:copy-buffer-file-path-builder (&rest args) - `(imalison:compose-copy-builder ,@args 'buffer-file-name)) + `(imalison:compose-copy-builder ,@args buffer-file-name)) (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path-full) (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-name