From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via Users list for the GNU Emacs text editor Newsgroups: gmane.emacs.help Subject: Re: [External] : Re: Testing whether a list contains at least one non-nil element Date: Fri, 28 Oct 2022 09:09:12 -0400 Message-ID: References: <87r0yw85la.fsf@dataswamp.org> <87lep031vm.fsf@web.de> Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="8552"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) To: help-gnu-emacs@gnu.org Cancel-Lock: sha1:DoXgbUSak94Q10lOJCZy9NrLL7c= Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Fri Oct 28 15:10:25 2022 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ooP7x-000201-Gt for geh-help-gnu-emacs@m.gmane-mx.org; Fri, 28 Oct 2022 15:10:25 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ooP70-000890-7v; Fri, 28 Oct 2022 09:09:26 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ooP6y-00087T-Kx for help-gnu-emacs@gnu.org; Fri, 28 Oct 2022 09:09:24 -0400 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ooP6w-00036j-4A for help-gnu-emacs@gnu.org; Fri, 28 Oct 2022 09:09:24 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1ooP6t-0000eC-OE for help-gnu-emacs@gnu.org; Fri, 28 Oct 2022 15:09:19 +0200 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=geh-help-gnu-emacs@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: "help-gnu-emacs" Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.help:140468 Archived-At: Michael Heerdegen [2022-10-28 08:20:45] wrote: > writes: >> If you are doing it "by hand", why not indulge in Lisp's >> "classic elegance", like so: >> >> (defun has-non-nil (lst) >> (cond >> ((null lst) nil) >> ((consp lst) (or (not (null (car lst))) (has-non-nil (cdr lst)))) >> (t (error "Not a proper list! You cheater!")))) > > You don't want to implement such functions in Emacs with recursion > because you'll easily hit `max-lisp-eval-depth' when they are called. Indeed (and it's significantly slower than the corresponding loop without function calls). > Sorry to tell you, but a loop is the preferable way in Elisp. Luckily, since Emacs-28 you can have your cake and eat it too: (defun has-non-nil (lst) (named-let loop ((lst lst)) (cond ((null lst) nil) ((consp lst) (or (not (null (car lst))) (loop (cdr lst)))) (t (error "Not a proper list! You cheater!"))))) Admittedly, here the `named-let` construct gives you only the elimination of tail-recursion, but in many other circumstances it also leads to quite elegant code. Stefan PS: For the curious, here's what the above `named-let` expands to: (defalias 'has-non-nil #'(lambda (lst) (let ((lst lst)) (let (retval) (while (let ((lst lst)) (cond ((null lst) nil) ((consp lst) (let ((val (not (null (car lst))))) (if val (progn (setq retval val) nil) (progn (setq lst (cdr lst)) :recurse)))) (t (progn (setq retval (error "Not a proper list! You cheater!")) nil))))) retval))))