3

A lot of emacs configurations shared publicly have this format:

;; 01-something.el
(provide 'something)

;; init.el
(require 'something)

Suppose I'm writing a defun named "s-join" inside 01-something.el

Suppose somewhere during init.el initialization, magit.el loads up s.el - the popular string utility package, which also has a defun named "s-join"

So now, in any given context, how do I know what gets executed when I do

(s-join)

?

1
  • OT detail: file 01-something.el should provide feature 01-something, not (only) something. Oct 13, 2020 at 21:51

3 Answers 3

5

All functions and variables defined in a file that gets loaded are put into the global environment. Although Emacs has installable packages, those packages are not isolated from each other in any way. If two files define functions or variables with the same name then you'll get a warning when the second one is loaded.

You can find out where a function was defined by asking for help on the function with C-h f. It will prompt you for a function name. If the text at point looks like a valid lisp identifier, and a function by that name exists, that identifier will be the default value for the prompt. C-h v will do the same for variables. C-h F prompts for a function name and takes you to the info page where that function is documented, which may include more detailed information.

4
  • I’m a vim guy, but I thought emacs got lexical scoping at one point; wouldn’t this obviate some of that? Oct 8, 2020 at 0:09
  • 1
    Emacs implements both lexical and dynamic scoping, but that's for the code inside of functions. Function and variable definitions happen in the global environment.
    – db48x
    Oct 8, 2020 at 2:31
  • how do I ensure my function named "s-join" does not clash with the function of the same name from the s.el package Oct 10, 2020 at 14:38
  • 2
    Simply use a name not currently used by any other package. The convention is that every package should start the name of every function with the package name. Thus package foo will define functions foo-frob-the-thing and foo-compute-barness, while package bar will define functions like bar-frob-the-other-thing and so on. For functions you define in your init file, you might consider using your own name as the prefix. For example, I have a function called db48x/erc-generate-log-file-name-long-date in mine, because that seemed like a good name at the time.
    – db48x
    Oct 10, 2020 at 14:44
1

In Elisp, all functions names normaly (but not necessarily) reside as an entry in a global environment (obarray). In Elisp functions can be redefined. Which means the function definition which has been evaled (or loaded) last will be the only one, which is known and used.

This way you can change functions in your init file, you just need to be sure your function definition is evaled after the function you want to change.

But beware! If the original function changes in behavior or parameters, yours is not changing automatic, and so dependend functions could fail or misbehave.


Replying to those comments below, on how to avoid failure of using source code.

  1. you should choose a function name which is unique to your own function to prevent this (i.e. prefix your function name)
  2. you could write a guard around your function, to prevent your function definition overwriting some existing function (this does not help if your function gets overwritten, see next point)
(unless (fboundp 's-join)
  (defun s-join ()
    ...))
  1. you could use an advice at your function, and there check for characteristics of your function (i.e. parameters, or first sexp in body, etc.) IMO advices stay put even when the function gets redefined.
4
  • how do I ensure my function named "s-join" does not clash with the function of the same name from the s.el package Oct 10, 2020 at 14:38
  • What do you mean by clash? The last definition simply redefines (aka overwrites) a previous definition. Any functioncalls which use the older definition might then simply fail.
    – jue
    Oct 11, 2020 at 9:39
  • you used the word fail - so failure is what I'm trying to avoid. Oct 12, 2020 at 13:52
  • @american-ninja-warrior I tried to guess what you want, see updated answer.
    – jue
    Oct 13, 2020 at 21:29
1

OP seems to be missing the point already clearly made in the two answers given: you cannot do what you are asking. Emacs uses a voluntary naming convention, not syntax or compilation rules, to define namespaces. It may sound like a recipe for chaos, but in practice it works very well.

What you are doing when you name your function s-join is (effectively) stealing the s package's namespace-identifying prefix, in breach of the convention. Don't do that. Name your function anw/join-strings or similar, as suggested above.

If you really, really need to temporarily replace an existing function, you can use cl-flet or cl-labels. See the Info node for the CL package.

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.