[Openmcl-devel] documentation from the string to the error print
Janusz Podrazik
info at mracpublishing.com
Wed Jun 22 05:56:54 PDT 2011
It was my mistake, all of your macros working well - I should not quote the function name (do-quietly 'sum ; just sum
Janusz
On Wednesday, 22 June 2011 at 12:16, Janusz Podrazik wrote:
> Dear Pascal,
>
> Thanks so much for the in depth explanation.
> I had try your suggestions but never got the result I am looking for.
>
> The entire code for the DIAGNOSE-QUIETLY:
>
> ;;; -----------------------------------------------------------------------------
> ;;; DIAGNOSE-QUIETLY
> ;;; -----------------------------------------------------------------------------
>
> (defVar diagnose-verbose t)
> (defVar $cr$ 'nil)
> (defVar *compile-diagnose* nil)
> (defParameter *current-evaluation* "")
>
> (defun diagnostic (&rest l)
> (when l (setq *current-evaluation* (car l)))
> (if diagnose-verbose
> (dolist (item l)
> (if (eql item $cr$)
> (terpri)
> (princ item)))))
>
> (defMacro do-quietly (name &body body)
> `(let ((temp diagnose-verbose)
> (return-value nil))
> (handler-case
> (progn
> (setq diagnose-verbose nil)
> (setq return-value (progn , at body))
> (setq diagnose-verbose temp)
> return-value)
> (error (c)
> (princ "ERROR! Check parameters.")
> (princ (documentation ',name 'function))
> (print c)
> (setq diagnose-verbose temp)
> (abort)))))
>
> (defun sum (n)
> "SUM (numbers)
> Returns the sum of the elements in a series of numbers.
> Examples:
> (sum '(1 2 3 4))
> (sum '(1 2 3 -4))"
> (diagnostic "sum" $cr$)
> (do-quietly 'sum
> (reduce #'+ n)))
>
>
> The diagnostic function print the name and the result:
>
> (sum '(1 2 3 4))
> ? sum
> 10
>
> The do-quietly macro suppress the print of the sub
> function (if any) and if error print the documentation string.
>
> The concept is to get the user quick help to resolved
> the error with the arguments.
>
> Maybe the best way would be to have one function doing
> the print of the NAME and result and if error the documentation.
> Let say the function name would be DIAGNOSE-QUIETLY.
> But I can't find the way to work. Therefore I use
> one function for NAME and marcro function for error.
>
> the use would be like:
>
>
> (defun sum (n)
>
>
> "SUM (numbers)
>
>
> Returns the sum of the elements in a series of numbers.
>
>
> Examples:
>
>
> (sum '(1 2 3 4))
>
>
> (sum '(1 2 3 -4))"
>
>
> (diagnose-quietly 'sum
>
>
> (reduce #'+ n)))
>
>
>
>
>
>
>
>
>
>
> For now, I am getting Stack overflow.
>
> (sum '(1 2 3 y))
> ERROR! Check parameters.
> > Error: Stack overflow on value stack.
> > While executing: symbol-package, in process Listener(13).
> > Type cmd-. to abort, cmd-\ for a list of available restarts.
> > Type :? for other options.
> 1 >
>
> Janusz
> --
> MRAC Publishing
> Janusz Podrazik
>
>
> On Wednesday, 22 June 2011 at 01:16, Pascal J. Bourguignon wrote:
>
> > Janusz Podrazik <info at mracpublishing.com (mailto:info at mracpublishing.com)> writes:
> >
> > > What I am trying to do is to include function documentation from the
> > > string to the error print.
> > >
> > > (defMacro do-quietly (name &body body) ; with name
> > > `(let ((temp diagnose-verbose)
> > > (return-value nil))
> > > (handler-case
> > > (progn
> > > (setq diagnose-verbose nil)
> > > (setq return-value (progn ,@@body))
> > > (setq diagnose-verbose temp)
> > > return-value)
> > > (error (c)
> > > (princ ""ERROR! Check Arguments.")
> > > (princ (documentation name 'function))
> > > (print c)
> > > (setq diagnose-verbose temp)
> > > (abort)))))
> > >
> > > (defun collect-sum (n)
> > > "COLLECT-SUM (numbers)
> > > Returns the sum of the elements in a series of numbers.
> > > Examples:
> > > (collect-sum '(1 2 3 4)
> > > (collect-sum '(1 2 3 -4))"
> > > (do-quietly 'collect-sum ;function name
> > > (reduce #'+ n)))
> > >
> > > 4 > ERROR! Check Arguments.
> > > > Error: Unbound variable: name
> > > > While executing: collect-sum, in process Listener(13).
> > > > Type cmd-. to abort, cmd-\ for a list of available restarts.
> > > > Type :? for other options.
> > >
> > > whats wrong?
> >
> > You wrote a macro that generates code that makes reference to a variable
> > named NAME, while no such variable exist.
> >
> > The parameters of the macros are known at compilation time only, when
> > macro expansion occurs. At run time, the macro doesn't exist anymore,
> > and neither do its parameters.
> >
> > So you need to insert the name of the function in the code generated:
> >
> > `... (princ (documentation ',name 'function)) ...
> >
> > (Remember some function names are lists, so you must quote it for those
> > cases).
> >
> >
> > Now, your macro has a lot of problems:
> >
> > (defmacro do-quietly (name &body body)
> > `(let ((temp diagnose-verbose)
> > (return-value nil))
> > (handler-case
> > (progn
> > (setq diagnose-verbose nil)
> > (setq return-value (progn , at body))
> > (setq diagnose-verbose temp)
> > return-value)
> > > (error (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c)
> > (setq diagnose-verbose temp)
> > (abort)))))
> >
> > What's this free variable diagnose-verbose??
> > If that's a special variable, it should be named *diagnose-verbose*.
> > In that case, you can just use a dynamic binding to shadow its value:
> >
> > (defmacro do-quietly (name &body body)
> > `(let ((return-value nil))
> > (handler-case
> > (let ((*diagnose-verbose* nil))
> > (setq return-value (progn , at body))
> > return-value)
> > (error (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c)
> > (abort)))))
> >
> > Then, bodies may return several values, are you sure you want to throw
> > away all but the first? In any case, you should not use SETQ, but LET:
> >
> > (defmacro do-quietly (name &body body)
> > ``(handler-case
> > (let ((*diagnose-verbose* nil))
> > (let ((return-value (progn ,@@body)))
> > return-value))
> > (error (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c)
> > (abort))))
> >
> > If you wanted to return only the first value, it might be clearer to use
> >
> > (values (progn , at body)) ; values returns as many values as
> > ; arguments it is given, so we see only
> > ; one value is returned here.
> >
> > or even:
> >
> > (nthh-value 0 (progn , at body)) ; explicitely return just the first value.
> >
> >
> > So if I wanted to throw away the other values of the body, I'd write:
> >
> > (defmacro do-quietly (name &body body)
> > `(handler-case
> > (let ((*diagnose-verbose* nil))
> > (values (progn ,@@body)))
> > (error (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c)
> > (abort))))
> >
> > but there's really no reason to do it in general, so let's just let body
> > return all its values:
> >
> > (defmacro do-quietly (name &body body)
> > `(handler-case
> > (let ((*diagnose-verbose* nil))
> > , at body)
> > (error (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c)
> > (abort))))
> >
> >
> >
> > On the other hand, diagnose-verbose could be a symbol macro, in which
> > case you'd have to use #+clisp ext:letf to bind it instead of cl:let,
> > ext:letf expands to something like:
> >
> > (let ((saved-value diagnose-verbose))
> > (unwind-protect
> > (progn (setf diagnose-verbose nil)
> > (do-something))
> > (setf diagnose-verbose saved-value)))
> >
> > so you'd write something similar:
> >
> > (defmacro do-quietly (name &body body)
> > (let ((saved-variable (gensym "SAVED-VALUE-")))
> > `(handler-case
> > (let ((,saved-variable diagnose-verbose))
> > (unwind-protect
> > (progn
> > (setf diagnose-verbose nil)
> > ,@@body)
> > (setf diagnose-verbose ,saved-variable)))
> > (errror (c)
> > (princ "ERROR! Check Arguments.")
> > (princ (documentation ',name 'function))
> > (print c))
> > (abort)))))
> >
> >
> >
> >
> >
> > It is better to use princ for the condition too, if you want a human
> > readable error message. You could also use format:
> >
> > (defmacro do-quietly (name &body body)
> > `(handler-case
> > (let ((*diagnose-verbose* nil))
> > , at body)
> > (error (err)
> > (format t ""ERROR! Check Arguments. ~&~A~%~A~%"
> > (documentation ',name 'function) err)
> > (abort))))
> >
> > Finally, are you sure you want to call ABORT here? This will probably
> > stop the execution of your program, since I doubt yyou installed an ABORT
> > restart. It might be better to not call ABORT, and let the program run
> > other tests. You may also want to enter the debugger to better explore
> > why the form failed, in the context (you'd rather use HANDLER-BIND in
> > this case thought). Or if you just wanted to issue the message, you
> > could also re-signal the error (ERROR ERR), so that the next handler has
> > a chance of handling it too.
> >
> >
> > --
> > __Pascal Bourguignon__ http://www.informatimago.com/
> > A bad day in () is better than a good day in {}.
> >
> > _______________________________________________
> > Openmcl-devel mailing list
> > Openmcl-devel at clozure.com (mailto:Openmcl-devel at clozure.com)
> > http://clozure.com/mailman/listinfo/openmcl-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20110622/510509c2/attachment.htm>
More information about the Openmcl-devel
mailing list