[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