From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Marcin Borkowski Newsgroups: gmane.emacs.help Subject: Re: How to mapcar or across a list? Date: Wed, 15 Jul 2015 23:02:01 +0200 Message-ID: <87d1ztm8xi.fsf@mbork.pl> References: <871tg9m9os.fsf@kuiper.lan.informatimago.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1436994173 16115 80.91.229.3 (15 Jul 2015 21:02:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 15 Jul 2015 21:02:53 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Wed Jul 15 23:02:43 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZFTpD-0004CF-4R for geh-help-gnu-emacs@m.gmane.org; Wed, 15 Jul 2015 23:02:43 +0200 Original-Received: from localhost ([::1]:37492 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFTpB-0001YR-KD for geh-help-gnu-emacs@m.gmane.org; Wed, 15 Jul 2015 17:02:41 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:45010) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFToz-0001Y8-Rx for help-gnu-emacs@gnu.org; Wed, 15 Jul 2015 17:02:31 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZFTov-0008FG-DM for help-gnu-emacs@gnu.org; Wed, 15 Jul 2015 17:02:29 -0400 Original-Received: from mail.mojserwer.eu ([195.110.48.8]:51580) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFTov-0008Et-3i for help-gnu-emacs@gnu.org; Wed, 15 Jul 2015 17:02:25 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by mail.mojserwer.eu (Postfix) with ESMTP id F2D28512011 for ; Wed, 15 Jul 2015 23:02:09 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mail.mojserwer.eu Original-Received: from mail.mojserwer.eu ([127.0.0.1]) by localhost (mail.mojserwer.eu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QITUXxeftg6J for ; Wed, 15 Jul 2015 23:02:06 +0200 (CEST) Original-Received: from localhost (unknown [109.232.24.146]) by mail.mojserwer.eu (Postfix) with ESMTPSA id 8B2014F607B for ; Wed, 15 Jul 2015 23:02:05 +0200 (CEST) In-reply-to: <871tg9m9os.fsf@kuiper.lan.informatimago.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 195.110.48.8 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:105740 Archived-At: On 2015-07-15, at 22:45, Pascal J. Bourguignon wrote: > Marcin Borkowski writes: > >> Hi there, >> >> so here's my problem: I have a list of Boolean values, and I want to >> `mapcar' an `or' across it (IOW, I want to test whether at least one of >> them is true). Of course, (apply #'or my-list) does not work. Of >> course, I can (cl-reduce (lambda (x y) (or x y)) my-list) -- but is >> there a better method? >> >> BTW, my-list doesn't really exist: it is a result of `mapcar'ing >> a function taking some value and yielding a Boolean value, so bonus >> points if the method does not process the whole list. > > It's too late, lisp is not a lazy language. Well, *after* I mapcar then it's too late, but your own answer (below) shows that mapcar itself is not necessary (as I suspected). >> (Note: I just noticed that my-list is in fact sorted so that all true >> values (if any) will occur at the beginning anyway, so I can just test >> the first one. This means that my problem is purely academic, though >> still interesting, I guess.) > > First you want to reduce a list of booleans to a single value, so what > makes you thing that mapcar is the right too for that? There's the word > "map" in "mapcar", didn't you notice? My bad, you're right, of course. > map reduce > > x1 --> r1 x1 -\ > x2 --> r2 x2 --+-> r > x3 --> r3 x3 -/ Please, do not shame a mathematician. I hope notany (pun intended;-)) of my students will read this... > Also, mapcar allocates a new list of same length as the original list > for the result, so it is costly. At least, you could consider mapc. True. > With mapc (or mapcar) you could perform your task with some cl magic: > > (require 'cl) > (setf lexical-binding t) > > (defun* or-all (list) > (mapc (lambda (element) > (when element > (return-from or-all t))) > list) > nil) > > (defun* and-all (list) > (mapc (lambda (element) > (unless element > (return-from and-all nil))) > list) > t) > > (or-all '(nil nil nil)) --> nil > (or-all '(nil t nil)) --> t > > (and-all '(t t t)) --> t > (and-all '(t nil t)) --> nil > > > But I fail to see how it's better than: > > (defun* or-all (list) > (reduce (lambda (a b) (or a b)) list)) > > (defun* and-all (list) > (reduce (lambda (a b) (and a b)) list)) Of course, but - as I expected - someone already felt that there should be a more elegant way, and hence the abstraction called `some', `every' etc. > or than just: > > (some 'identity '(nil nil nil)) --> nil > (some 'identity '(nil t nil)) --> t > (some 'identity '(t t t )) --> t > > (every 'identity '(nil nil nil)) --> nil > (every 'identity '(t nil t )) --> nil > (every 'identity '(t t t )) --> t > > There are also the negations: > > (notevery 'identity '(nil nil nil)) --> t > (notevery 'identity '(nil t nil)) --> t > (notevery 'identity '(t t t )) --> nil > > (notany 'identity '(nil nil nil)) --> t > (notany 'identity '(t nil t )) --> nil > (notany 'identity '(t t t )) --> nil > > And since your booleans are computed by a function with mapcar, you > could avoid computing this function for all the elements of the original > list, and you could avoid allocating the temporary list by having some > call this function: > > > So instead of: > > (reduce (lambda (a b) (or a b)) > (mapcar 'complex-and-lengthy-predicate list)) > > use: > > (some 'complex-and-lengthy-predicate list) How cool. Again: I felt that something like that should exist, so I'm not surprised that it actually does. > For example: > (some (lambda (x) (print x) (evenp x)) '(1 2 3 5 7 9 11)) > prints: > 1 > > 2 > --> t > > > Learn more about Common Lisp: > http://www.lispworks.com/documentation/HyperSpec/Front/ > http://cliki.net/ Well, maybe I should. I have a bunch of students who want to study CL, I should be able to help them;-). (I read parts of the Cl spec, most of "Practical Common Lisp" and small parts of "On Lisp", but that was a few years ago...) Thanks again, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Faculty of Mathematics and Computer Science Adam Mickiewicz University