From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Marcin Borkowski Newsgroups: gmane.emacs.help Subject: How to create a higher order function? Date: Tue, 21 Sep 2021 06:10:50 +0200 Message-ID: <87k0jawotx.fsf@mbork.pl> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="19925"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: mu4e 1.1.0; emacs 28.0.50 To: Help Gnu Emacs mailing list Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Tue Sep 21 06:11:40 2021 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 1mSX86-0004mp-Iw for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 21 Sep 2021 06:11:38 +0200 Original-Received: from localhost ([::1]:57354 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mSX84-0003zG-5m for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 21 Sep 2021 00:11:36 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:55292) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mSX7e-0003yH-33 for help-gnu-emacs@gnu.org; Tue, 21 Sep 2021 00:11:10 -0400 Original-Received: from mail.mojserwer.eu ([195.110.48.8]:45146) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mSX7Z-0007ly-H4 for help-gnu-emacs@gnu.org; Tue, 21 Sep 2021 00:11:09 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by mail.mojserwer.eu (Postfix) with ESMTP id 0F38CE65AD for ; Tue, 21 Sep 2021 06:10:58 +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 a3twhpLK5Jlt for ; Tue, 21 Sep 2021 06:10:54 +0200 (CEST) Original-Received: from localhost (178235147044.dynamic-3-poz-k-0-1-0.vectranet.pl [178.235.147.44]) by mail.mojserwer.eu (Postfix) with ESMTPSA id 2EDB2E6208 for ; Tue, 21 Sep 2021 06:10:54 +0200 (CEST) Received-SPF: pass client-ip=195.110.48.8; envelope-from=mbork@mbork.pl; helo=mail.mojserwer.eu X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.23 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-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:133117 Archived-At: Hi all, assume that I want a function which "inverts" the meaning of a given predicate. Something that would turn `<' into `>=' etc. Here's my first attempt (A): --8<---------------cut here---------------start------------->8--- ;;; -*- lexical-binding: nil; -*- (defun negate (fun) "Try to return a function returning the logical opposite of FUN." (lambda (&rest args) (not (apply fun args)))) --8<---------------cut here---------------end--------------->8--- Of course, it doesn't work, since (under dynamic scope) it just creates a function which uses a dynamic binding for `fun' (which is probably nil). So, here's a better (at least: working) version (B): --8<---------------cut here---------------start------------->8--- ;;; -*- lexical-binding: nil; -*- (defun negate (fun) "Return a function returning the logical opposite of FUN." `(lambda (&rest args) (not (apply ,(symbol-function fun) args)))) --8<---------------cut here---------------end--------------->8--- It seems to work fine, even if it's a bit complicated. Of course, the more obvious way to do it is to use the first definition under lexical scope (C): --8<---------------cut here---------------start------------->8--- ;;; -*- lexical-binding: t; -*- (defun negate (fun) "Try to return a function returning the logical opposite of FUN." (lambda (&rest args) (not (apply fun args)))) --8<---------------cut here---------------end--------------->8--- My question is: which of (B) and (C) is better? (C) is definitely simpler, and with lexical scope becoming the default (perhaps at some point in time in the future) or the recommended (even now, I guess) setting, is probably the way to go. But maybe (B) is better under some circumstances? Is it faster? (I don't think so, and my simple benchmarks were inconclusive.) Is it more memory-efficient? (Could be.) Does it have any other advantage? Disclaimer: I'd like to study the replies and put the answer on my blog and in my book. I'll give the credit where it's due, of course. TIA, -- Marcin Borkowski http://mbork.pl