EmacsGolf 4

Xah Lee is doing some refactoring and wants to change this

;; define several class of keywords

(defvar mylsl-keywords
  '("break" "default" "do" "else" "for" "if" "return" "state" "while")
  "LSL keywords.")

(defvar mylsl-types
  '("float" "integer" "key" "list" "rotation" "string" "vector")
  "LSL types.")

(defvar mylsl-constants
  "LSL constants.")

(defvar mylsl-events
  '("at_rot_target" "at_target" "attach")
  "LSL events.")

(defvar mylsl-functions
  '("llAbs" "llAcos" "llAddToLandBanList" "llAddToLandPassList")
  "LSL functions.")

into this

;; define several class of keywords

(defvar mylsl-keywords nil "LSL keywords.")
(setq mylsl-keywords '("break" "default" "do" "else" "for" "if" "return" "state" "while") )

(defvar mylsl-types nil "LSL types.")
(setq mylsl-types '("float" "integer" "key" "list" "rotation" "string" "vector"))

(defvar mylsl-constants nil "LSL constants.")
(setq mylsl-constants '("ACTIVE" "AGENT" "ALL_SIDES" "ATTACH_BACK"))

(defvar mylsl-events nil "LSL events.")
(setq mylsl-events '("at_rot_target" "at_target" "attach"))

(defvar mylsl-functions nil "LSL functions.")
(setq mylsl-functions '("llAbs" "llAcos" "llAddToLandBanList" "llAddToLandPassList"))

His first inclination was to just brute force it with cut and paste and some typing but then he asked himself what he would do if he had hundreds of lines like this to fix. I can think of at least two efficient ways to do this. What would you do?

This entry was posted in General and tagged . Bookmark the permalink.
  • looking at this now, i probably would use query-replace-regexp.

    here's regex

    (defvar [^<br />

    here's replacement.

    (defvar \1 nil "\3")
    (setq \1 '(\2))

    the other way is key macros. Then call apply-macro-to-region-lines. Would be interesting to see what others comes up. Now it doesn't seem a interesting problem. ha.

    if one of the string contains paren, then regex won't work, key macro still do. I think key macro here is interesting because it relies on a uniquely emacs feature of selecting sexp.

    • Sorry, scratch the apply-macro-to-region-lines. Don't think it'd work here. instead, in macro, search for next "(defvar" to go to the next item.

  • Phil

    I'm just curious as to why that change would be desirable. Is there other code setting those variables before you have defvar'd them, causing the init value to be ignored?

    And surely if this new code executes in the context of a buffer with buffer-local values, you would be setting those, and not affecting the global values. Perhaps that's never going to happen in this case, but it still seems to make this a dangerous pattern to be using?

    • hi phil, i made the change because i was getting annoyed when developing a package, eval the package doesn't change defvar variables.

      i wrote about it here

      〈Emacs Lisp “defvar” Doesn't Override〉

      what do you think of defcustom?

      • Phil

        Ah, I see. Yes, I've run into that situation as well, but always just dealt with it manually as I tweaked the values. I don't feel that the explicit setq is the right solution, for aforementioned reasons.

        Maybe we could utilise some advice for defvar in conjunction with a directory-local variable for your development files?

        (defadvice defvar (after my-devel-defvar-reset)
        (when (and (memq this-command '(eval-buffer eval-region))
        (local-variable-p 'my-devel-defvar-reset)
        (ad-get-arg 1))
        (set (ad-get-arg 0) (ad-get-arg 1))))

        (ad-activate 'defvar)

      • Phil

        I'll note that if you were to eval-buffer a library which required other currently-unloaded libraries, that's going to kick in for other code as well. I'm not sure if/how you could guarantee to isolate the behaviour to the original buffer. I've never tried to mess with the eval system before.

        As for defcustom, while that's certainly the appropriate thing to use for user settings, the same issue will arise with that as for defvar (for the same reasons).

        • Nice code on defadvice. I haven't looked into defadvice in detail.

          i get a sense many find setq after defvar very bad. The way i thought is that defvar is just a declaration to make source code more readable and with inline doc for vars. So, emacs's behavior was strange for me.

          the issue of overriding user def didn't occur to me until you and g+ lispers pointed it out.

          but still, today we have defcustom. So i don't quite see setq after defvar is bad. It is bad in the context of older code. Are there other reason you are thinking? was emacs doc telling developers to use defvar? (real question)