1

The beginning of my ~/.emacs.d/init.el file looks like this:

;; MELPA
(require 'package)
(setq package-enable-at-startup nil)
(setq package-check-signature nil)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("elpy" . "https://jorgenschaefer.github.io/packages/"))

;; boostrap 'use-package'
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(use-package windmove
  ;; move cursor between windows
  :demand
  :bind
  (("C-<left>" . windmove-left)
   ("C-<right>" . windmove-right)
   ("C-<up>" . windmove-up)
   ("C-<down>" . windmove-down)))

... more stuff ...

I am trying to byte compile my init.el file. I execute the following in the terminal, sinde the ~/.emacs.d/ directory:

$ emacs --batch --eval '(byte-compile-file "init.el")'

The output is:

In toplevel form:
init.el:59:1:Warning: ‘("C-<left>" . windmove-left)’ is a malformed function
init.el:59:14:Warning: reference to free variable ‘windmove’
init.el:62:3:Error: Wrong type argument: sequencep, windmove-right

Basically, the very first key binding definition fails... and there is also some sort of warning about a free variable. How do I properly byte-compile the init.el file - even for the above very simple example (imagine there's nothing else to the init.el file)?

2 Answers 2

1

Your code is missing a (require 'use-package); without that, Emacs gets confused about use-package and treats it as a function instead of a macro.

-1

A guess is that you need to quote the list after :bind:

'(("C-<left>" . windmove-left)
  ("C-<right>" . windmove-right)
  ("C-<up>" . windmove-up)
  ("C-<down>" . windmove-down))

The error message tells you that the compiler is trying to evaluate this as a functional application:

(("C-<left>" . windmove-left)
 ("C-<right>" . windmove-right)
 ("C-<up>" . windmove-up)
 ("C-<down>" . windmove-down))

That is, it's looking at that as an application of the "function" ("C-<left>" . windmove-left) to the arguments that are the other elements of that list. It looks as the list as (FUNCTION ARG1 ARG2 ARG3).

Because it's trying to evaluate the list instead of taking it as data (i.e., as a list), I assume you need to quote it ('). Quoting it prevents evaluation of the list itself; evaluating a quoted list just returns the list.

UPDATE

Well, I don't use use-package, and know nothing about it. I just know that the error message means the list you have is being interpreted as a functional application. But looking at other questions about use-package with :bind I see that the list after :bind is not supposed to be quoted.

So another guess is that you're missing something after :demand, so that :demand is acting on :bind, and so the list after :bind is evaluated.

(Just another guess...)

And finding other examples, it seems that what you're missing after :demand is t:

(use-package windmove
  ;; move cursor between windows
  :demand t
  :bind
  (("C-<left>" . windmove-left)
   ("C-<right>" . windmove-right)
   ("C-<up>" . windmove-up)
   ("C-<down>" . windmove-down)))

In sum, each of the keywords (:demand and :bind) needs to be followed by a value. Because :demand was missing its value (t) the compiler took the :bind after it as the value of :demand. And after that there was no keyword but just a list. And that got evaluated as a functional application.

2
  • Unfortunately this does not seem to fix the issue (adding :demand t). But interesting observation... Aug 27, 2020 at 17:07
  • Just an FYI. The t after :demand, and indeed many other forms like :ensure, are not necessary.
    – Joe
    Apr 6, 2021 at 3:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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