From ed2e44722b41b635699dd4745c4de37042e55d29 Mon Sep 17 00:00:00 2001 From: Magnar Sveen Date: Fri, 28 Sep 2012 10:37:41 +0200 Subject: [PATCH] !reduce macro --- bang.el | 28 ++++++++++++++++++++++------ tests.el | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/bang.el b/bang.el index 46689e4..a410bb6 100644 --- a/bang.el +++ b/bang.el @@ -27,11 +27,6 @@ (eval-when-compile (require 'cl)) -(defvar !compare-fn nil - "Tests for equality use this function or `equal' if this is nil. -It should only be set using dynamic scope with a let, like: -(let ((!compare-fn =)) (!union numbers1 numbers2 numbers3)") - (defmacro !filter (form-or-fn list) `(let ((!--list ,list) (!--result '())) @@ -47,11 +42,27 @@ It should only be set using dynamic scope with a let, like: `(mapcar #',form-or-fn ,list) `(mapcar #'(lambda (it) ,form-or-fn) ,list))) +(defmacro !reduce-from (form-or-fn initial-value list) + `(let ((!--list ,list) + (!--acc ,initial-value)) + (while !--list + (let ((it (car !--list)) + (acc !--acc)) + (setq !--acc ,(if (functionp form-or-fn) (list form-or-fn 'acc 'it) (list 'progn form-or-fn))) + (setq !--list (cdr !--list)))) + !--acc)) + +(defmacro !reduce (form-or-fn list) + (if (eval list) + `(!reduce-from ,form-or-fn ,(car (eval list)) ',(cdr (eval list))) + (if (functionp form-or-fn) + (list form-or-fn) + `(let (acc it) ,form-or-fn)))) (defun !concat (list) (apply 'concatenate 'list list)) -(defalias '!select 'remove-if-not) +(defalias '!select '!filter) (defalias '!reject 'remove-if) (defalias '!partial 'apply-partially) @@ -92,5 +103,10 @@ or with `!compare-fn' if that's non-nil." (setq lst (cdr lst))) lst)))) +(defvar !compare-fn nil + "Tests for equality use this function or `equal' if this is nil. +It should only be set using dynamic scope with a let, like: +(let ((!compare-fn =)) (!union numbers1 numbers2 numbers3)") + (provide 'bang) ;;; bang.el ends here diff --git a/tests.el b/tests.el index 9600cb6..367ebeb 100644 --- a/tests.el +++ b/tests.el @@ -16,6 +16,20 @@ (should (equal (!map (* it it) '(1 2 3 4)) '(1 4 9 16))) (should (equal (!map square '(1 2 3 4)) '(1 4 9 16)))) +(ert-deftest reduce () + "`!reduce' takes a list and applies the function over them to create one result" + (should (equal (!reduce + '()) 0)) + (should (equal (!reduce + '(1)) 1)) + (should (equal (!reduce + '(1 2)) 3)) + (should (equal (!reduce-from + 7 '()) 7)) + (should (equal (!reduce-from + 7 '(1)) 8)) + (should (equal (!reduce-from + 7 '(1 2)) 10)) + + (should (equal (!reduce (lambda (memo item) (format "%s-%s" memo item)) '(1 2 3)) "1-2-3")) + (should (equal (!reduce (format "%s-%s" acc it) '(1 2 3)) "1-2-3")) + (should (equal (!reduce (format "%s-%s" acc it) '()) "nil-nil")) +) + (ert-deftest difference () "`!difference' returns a new list of only elements in list1 that are not in list2." (should (equal (!difference '() '()) '()))