Wilfred / suggest.el

discover elisp functions that do what you want
367 stars 14 forks source link

Undefined reference to it. #11

Closed MatthewRock closed 8 years ago

MatthewRock commented 8 years ago

I downloaded the mode today from melpa and tried running it, but unfortunately I get undefined reference to the "it" variable. The version of suggest is 20160807.1830 and my emacs version is 24.4.1.

Wilfred commented 8 years ago

You probably have an old version of dash.el or loop.el.

Could you try M-x toggle-debug-on-error and running again? This will give you a backtrace, please paste that in this issue :)

MatthewRock commented 8 years ago

After running M-x suggest I got:

Debugger entered--Lisp error: (void-variable it) suggest--permutations(((1 #("1" 0 1 (fontified nil))) (2 #("2" 0 1 (fontified nil))))) suggest--possibilities((#("1" 0 1 (fontified nil)) #("2" 0 1 (fontified nil))) (1 2) 3) suggest-update() suggest()

(suggest record nil)

ad-Advice-call-interactively(# suggest record nil) apply(ad-Advice-call-interactively # (suggest record nil)) call-interactively(suggest record nil) command-execute(suggest record) helm-M-x(nil "suggest")

(helm-M-x nil nil)

ad-Advice-call-interactively(# helm-M-x nil nil) apply(ad-Advice-call-interactively # (helm-M-x nil nil)) call-interactively(helm-M-x nil nil) command-execute(helm-M-x)

I see that I didn't need to call anything since suggest tries to show suggestion for the "test set".

Wilfred commented 8 years ago

Thanks.

OK, so it's complaining about suggest--permutations, which uses --each and --each-indexed. Both of these define an it variable.

--each-indexed was only added in dash.el 2.13: https://github.com/magnars/dash.el#from-212-to-213 so I'd guess you're missing that. What version of dash.el do you have?

yrns commented 8 years ago

FWIW, I got the same error with dash 2.13. Still trying to figure out why.

Wilfred commented 8 years ago

@yrns are you getting the same traceback? Could you try deleting ~/.emacs.d/elpa/suggest*/*.elc?

yrns commented 8 years ago

@Wilfred I was getting the same stack trace, yes. Deleting the *.elc files worked. How did this happen? This was the first time I installed it. I used paradox.

BTW, this is very cool!

Wilfred commented 8 years ago

Deleting the *.elc files worked. How did this happen?

Tricky! Here's what I think happened:

To generate a .elc, Emacs expands all the macro calls, then converts the resulting source code to bytecode. This requires it to know which forms are macros. It assumes that unknown forms are function calls.

As an example, define a standalone function in a file foo.el:

(defun wh-example-func ()
  (wh-with-it
   (+ it 1)))

Now M-x byte-compile-file RET foo.el, M-x load-file RET foo.elc, then M-x disassemble RET wh-example-func:

byte code for wh-example-func:
  args: nil
0       constant  wh-with-it
1       varref    it
2       add1      
3       call      1
4       return    

We can see Emacs will try to evaluate it before calling wh-with-it, causing the error Symbol's value as variable is void: it

We're now doomed, defining a wh-with-it macro won't help us unless we byte-compile again afterwards.

Interpreted code is different. We define our function again:

(defun wh-example-func2 ()
  (wh-with-it2
   (+ it 1)))

And evaluate with M-x eval-buffer then M-: (wh-example-func2). This errors: Symbol's function definition is void: wh-with-it2.

However, if we define the macro it wants in a separate buffer:

(defmacro wh-with-it2 (form)
  `(let ((it 1))
     ,form))

and M-x eval-buffer, M-: (wh-example-func2), then we get the answer 2. Our macro is evaluated at runtime. This is Emacs using 'lazy macro expansion'. It usually does 'eager macro expansion' but it couldn't in our case, because wh-with-it2 was not defined when we evaluated wh-example-func2.

TL;DR: Byte-compiling files doesn't work if you don't have the necessary macros.

Wilfred commented 8 years ago

I suspect @MatthewRock had the same issue. @MatthewRock please make sure you have the latest dash.el, and delete any ~/.emacs.d/elpa/suggest*/*.elc files. Given this, I'm going to close this issue.

Do let me know if you hit further issues.

MatthewRock commented 8 years ago

Actually I am running emacs as a daemon. I upgraded some packages, probably one including the macros, and something must have went wrong(version mismatch?); after restarting the daemon, everything runs ok. Thanks for help though.