How to trace a local function [duplicate] - common-lisp

In common lisp, the function (trace name) can be used to see output about the calls to a function.
If my function is declared with local scope, how do I describe it to trace?
eg, how do I trace bar, below:
(defun foo (x)
(labels ((bar (y) (format t "bar: ~a~&" y)))
(bar x)))

As there is no standard way of tracing local functions, the way I'd go about the problem is by writing a tracing-labels macro that implements tracing, transforming the following:
(defun foo (x)
(tracing-labels ((bar (y) (format t "bar: ~a~&" y)))
(bar x)))
into something like this:
(defun foo (x)
(labels ((bar (y)
(format *trace-output* "~&ENTER: ~S" 'bar) ;'
(multiple-value-prog1
(progn (format t "bar: ~a~&" y))
(format *trace-output* "~&LEAVE: ~S" 'bar)))) ;'
(bar x)))

Tracing local functions with (TRACE ...) is not defined by ANSI Common Lisp.
Some implementations have extensions to do that. See for example CMU CL.
Other than that, you would need add some code to the definition of FOO. For example it might be useful to have a macro so that you can write the call to bar as (trace-it (bar x)) and the macro would expand into code that prints the entry and exit.

Related

Controlling the printing of special cons forms (e.g printing (function +) as #'+ etc)

I want some reader macros to print as as shortened expression that the macro understands. Lets say I want to extend the #' macro to take #'~[rest-of-symbol] and turn that into (complement #'rest-of-symbol).
What controls how that is printed? On SBCL, for instance, '(function +) prints as #'+. How do i make '(complement #'listp) print as #~listp?
My first thought was
(defmethod print-object :around ((obj cons) stream)
;; if #'~fn-name / (complement (function fn-name))
;; => fn-name otherwise NIL
(let ((fn-name
(ignore-errors
(destructuring-bind (complement (function fn-name))
obj
(when (and (eq complement 'complement)
(eq function 'function))
fn-name)))))
(if fn-name
(format stream "#'~~~S" fn-name)
(call-next-method))))
This works insofar as (print-object '(complement #'evenp) *standard-output*) prints it the way I want, but the REPL doesn't. Also (print-object '#'+ *standard-output*) prints it as (function +) so the REPL isn't using print-object. With defining the print-object method for user defined classes the REPL always picks up on the new definition.
This is my first post and I'm sorry I can't get the code to format properly. If someone can put a link on how to do that I would appreciate it.
Evaluation time
You are mixing code with data in your example:
(function +)
Is a special form that evaluates to a function object, which admits a shorter syntax:
#'+
But when you are writing:
'(function +)
or
'(complement fn)
Then in both cases you are writing quoted, literal lists, which evaluates to themselves (namely a list starting with symbol function or complement, followed respectively by symbol + and fn).
However, you want the code to be evaluated at runtime to actual function objects; if you type this in the REPL:
(complement #'alpha-char-p)
The result is a value that is printed as follows:
#<FUNCTION (LAMBDA (&REST SB-IMPL::ARGUMENTS) :IN COMPLEMENT) {101AAC8D9B}>
You have an actual function object that you can funcall. In other words, by the time you reach print-object, you no longer have access to source code, you are manipulating data at runtime which happens to be functions. So you cannot use destructuring-bind to get the complement symbol that was present in the source code.
What you need to do instead is to attach metadata to your function. There is a way to do that in Common Lisp by defining a new type of function, thanks to the Meta-Object Protocol.
Funcallable objects
I'm relying on Closer-MOP for all the symbols prefixed with c2cl: below. I define a new class of functions, annotated-fn, which is a function with addditional data:
(defclass annotated-fn (c2cl:funcallable-standard-object)
((data :initform :data :initarg :data :reader annotated-fn-data))
(:metaclass c2cl:funcallable-standard-class))
Notice that this class is a funcallable-standard-object (like the usual functions), and its metaclass is funcallable-standard-class. Such an object has an additional implicit slot that is a function to call.
More precisely, you have to call c2cl:set-funcallable-instance-function to set a function associated with the object, and when later you use funcall or apply with the object, then the wrapped function is called instead. So you can transparently use this class of functions wherever you usually use a function. It just has additional slots (here data).
For example, here is how I instantiate it, with a function to wrap additional data:
(defun annotate-fn (function data)
(let ((object (make-instance 'annotated-fn :data data)))
(prog1 object
(c2cl:set-funcallable-instance-function object function))))
Let's try it:
(describe
(annotate-fn (constantly 3)
'(:category :constantly)))
#<ANNOTATED-FN {1006275C7B}>
[funcallable-instance]
Lambda-list: UNKNOWN
Derived type: FUNCTION
Documentation:
T
Source file: SYS:SRC;CODE;FUNUTILS.LISP
Slots with :INSTANCE allocation:
DATA = (:CATEGORY :CONSTANTLY)
You can also use this object like any other function.
Now, your reader macros can expand into calls to annotate-fn, and add any kind of additional metadata you need to the function.
Reader macro
For our example, imagine you define a reader macros for constant functions:
(set-macro-character #\[ 'read-constantly t)
(set-macro-character #\] (get-macro-character #\) nil))
(defun read-constantly (stream char)
(declare (ignore char))
(let* ((list (read-delimited-list #\] stream t))
(value (if (rest list) list (first list)))
(var (gensym)))
`(let ((,var ,value))
(annotate-fn (constantly ,var)
(list :category :constantly
:constant ,var)))))
Using this syntax:
> [(+ 8 5)]
=> #<ANNOTATED-FN ...>
By the way, the syntax I defined also allows the following:
> [+ 8 5]
Pretty-printing
Let's define a generic function that prints an annotated function given its :category field:
(defgeneric print-for-category (category data object stream))
(defmethod print-object ((o annotated-fn) s)
(let* ((data (annotated-fn-data o))
(category (getf data :category)))
(print-for-category category data o s)))
Then, we can specialize it for :constantly, and here we assume also that the data associated with the function contains a :constant field:
(defmethod print-for-category ((_ (eql :constantly)) data o s)
(format s "[~s]" (getf data :constant)))
For example:
(let ((value (+ 8 6)))
(annotate-fn (constantly value)
`(:constant ,value
:category :constantly)))
This above is printed as:
[14]
Which would be the same as your hypothetical reader macro.
To do this you need to understand the pretty printer. I have understood it in the past but no longer do completely. It dispatches on type and the trick for things like this is that you can specify very specific types for trees of conses, although doing so is verbose.
Here is an example which is almost certainly not completely correct, but does achieve what you want in this case:
(defparameter *ppd* (copy-pprint-dispatch))
(defun pprint-complement-function (s form)
;; This is the thing that the pretty printer will call. It can
;; assume that the form it wants to print is already correct.
(destructuring-bind (complement (function name)) form
(declare (ignore complement function))
(format s "#'~~~W" name)))
;;; Now set this in the table with a suitable hairy type specification
;;;
(set-pprint-dispatch '(cons (eql complement)
(cons (cons (eql function)
(cons t null))
null))
'pprint-complement-function
0
*ppd*)
And now
> (let ((*print-pprint-dispatch* *ppd*))
(pprint '(complement (function foo)))
(pprint '((complement (function foo)) (function foo))))
#'~foo
(#'~foo #'foo)
You can make the awful nested cons type specifier easier by defining this (which, perhaps, should be the compound type specifier for list except you can't do that):
(deftype list-of-types (&rest types)
(labels ((lot (tt)
(if (null tt)
'null
`(cons ,(first tt) ,(lot (rest tt))))))
(lot types)))
And then
(set-pprint-dispatch '(list-of-types (eql complement)
(list-of-types (eql function)
*))
'pprint-complement-function
0
*ppd*)
is perhaps easier to read.

How do you create an interpreted function in SBCL?

I want to create an interpreted function definition, not a compiled one.
SBCL manual says :
Variable: *evaluator-mode* [sb-ext] : Toggle between different evaluator
implementations. If set to :compile, an implementation of eval that
calls the compiler will be used. If set to :interpret, an interpreter
will be used.
So, I try to create a BAR function (which does not exist) :
(let ((sb-ext::*evaluator-mode* :interpret))
(defun bar (x) (+ x 1)))
But then, I check, and BAR is already compiled :
CL-USER> (compiled-function-p #'bar)
T
So, how do you create an interpreted version of BAR ?
The let form in your question only sets the evaluator mode at runtime. By then, the function has already been compiled.
You need to set it at load time and also make sure to load the file instead of compiling then loading it.
Try this:
In your-file.lisp:
;; at load time, set evaluator mode to interpret (before bar definition is met)
(eval-when (:load-toplevel :execute)
(setf sb-ext::*evaluator-mode* :interpret))
;;define your interpreted function
(defun bar (x)
(+ x 1))
;; set evaluator back to compile mode (optional)
(eval-when (:load-toplevel :execute)
(setf sb-ext::*evaluator-mode* :compile))
;;check if bar is a compiled function
(print (compiled-function-p #'bar)) ;;prints NIL
Then load it with (load "your-file.lisp") (this doesn't compile the file first).
I think that *evaluator-mode* is pretty inherently a global variable. For instance, if you do this:
> (setf sb-ext:*evaluator-mode* ':interpret)
:interpret
> (setf (symbol-function 'bar)
(lambda (x) x))
#<interpreted-function nil {10026E7E2B}>
> (compiled-function-p #'bar)
nil
you get an interpreted function. But if you do this:
> (setf sb-ext:*evaluator-mode* ':compile)
:compile
> (setf (symbol-function 'bar)
(let ((sb-ext:*evaluator-mode* ':interpret))
(lambda (x) x)))
#<function (lambda (x)) {52C3687B}>
> (compiled-function-p #'bar)
t
You don't. My take on this, which may be wrong, is that the value which is in effect at the start of each top-level form is what counts: once the system has decided that it's going to use the compiling-evaluator for a form then it can't change its mind.
And note that there is a complicated definition of 'top-level form', and in particular that when processing a file then in a form like
(let (...)
(x ...))
then (x ...) is not a top-level form.

How can I define a &key argument that supersedes an &optional parameter in Lisp

I just started writing this function and I was wondering if there was a way, that if just the &key argument was entered, the &optional list could be ignored.
(defun test (&optional arg (i 0) &key (size s))
...)
I would like to be able to run
(test arg)
or
(test arg i)
but also
(test :size)
Now this is a better mock up but I don't know where to put :size in params list
(defun test (&optional arg (i 0))
(cond ((eq arg nil) (return-from test (test-1)))
((listp arg)
(return-from test (test-2 arg)))
((pointerp arg) (mem-aref (test-3 arg) :int i))
(:size (size-test arg))
(t nil)))
so i can run (test) and get:
<output of (test-1)>
I can run (test '(1 2 3)) and get:
<output of (test-2 arg)>
I can run (test <pointer> 0)
and output is:
<output of (mem-aref (test-3 arg) :int i)>
I can run (test :size) and get:
<output of (test-size arg)>
Mixing optional and keyword arguments
Mixing optional and keyword arguments is still something that's not all that easy to do. If a function accepts an optional argument, then you won't be able to use the keyword arguments unless the optional argument is also provided. Otherwise, the first keyword would be interpreted as the optional argument, and so on. See, for instance, this Stack Overflow question: How can I have optional arguments AND keyword arguments to the same function?. As the answer to that question points out, it's usually a bug-prone practice to mix optional and keyword arguments. Common Lisp does it with read-from-string, and it often leads people into trouble.
What you're proposing, though, isn't just having a function that uses both keyword and optional arguments, but, from the sounds of it, is actually doing some checking of the types of arguments, and taking one behavior in one case, and another in another. In this case, if i is supposed to be a number, then you could check the first argument, and if it's a number, then treat it as the optional argument, and the rest as keyword arguments, and if it's not a number, then treat the whole list as keyword arguments. You can do that with an &rest argument that you destructure in different ways:
(defun frob (&rest args)
(flet ((frob-driver (i size)
(list i size)))
(if (or (endp args) (numberp (first args)))
;; no args, or the first argument is a number (and thus
;; not a keyword argument)...
(destructuring-bind (&optional (i 'default-i) &key (size 'default-size)) args
(frob-driver i size))
;; otherwise, there are some non-numeric arguments at
;; beginning, so it must be the keyword list, and that the
;; "optional" wasn't provided.
(destructuring-bind (&key (size 'default-size) &aux (i 'default-i)) args
(frob-driver i size)))))
(frob 10 :size 50) ; give i and size
;=> (10 50)
(frob :size 60) ; give size, but not i
;=> (default-i 60)
(frob 40) ; give i, but not size
;=> (40 default-size)
(frob) ; give neither
;=> (default-i default-size)
Keyword arguments without keyword symbols
In the comments, you mentioned that you'd like to be able to use non-keyword symbols as keywords in argument lists. This is easy enough. In the HyperSpec, ยง3.4.1 Ordinary Lambda Lists describes the syntax for keyword arguments:
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
This means that you can define functions like this:
(defun frob (&key foo ((bar-keyword bar-variable) 'default-baz))
(list foo bar-variable))
(frob :foo 1 'bar-keyword 2)
;=> (1 2)
(frob :foo 3)
;=> (3 default-baz)
(frob 'bar-keyword 2)
;=> (nil 2)
You have to use a &rest argument list and process it in the function.
Mixing optional and keyword arguments should be avoided. It is BAD style to use optional and keyword arguments. This has been the source for countless errors with the few functions which use that (like READ-FROM-STRING).
In short, "no". There's no way of making that happen. As a general rule, try to stay away from mixing &rest, &optional and &key arguments, since their interactions are subtle and will more frequently trip you up than actually be useful.
Furthermore, if :size is a keyword argument, hen (test :size) is missing one argument (the value to bind size to). Your best bet is probably to look a arg to see if it is :size or something else.
Posting as answer because I solved the main issue here is the resultant code I came up with, The cond statements are what matter. The &args usage created another issue and that post is being discussed here. The ((symbolp (cadr args)) (%vector-float-size (first args))) line is what I came up with from Joshua Taylors kindly written and extremely informative answer.
(defun vector-float (&rest args)
(cond ((eq (first args) nil) (return-from vector-float (%vector-float)))
((listp (first args))
(c-arr-to-vector-float (first args)))
((symbolp (cadr args)) (%vector-float-size (first args)))
((pointerp (first args)) (mem-aref (%vector-float-to-c-array (first args)) :float (second args)))
(t nil)))

The #' in common lisp

In chapter 3 of Practical Common Lisp book there's an example of a SQL-like select and where functions. Here's a simplified version of it:
(defun where (x)
#'(lambda (item)
(> item x)))
and it is used like this:
(remove-if-not (where 2) (list 1 2 3 4))
Earlier in the book it is explained that the #' sequence is used to state that it is followed by a function name, rather than a variable that requires evaluation. I don't understand why it's needed here. I tried implementing the where function without it and it worked as well:
(defun where (x)
(lambda (item)
(> item x)))
I tried googling for it, and, as you can imagine, with such a sequence of characters it wasn't a very fruitful search. And I don't know the name of this thing.
Is there any particular reason why it's needed in the above code?
This is the precise page in Hyperspec which deals with the standard macro character "sharp" followed by "single quote".
To make it simple, this reader macro expands to enclose the following form into (function <form>) s-expression. This effectively tells the parser that the form is callable.
lambda is a macro, which generates the code, which already contains the (function <form>), but historically and for consistency, the alternative form, which is obtained from the reader macro with sharp + quote, is often used too.
Here's Writing lambda expressions in common lisp (another StackOverflow question) which covers in-depth the particular case of (lambda <form>)
Note: *print-pretty* is NIL for these examples.
(defun where (x)
#'(lambda (item)
(> item x)))
In above function where you are creating an anonymous function and you are returning it as a closure (the function plus variable binding for X). Since you are returning it as a value, you have to write (FUNCTION (LAMBDA ...)). #'(lambda ...) is a notation which is shorter, but results in the same - using the reader macro #':
CL-USER 74 > (read-from-string "#'(lambda (foo) (1+ foo))")
(FUNCTION (LAMBDA (FOO) (1+ FOO)))
You can also write:
(defun where (x)
(lambda (item)
(> item x)))
During the definition of Common Lisp it has been added to be able to write above code. It is also identical to the (function (lambda ...)) form. In Common Lisp LAMBDA is macro, which expands into it:
CL-USER 75 > '(lambda (foo) (1+ foo))
(LAMBDA (FOO) (1+ FOO))
CL-USER 76 > (macroexpand '(lambda (foo) (1+ foo)))
(FUNCTION (LAMBDA (FOO) (1+ FOO)))
T
So, LAMBDA is a macro and when the evaluator sees it as in (lambda ...), it expands the form into a (function (lambda ...)) form, which then gets evaluated.
FUNCTION is a special form and when the evaluator sees it, it returns a function object - in the case of (function (lambda (foo) (1+ foo))) it returns the anonymous function as an object:
CL-USER 77 > (function (lambda (foo) (1+ foo)))
#<anonymous interpreted function 406000761C>
So you see that (function (lambda ...)) is the real s-expression notation to get a function object and both #'(lambda ...) (via a reader macro) or (lambda ...) (via a macro) are shorter notations in Lisp source code. It is unusual for a programmer to use the long form. Most (99.999%) use one of the shorter notations in source code.
Btw.: If the evaluator sees function enclosing a name of a function like this (function sin), then it looks up the function binding and returns the corresponding function object:
CL-USER 78 > (function sin)
#<Function SIN 4110083C6C>

Common lisp: Redefine an existing function within a scope?

In Common Lisp, is it possible to redefine an already defined function within a certain scope? For example, given a function A that calls a function B. Can I temporarily redefine B during a call to A?
I'm looking for something along the lines of a let block, but that can redefine functions.
Within a given lexical scope, yes. Use FLET or LABELS. Any function defined with FLET will be unable to call functions defined in the same lexical scope, if you want that (for, say, self-recursive of a group of mutually recursive functions), you will need to use LABELS.
Note that both FLET and LABELS only establish lexical shadowing, should not be used to shadow functions from the COMMON-LISP package and will not dynamically change what function is called from outside the lexical scope the form establishes.
Local functions can be introduced with FLET and LABELS.
If you want to redefine/shadow an existing function using dynamic scope, this is a macro I've been using for a while.
(defmacro! with-shadow ((fname fun) &body body)
"Shadow the function named fname with fun
Any call to fname within body will use fun, instead of the default function for fname.
This macro is intentionally unhygienic:
fun-orig is the anaphor, and can be used in body to access the shadowed function"
`(let ((fun-orig))
(cond ((fboundp ',fname)
(setf fun-orig (symbol-function ',fname))
(setf (symbol-function ',fname) ,fun)
(unwind-protect (progn ,#body)
(setf (symbol-function ',fname) fun-orig)))
(t
(setf (symbol-function ',fname) ,fun)
(unwind-protect (progn ,#body)
(fmakunbound ',fname))))))
Usage:
Clozure Common Lisp Version 1.9-r15759 (DarwinX8664) Port: 4005 Pid: 4728
; SWANK 2012-03-06
CL-USER>
(defun print-using-another-fname (x)
(print x))
PRINT-USING-ANOTHER-FNAME
CL-USER>
(let ((*warn-if-redefine-kernel* nil))
(with-shadow (print (lambda (x)
(funcall fun-orig (+ x 5))))
(print-using-another-fname 10)))
15
15
CL-USER>
(print 10)
10
10
CL-USER>
Note that it relies on Doug Hoyte's defmacro! macro, available in Let Over Lambda.
Also as written, it's anaphoric (fun-orig is available within the body). If you want it completely hygienic, just change the fun-orig's to ,g!fun-orig's.
I most often redefine functions when writing unit tests. Mocking functions within the scope of a particular unit test is helpful, and sometimes that needs to be done with dynamic (not lexical) scope.
You can simulate dynamic-binding for funs like this:
(defmacro setvfun (symbol function)
`(progn
(setf ,symbol ,function)
(setf (symbol-function ',symbol) (lambda (&rest args) (apply (symbol-value ',symbol) args)))))
and then ,for example, with
(setvfun some-fun (lambda() (format t "initial-definition~%")))
(defun test-the-fun (&rest args) (apply #'some-fun args))
(defun test ()
(test-the-fun)
(flet ((some-fun () (format t "Lexically REDEFINED (if you see this, something is very wrong)~%")))
(test-the-fun))
(let ((some-fun (lambda (x) (format t "Dynamically REDEFINED with args: ~a~%" x))))
(declare (special some-fun))
(test-the-fun "Hello"))
(test-the-fun))
you get:
REPL> (test)
==>initial-definition
==>initial-definition
==>Dynamically REDEFINED with args: Hello
==>initial-definition

Resources