make-translator-fun

Paul Werkowski pw at snoopy.qozzy.com
Sun Jan 10 15:13:04 UTC 2021


The context for my post was this:

(define-presentation-to-command-translator xlate-set-lcursor
     (clim:blank-area com-set-cursor plotter
                      :documentation "Set Left Cursor"
                      :gesture :select
                      :tester ((object window)
                               (declare (ignore object))
                               (typep window 'basic-chart-pane)))
     (object x y window)
   (%set-a-cursor (chart-pane-chart window) 'lcursor x y window))

where originally I omitted 'object' from the next to last line resulting 
in the wrong values being presented to the %set-a-cursor function. User 
error on my part but LispWorks CLIM2 did what I expected anyway thus 
keeping me ignorant of my omission. Perhaps LW was able to infer what I 
wanted.

On 1/10/2021 2:45 AM, Lauren P wrote:
> Hey,
>
> On Sat, Jan 9, 2021, 11:21 Paul Werkowski <pw at snoopy.qozzy.com 
> <mailto:pw at snoopy.qozzy.com>> wrote:
>
>     (defun make-translator-fun (args body)
>        (cond ((null args)
>               (warn "OBJECT parameter is obligatory (adding ignored
>     parameter)")
>               (let ((object-arg (gensym "OBJECT-ARG")))
>                 `(lambda (,object-arg &key &allow-other-keys)
>                    (declare (ignore ,object-arg))
>                    , at body)))
>              (t
>               `(lambda (,(car args) &key ,@(cdr args) &allow-other-keys)
>                  (declare (ignorable ,(car args)))
>                  , at body))))
>
>     I guess the above does the right thing if ARGS is NIL but won't catch
>     the case of ARGS incorrectly given as, for instance, (x y window)
>     instead of (object x y window).
>
> I would give it an explicit parameter so it takes (OBJECT-ARG ARGS 
> BODY) so autodoc shows where the object argument goes without having 
> to remember to read the docstring.
>
> I'd put in a destructuring bind at the T case and then test that... it 
> should bomb in the compiler if you pass it (NIL X Y WINDOW) as-is: 
> you'll need to gensym and DECLARE IGNORE if it's a NIL.
>
> If you wrap it in a macro the way I write that lambda list is 
> ((OBJECT-ARG &REST ARGS) &BODY BODY); it is displayed by autodoc and 
> the destructuring bind catches it at compile time. If you really want 
> to accept a no arguments form, I tend to use NAME* for the alternative 
> form and make it a wrapper stub, otherwise I prefer to assume "forgot 
> arguments" and error.
>
> I wouldn't set the object argument ignorable in the T case unless it 
> was typed in as NIL, as it can hide bugs in the body code. Better to 
> let the user specify ignorable in the BODY if they are sure they don't 
> need it.
>
> (More of a style thing, I find it cleaner to normalize the argument 
> list to replace the empty list with (NIL) so it works with 
> destructuring bind: you can get rid of the main branch and only type 
> the bulk of the code once, since you need to check for a gensym and 
> ignore declaration in the T case as well. Also, leave out 
> &ALLOW-OTHER-KEYS unless absolutely necessary... I've found it makes 
> it exceedingly difficult to catch typos.)
>
> Hope this is useful for you!
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/mcclim-devel/attachments/20210110/30c2eee0/attachment.html>


More information about the mcclim-devel mailing list