How to declare a function before its definition in common lisp?
Asked Answered
E

4

7

I will get an undefined function warning about f2 in SBCL with following code sample. Is it possible that I can declare f2 first, like in C, to avoid the warning. I Googled, without any clue.

(defun f ()
  (print (f2)))

(defun f2 ()
  (print "f2"))
Emileeemili answered 28/11, 2016 at 4:3 Comment(0)
K
8

If you use the function before you define it in a single compilation unit, e.g., the same file, then the compiler will not complain about the undefined function (plain load still may, so compile your code first!)

Otherwise, you can declaim ftype:

(declaim (ftype (function () t) f2)

meaning that f2 accepts no arguments and returns a single value of type t.

However, it makes much more sense to compile the file where you use the function while the definition is already loaded. You can (and should!) use asdf as a Lisp-specific make(1): specifying dependencies so that the compiler has the definitions of all the functions while it compiles their users.

Karb answered 28/11, 2016 at 4:26 Comment(6)
much appreciated, I have been looking for this for a very long time. ;-) And it works with declaim. - BTW, even I put both functions in same file, sbcl still give undefined function warning.Emileeemili
@lll You're probably just loading the file instead of first compiling it. From the repl, use (load (compile-file "file.lisp")), or from Slime/Sly use C-c C-k.Blah
Actually I think what the standard calls 'compilation unit' has not effects for compilation semantics. The compiler semantics of a function in a file being used before later being defined in the same file, has nothing to do with a 'compilation unit' - it is just tied to the idea of file compilation - and not a concept of 'compilation unit' - which only exist vaguely defined by with-compilation-unit.Fixed
@RainerJoswig: I think the writeup is sufficiently clear.Karb
The behaviour is optional (can expand into a progn) and what it means to defer warnings is not well specified. The implementations actually are deferring undefined function warnings and are only warning about those who are not defined in the compiled files - but it seems to me that this functionality is more or less underspecified in the standard. For example sbcl does not complain when it eventually sees the function, but it does no longer check the arglist - which it does within one file. CCL / CLISP still check the arglists.Fixed
@RainerJoswig: yes, this is why I recommend asdf.Karb
F
4

If the functions are in the same file, a compiler won't give a warning.

Example SBCL:

bash-3.2$ sbcl
This is SBCL 1.3.10, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (compile-file "/tmp/order.lisp")

; compiling file "/private/tmp/order.lisp" (written 28 NOV 2016 12:14:37 PM):
; compiling (DEFUN F ...)
; compiling (DEFUN F2 ...)

; /tmp/order.fasl written
; compilation finished in 0:00:00.178
#P"/private/tmp/order.fasl"
NIL
NIL
* (load *)

T
* 
Fixed answered 28/11, 2016 at 11:16 Comment(0)
R
4

You do not have to put functions into the same file in Common Lisp for them to be in the same compilation unit.

Doing this is an anti-pattern; large programs are, of course, constructed from modules, most of which call functions that are in another module. You cannot roll an entire program into a single physical module to avoid a warning about this.

Lisp has a mechanism by which a cluster of compiles is regarded as a single compilation unit: the with-compilation-unit macro:

(with-compilation-unit
  (compile-file "file-f")
  (compile-file "file-f2"))

If you use the ASDF build system, I seem to recall it does the with-compilation-unit under the hood for you, around all of the files of a system.

This approach will help eliminate those warnings which are deferred. That is to say, if the implementation warns about undefined identifiers, but defers doing so until the end of the compilation unit, then if you use this macro, the deferral is extended until the end of the total compilation unit spanning multiple files.

When warnings about undefined identifiers are deferred, the purpose is to eliminate those warnings. If the definition of a previously undefined function appears before the end of a translation unit, the warning can be suppressed. This macro allows a definition in one file to suppress a deferred warning in another file.

If an implementation doesn't defer warnings, then the macro will not help.

Rebec answered 28/11, 2016 at 15:38 Comment(3)
This just defers the warning to the end of the compilation unit. The question was to get rid of the warning.Fixed
If you think a bit about it, it appears that it also would not be a good idea to get rid of the warning by just wrapping a WITH-COMPILATION-UNIT around the compilation of two files. The function would still be undefined in the first file.Fixed
@RainerJoswig I'm not aware of a ANSI CL way to say "please get rid of this warning". The idea is that if an implementation defers warnings then with-compilation-unit will extend that deferral over several files. An implementation defers warnings precisely for the purpose of squashing unnecessary ones. A deferred "undefined function" warning spontaneously vanishes if a definition of the function is seen before the end of the compilation unit.Rebec
M
1

Just change the order of your defun's. First, define f2 and than f.

Mix answered 28/11, 2016 at 7:23 Comment(2)
Can't use this approach if you have mutual recursion which creates a cycle in the call graph.Rebec
Although, definitions then use is a good program organization. Hard to maintain over a long time in large programs, though, without moving functions around, which creates ugly textual diffs that interfere with merges. Often you find, "damn, I need to call this function from here now, but it's defined later".Rebec

© 2022 - 2024 — McMap. All rights reserved.