6

I have this function:

(defun uikit-autolayout (stackview)
  "Ask STACKVIEW to auto layout."
  (let* ((orientation-index (pcase (uikit--orientation-of stackview)
                              ('left 0) ; rotate clockwise 0 degree
                              ('bottom 1) ; rotate 90 degree
                              ('right 2) ; 180 degree
                              ('top 3))) ; 270 degree
         (last-left (byte-compile (lambda (SELF) (ignore SELF) (uikit-left-of stackview))))
         (space-func (pcase (uikit--autolayout-of stackview)
                       ('stacking (byte-compile (lambda () (uikit--stacking-space-of stackview))))
                       ('equal-spacing #'uikit-equal-spacing-space-of)))
         (top-func (pcase (uikit--v-align-of stackview)
                     ('top (lambda (SELF) (uikit-top-of (uikit--parent-stackview-of SELF))))
                     ('center (lambda (SELF)
                                (+ (uikit-top-of (uikit--parent-stackview-of SELF))
                                   (/ (- (uikit--max-subview-height (uikit--parent-stackview-of SELF))
                                         (uikit-content-height-of SELF)) 2))))
                     ('bottom (lambda (SELF)
                                (- (uikit-bottom-of (uikit--parent-stackview-of SELF))
                                   (uikit-content-width-of SELF)))))))
    (let ((uikit-left-of (nth orientation-index '(uikit-left-of uikit-bottom-of uikit-right-of uikit-top-of)))
          (uikit-bottom-of (nth orientation-index '(uikit-bottom-of uikit-right-of uikit-top-of uikit-left-of)))
          (uikit-right-of (nth orientation-index '(uikit-right-of uikit-top-of uikit-left-of uikit-bottom-of)))
          (uikit-top-of (nth orientation-index '(uikit-top-of uikit-left-of uikit-bottom-of uikit-right-of))))
      ;; ??? unused lexical variable xxx
      (ignore last-left space-func top-func uikit-left-of uikit-bottom-of uikit-right-of uikit-top-of)
      ;; during the drawing process `uikit-<constrain>-of' will be
      ;; bind to another function that calculates the constrain into
      ;; actual number and saves to cache
      (dolist (subview (uikit--subview-list-of stackview))
        ;; autolayout yourself if you are a stackview
        (when (cl-typep subview 'uikit-stackview)
          (uikit-autolayout subview))
        ;; set your parent
        (setf (uikit--parent-stackview-of subview) stackview)
        ;; set your left to the right of the previous view
        (uikit-left-of subview last-left)
        (setq last-left (byte-compile (lambda (SELF) (ignore SELF)
                                        (+ (uikit-right-of subview)
                                           (funcall space-func)))))
        ;; top & bottom
        (uikit-top-of subview top-func)))))

When I run it, following warnings pop up:

Warning: Unused lexical variable ‘orientation-index’
Warning: Unused lexical variable ‘orientation-index’
Warning: Unused lexical variable ‘last-left’
Warning: Unused lexical variable ‘stackview’
Warning: Unused lexical variable ‘orientation-index’
Warning: Unused lexical variable ‘last-left’
Warning: Unused lexical variable ‘top-func’
Warning: Unused lexical variable ‘uikit-left-of’
Warning: Unused lexical variable ‘uikit-bottom-of’
Warning: Unused lexical variable ‘uikit-right-of’
Warning: Unused lexical variable ‘uikit-top-of’
Warning: Unused lexical variable ‘--dolist-tail--’
Warning: Unused lexical variable ‘stackview’
Warning: Unused lexical variable ‘orientation-index’
Warning: Unused lexical variable ‘last-left’
Warning: Unused lexical variable ‘top-func’
Warning: Unused lexical variable ‘uikit-left-of’
Warning: Unused lexical variable ‘uikit-bottom-of’
Warning: Unused lexical variable ‘uikit-right-of’
Warning: Unused lexical variable ‘uikit-top-of’

All these variables are those I declared in let binding, and I used them (except uikit-left/top/bottom/right-of). I tried to "use" then with a ignore call, but that doesn't help.

Why am I getting these warnings and how can I fix the problem?

P.S. When I byte compile the file, everything is fine, no warnnings.


UPDATE:

As Stefan and Phill says, when I remove the byte-compile function it doesn't show warnings anymore. And yes, I don't really need to use byte-compile the first place. Thanks! It's interesting that byte-compile compiles closures back into lambda, I never thought it will do that sort of thing.

4
  • 1
    If you remove all the (byte-compile ...) wrappers, I presume the warnings go away?
    – phils
    Oct 9, 2018 at 6:10
  • 1
    The byte-compiler is telling you about the lexical variables which are not used in the anonymous functions being compiled at run-time. (lambda (SELF) (ignore SELF) (uikit-left-of stackview)) uses stackview but not orientation-index, which is where the first warning comes from. You can follow the rest of the sequence from there...
    – phils
    Oct 9, 2018 at 6:17
  • 2
    I don't think there's a purpose to byte-compiling those lambdas at run-time, if you are byte-compiling the whole library? Was there a reason why you did that? I'm sure someone will correct me if I'm missing something, but if the file is compiled then the (implicitly function-quoted) lambdas will be byte-compiled, and those compiled functions are what will be loaded and used at run-time.
    – phils
    Oct 9, 2018 at 7:33
  • 2
    (lambda (SELF) (ignore SELF) ...) with SELF not otherwise used is pointless. I guess this was the "I tried to 'use' them with an ignore call" part? Prefix unused parameters with an underscore, and the byte-compiler will ignore them. (lambda (_SELF) ...)
    – phils
    Oct 9, 2018 at 7:34

1 Answer 1

7

Here's the reason why you get those warnings when you don't byte-compile the file:

My crystal ball tells me this Elisp code is within a file marked as -*- lexical-binding:t -*- (which is a good thing). When the Elisp interpreter evaluates a lambda in this mode, it creates a closure without looking at the body of the lambda so the closure conservatively remembers the whole environment. In your case, for example, the function

(lambda (SELF) (ignore SELF) (uikit-left-of stackview))

will be evaluated to a closure of the form

(closure ((orientation-index . N) ...)
         (SELF)
         (ignore SELF) (uikit-left-of stackview))

where the first element is the environment (aka context) which lists all the surrounding lexically-scoped vars and their respective value.

When you ask the byte-compiler to compile this closure, you're asking it to do something it's not really capable of doing (it's designed to take source code as input, not pre-evaluated values like closures), and the way it handles this case is to turn the closure back into some more-or-less-equivalent source code (this is done in byte-compile--reify-function), more specifically it turns it into:

(lambda (SELF)
  (let ((orientation-index N)
        ...)
    (ignore SELF) (uikit-left-of stackview)))

and then compiles this code. If you look at byte-compile--reify-function it has a FIXME exactly for the problem you mention:

    ;; We check shadowing by the args, so that the `let' can be moved
    ;; within the lambda, which can then be unfolded.  FIXME: Some of those
    ;; bindings might be unused in `body'.

but since byte-compile is something used very rarely (and even more rarely in circumstances like yours), this is rather low priority: in 99.99% of the cases, the better fix is to not use byte-compile.

As you saw, byte-compiling the file removes the problem because in that case byte-compile receives as argument a function that's already compiled so it returns it without doing anything at all.

4
  • 1
    While useful in explaining the issue, I'd be interested to know how to fix these warnings.
    – ideasman42
    May 16, 2019 at 5:12
  • @ideasman42, the fix was mentioned already: don't manually call byte-compile on such values (intead, you want to byte-compile the whole file, which will also byte-compile this function but with better knowledge of what's going on).
    – Stefan
    May 16, 2019 at 12:20
  • 1
    I'm byte compiling the entire file, it's still giving the error.
    – ideasman42
    May 16, 2019 at 12:27
  • @ideasman42: then it's a completely different problem from the one discussed here (and BTW, these things are not errors but warnings)
    – Stefan
    May 16, 2019 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.