From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Klaus-Dieter Bauer Newsgroups: gmane.emacs.devel Subject: Can the byte-compiler check whether functions passed by name are defined? Date: Mon, 29 Jul 2013 12:35:03 +0200 Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=047d7b3a7dd86363fd04e2a40d4a X-Trace: ger.gmane.org 1375094144 26389 80.91.229.3 (29 Jul 2013 10:35:44 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 29 Jul 2013 10:35:44 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jul 29 12:35:47 2013 Return-path: Envelope-to: ged-emacs-devel@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 1V3knq-0007cN-1K for ged-emacs-devel@m.gmane.org; Mon, 29 Jul 2013 12:35:46 +0200 Original-Received: from localhost ([::1]:46119 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3knp-0005hs-B2 for ged-emacs-devel@m.gmane.org; Mon, 29 Jul 2013 06:35:45 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54409) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3knj-0005hd-2p for emacs-devel@gnu.org; Mon, 29 Jul 2013 06:35:42 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V3knf-0004My-2d for emacs-devel@gnu.org; Mon, 29 Jul 2013 06:35:38 -0400 Original-Received: from mail-ve0-x22c.google.com ([2607:f8b0:400c:c01::22c]:50611) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3kne-0004Mb-SI for emacs-devel@gnu.org; Mon, 29 Jul 2013 06:35:34 -0400 Original-Received: by mail-ve0-f172.google.com with SMTP id oz10so2807354veb.3 for ; Mon, 29 Jul 2013 03:35:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=ms1knirMQmO6Fvx4XzSsqM4tbCK44JPX0tYjWUfli3g=; b=EGGMRuXGHgZPyvwIzygEQeaWuu4KqwAk+jgj8gR2dplnGSZ/TwoB6QayhlRFguHsPf Q1RXJqZDwlzvswn0ULkzUTblOF3gnFrdaUNu6nESOwD5VUhqn282ry6rx+1OvfyGtFvO HoFN6KQYKZ/NQZaAxWE69i5AAs0AB+z2he4ACxgoDN+CoB/gBRFfPr4mYPGYF28ZDb3b Bsn99NJKczkjqhbECrLrqYMU76oSTJ4KKNjCunz8Jnvgr+QNkxz9OchTndU8FGq7YhbX yTyVUQFiYSIROwdqHNKm78dEA5RPBnTq2iXph5TDtBCzJKZjq+O1GUPDX8tH4Z8aJk9E f9uA== X-Received: by 10.220.101.197 with SMTP id d5mr8217882vco.59.1375094133972; Mon, 29 Jul 2013 03:35:33 -0700 (PDT) Original-Received: by 10.220.38.194 with HTTP; Mon, 29 Jul 2013 03:35:03 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400c:c01::22c X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:162236 Archived-At: --047d7b3a7dd86363fd04e2a40d4a Content-Type: text/plain; charset=UTF-8 Hello! TL;DR ===== Is there some possibility to make the byte-compiler check, whether functions passed to higher-order functions as a symbol are defined at compile-time, e.g. my-function-1 in (mapcar 'my-function-1 some-list)? I know some (intrusive) solutions, but if there is a built-in solution or at least an elegant solution I'd strongly prefer that one. My use-case =========== When I do programming in emacs lisp, I typically start top-down. In that process I introduce functions about whose implementation I intend to think later, and rely on the byte-compiler for pointing out functions to be implemented. That approach however breaks down, when using higher-order functions. If I have a function (defun my-function (strings) (append (list "start") (mapcar 'my-function-1 strings) (list "end"))) the byte-compiler will not tell me, that the function is undefined. What is normally a byte-compiler warning is now a runtime error. So far I don't know a //good// workaround, though I tried some: 1. Don't use a name, write a lambda in-place. Downside: Seriously reduces readability when `my-function-1' is complex or especially, when it contains something like (mapcar 'my-function-1 (delete nil (mapcar 'my-function-2 strings))) 2. Use a combination of function and variable ... (mapcar my-function-1 strings) ... (defconst my-function-1 (lambda () ... Downside: Uncommon, therefore probably hard to read for anyone else (and probably for myself a year later). 3. Wrap into a lambda. (mapcar (lambda (e) (my-function-1 e)) strings) Upside: When `my-function-1' is a general function that needs more than one argument, this construct seems to be an elegant solution when using lexical binding. Downside: When, like here, it takes only one argument, it is more likely unnecessarily confusing. 4. Wrap the higher-order functions into macros that do the check at compile time. Downside: I cannot think of a way, that - Preserves the interface, including parameter names, and thus the readbility of the `describe-function' text. - Is future proof in that it doesn't require changing the wrapper code when the interface of the function is changed in a backward-compatible way. - Doesn't interfere with the runtime behaviour of interpreted code (e.g. raising warnings only during compilation, but not when interpreting the code). kind regards, Klaus --047d7b3a7dd86363fd04e2a40d4a Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hello!


<= div>TL;DR
=3D=3D=3D=3D=3D

Is there some = possibility to make the byte-compiler check,
whether functions pa= ssed to higher-order functions as a symbol are
defined at compile-time, e.g. my-function-1 in=C2=A0

=C2=A0 =C2=A0 (mapcar 'my-function-1 some-list)?

=
I know some (intrusive) solutions, but if there is a built-in so= lution
or at least an elegant solution I'd strongly prefer that one.


My use-case
=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D

When I do programming in emacs = lisp, I typically start top-down. In
that process I introduce functions about whose implementation I intend=
to think later, and rely on the byte-compiler for pointing out
functions to be implemented.

That approac= h however breaks down, when using higher-order functions.
If I have a function

=C2=A0 =C2=A0 (defun my-= function (strings)
=C2=A0 =C2=A0 =C2=A0 (append (list "start= ")
=C2= =A0 =C2=A0 =C2=A0(mapcar 'my-function-1 strings)
=C2=A0 =C2=A0 =C2= =A0(list "end")))

the byte-compiler will= not tell me, that the function is undefined.
What is normally a = byte-compiler warning is now a runtime error. So
far I don't know a //good// workaround, though I tried some:
=

1. Don't use a name, write a lambda in-place. Downs= ide: Seriously
=C2=A0 =C2=A0reduces readability when `my-function= -1' is complex or especially,
=C2=A0 =C2=A0when it contains something like
=C2=A0 =C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0(mapcar 'my-function-1
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(delete nil=C2=A0
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0(mapcar 'my-function-2 strings)))

2. Use a combination of function and variable

=C2=A0 =C2=A0 =C2=A0 =C2=A0...
=C2=A0 =C2=A0 = =C2=A0 =C2=A0(mapcar my-function-1 strings)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0...
=C2=A0 =C2=A0 =C2=A0 =C2=A0(defconst my-function-1 (lam= bda () ...

=C2=A0 =C2=A0Downside: Uncommon, theref= ore probably hard to read for anyone else
=C2=A0 =C2=A0(and probably for myself a year later).=C2=A0
<= br>
3. Wrap into a lambda.

=C2=A0 =C2=A0= =C2=A0 =C2=A0(mapcar (lambda (e) (my-function-1 e)) strings)
=C2=A0 =C2=A0Upside: When `my-function-1' is a general func= tion that needs
=C2=A0 =C2=A0more than one argument, this construct seems to be an ele= gant
=C2=A0 =C2=A0solution when using lexical binding.
=
=C2=A0 =C2=A0Downside: When, like here, it takes only one ar= gument, it is more
=C2=A0 =C2=A0likely unnecessarily confusing.=C2=A0

4. Wrap the higher-order functions into macros that do the check at
<= div>=C2=A0 =C2=A0compile time.=C2=A0

=C2=A0 =C2=A0= Downside: I cannot think of a way, that

=C2=A0 =C2=A0- Preserves the interface, including param= eter names, and thus
=C2=A0 =C2=A0 =C2=A0the readbility of the `d= escribe-function' text.
=C2=A0 =C2=A0- Is future proof in tha= t it doesn't require changing the wrapper
=C2=A0 =C2=A0 =C2=A0code when the interface of the function is changed= in a
=C2=A0 =C2=A0 =C2=A0backward-compatible way.=C2=A0
=C2=A0 =C2=A0- Doesn't interfere with the runtime behaviour of interp= reted code
=C2=A0 =C2=A0 =C2=A0(e.g. raising warnings only during= compilation, but not when
=C2=A0 =C2=A0 =C2=A0interpreting the code).=C2=A0

=

kind regards, Klaus
--047d7b3a7dd86363fd04e2a40d4a--