skeeto / emacs-aio

async/await for Emacs Lisp
The Unlicense
218 stars 12 forks source link

Assertion failed on emacs 26.3 #4

Closed canatella closed 5 years ago

canatella commented 5 years ago

So I'd like to use aio for a personal project on Emacs 26.3, but I cannot use aio-defun. I suppose I must be missing something: evaluating

(aio-defun divide-safe (a b)
  (condition-case error
      (aio-await (divide a b))
    (arith-error :arith-error)))

Gives

Debugger entered--Lisp error: (cl-assertion-failed (lexical-binding nil))
  cl--assertion-failed(lexical-binding)
  #f(compiled-function (arglist &rest body) "Return a lambda generator.\n`iter-lambda' is to `iter-defun' as `lambda' is to `defun'." #<bytecode 0x44a9f0c1>)((a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))
  macroexpand((iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) nil)
  macroexp-macroexpand((iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) nil)
  macroexp--expand-all((iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))))
  macroexp--all-forms((apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) args) 1)
  #f(compiled-function (form func) #<bytecode 0x400a9353>)(((apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) args)) apply)
  macroexp--expand-all((apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) args))
  macroexp--all-forms((iter (apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) args)) 1)
  macroexp--all-clauses(((promise (aio-promise)) (iter (apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await ...) (arith-error :arith-error)))) args))) 1)
  #f(compiled-function (form body bindings fun) #<bytecode 0x400a9393>)(((let* ((promise (aio-promise)) (iter (apply (iter-lambda (a b) (aio-with-promise promise ...)) args))) (prog1 promise (aio--step iter promise nil)))) ((prog1 promise (aio--step iter promise nil))) ((promise (aio-promise)) (iter (apply (iter-lambda (a b) (aio-with-promise promise (condition-case error (aio-await ...) (arith-error :arith-error)))) args))) let*)
  macroexp--expand-all((let* ((promise (aio-promise)) (iter (apply (iter-lambda (a b) (aio-with-promise promise (condition-case error ... ...))) args))) (prog1 promise (aio--step iter promise nil))))
  macroexp--all-forms((lambda (&rest args) (let* ((promise (aio-promise)) (iter (apply (iter-lambda (a b) (aio-with-promise promise ...)) args))) (prog1 promise (aio--step iter promise nil)))) 2)
  macroexp--expand-all((aio-lambda (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))
  macroexp--all-forms((defalias (quote divide-safe) (aio-lambda (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error)))) 1)
  #f(compiled-function (form func) #<bytecode 0x400a9353>)(((defalias (quote divide-safe) (aio-lambda (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))) defalias)
  macroexp--expand-all((aio-defun divide-safe (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))
  macroexpand-all((aio-defun divide-safe (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))
  eval-sexp-add-defvars((aio-defun divide-safe (a b) (condition-case error (aio-await (divide a b)) (arith-error :arith-error))))
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)
skeeto commented 5 years ago

In order to use aio you must use lexical scope. Unfortunately it's not yet the default for Emacs, so you must enable it explicitly using a file local variable:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Lexical-Binding.html

The reason is that aio is built atop Emacs generators, and these require lexical binding. Regardless, you should always enable lexical binding anyway since it has lots of advantages and no disadvantages:

https://nullprogram.com/blog/2016/12/22/

canatella commented 5 years ago

I knew I was doing something wrong! Thank you very much.

gravitational-dark-light commented 4 years ago

And to really make lexical scope default everywhere

(run-at-time 0 nil (lambda ( ) (set-default 'lexical-binding t)))