1

I have a list of interactive functions and want to call a random one of them. In the end I expect to have a function that randomly changes the capitalization of the word at point (without moving the point).

I tried my best but did not get it to work.

The functions

Here are three functions that change the word at point in different ways. (They might behave unexpectedly when point is at the beginning of the word, but we won't worry about that now)

(defun upcase-word-without-moving ()
  "Convert the word at point to uppercase."
  (interactive)
  (save-excursion
    (backward-word)
    (upcase-word 1)
    ))

(defun downcase-word-without-moving ()
  "Convert the word at point to lowercase."
  (interactive)
  (save-excursion
    (backward-word)
    (downcase-word 1)
    ))

(defun capitalize-word-without-moving ()
  "Convert the word at point to be capitalized."
  (interactive)
  (save-excursion
    (backward-word)
    (capitalize-word 1)
    ))

get a random element of a list

(defun random-element-of-list (items)
  (let* ((size (length items))
         (index (random size)))
    (nth index items)))

I tried out this function and it works as expected:

(random-element-of-list '("a" "b" "c"))
(random-element-of-list '('upcase-word-without-moving 'downcase-word-without-moving 'capitalize-word-without-moving))

Put it all together

That should be easy, right? Have a list of the functions, pick a random element of that list and call it as a function.

(defun change-capitalisation-of-word-1 ()
  (interactive)
  (funcall (random-element-of-list '('upcase-word-without-moving 'downcase-word-without-moving 'capitalize-word-without-moving)))
  )

Trying this gives me one of three error messages:

  • Invalid function: 'upcase-word-without-moving
  • Invalid function: 'downcase-word-without-moving
  • Invalid function: 'capitalize-word-without-moving

I don't understand why this is. The emacs-manual on invalid function is a bit heavy on the theory for a lisp-beginner. It also doesn't seem to offer a simple solution.

So I tried changing some things. For example I tried to bind the selected function to a variable:

(defun change-capitalisation-of-word-2 ()
  (interactive)
  (let ((fun-to-call (random-element-of-list '('upcase-word-without-moving 'downcase-word-without-moving 'capitalize-word-without-moving))))
    (funcall fun-to-call)
    )
  )

This code has same problem with the same error messages.

I then tried to leave out the randomness and just use one of the three functions directly.

(defun change-capitalisation-of-word-3 ()
  (interactive)
  (let ((fun-to-call 'upcase-word-without-moving)) ;; constant
    (funcall fun-to-call)
    )
  )

This works as expected (but obviously doesn't solve my problem, it is the random selection of the function that I am after).

So I would like to know:

  • How I can make my function change-capitalisation-of-word work?
  • Is there a fundamental mistake I made or a concept I was not aware of?
2

You have double-quoted your function symbols. The sexp '(symbol1 symbol2) is a list of two symbols: symbol1 and symbol2. The sexp '('symbol1 'symbol2) is a list of two symbols 'symbol1 and 'symbol2. Note that the error message you get, "Invalid function: 'upcase-word-without-moving" tells you that emacs is trying to call the function 'upcase-word-without-moving, not upcase-word-without-moving.

1
  • 1
    Thank you. As always in programming the problem is hard to spot for a beginner and lies in a single letter. I ended up with: ``` (defun change-capitalisation-of-word () (interactive) (funcall (random-element-of-list '(upcase-word-without-moving downcase-word-without-moving capitalize-word-without-moving))) ) ```
    – Kaligule
    Aug 25 at 13:45

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.