Как использовать переменные от создателя в асинхронно называемом лямбда в elisp? [Дубликат]

Короткий ответ: вам нужно выполнить обратный вызов следующим образом:

function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
}

$.ajax({
    url: "...",
    success: callback
});
6
задан legoscia 27 November 2014 в 12:14
поделиться

3 ответа

Проблема в том, что привязки переменных Emacs Lisp по умолчанию динамические. То есть, когда функция оценивается, связанные переменные просматриваются не в среде, где была определена функция, но в среде, где была вызвана функция.

Emacs 24 или позже поддерживает лексическую привязку (т. е. функция видит переменные, которые были связаны вокруг определения функции ) изначально, но поскольку она изменяет семантику существующего кода, вам необходимо явно ее включить. Обычно это делается путем добавления локальной переменной файла в первую строку файла .el:

;; -*- lexical-binding: t; -*-

Другой альтернативой является использование lexical-let из библиотеки cl. Это работает и в предыдущих версиях Emacs. Обратите внимание, что таким образом вы явно указываете, какие переменные должны иметь лексическую привязку, поэтому код, такой как (lexical-let ((foo foo)) ...), не является редкостью - foo - это существующая переменная, которая должна быть «перенесена» в функцию.

7
ответ дан legoscia 5 September 2018 в 09:12
поделиться

Хорошо, я думаю, что у меня есть это сейчас. Приведенный выше пример является хорошим примером; вот еще один случай, если у кого-то еще есть такая трудность:

;;; ensure VAR1 has no binding
(makunbound 'VAR1)
;;;
(defun f1 (&optional VAR1)
  (interactive)
  (unless VAR1
    (set 'VAR1 "variable1"))
  (pop-to-buffer "*test*")
;  (lexical-let ( (VAR1 VAR1) ) ;;;
    (set-process-sentinel
     (start-process-shell-command "test"
                  "*test*"
                  (concat "echo " VAR1))
     (lambda (process event)
       (condition-case err
       (when (string-match-p "finished" event)
         (f2 VAR1))
     (error
      (princ
       (format "Sentinel error: %s" err))))))
;    ) ;;;
  )
;;;
(defun f2 (&optional VAR2)
   (interactive)
  (unless VAR2
    (set 'VAR2 "VARIABLE2"))
  (print VAR2))

Мы загружаем все (с комментариями в (f1)) и запускаем (f1). Значение VAR1 передается в (f2) перед , когда происходит ошибка. Похоже, что ошибка (void-variable VAR1) исходит из области определения области видимости (set-process sentinel PROCESS SENTINEL); VAR1 не определен там, хотя он остается в области функции SENTINEL ((lambda)).

Также использование (set ), как указано выше, не является наилучшей практикой, когда переменная предназначена только для того, чтобы область была локальной для функции.

Если мы раскомментируем строки, помеченные знаком ;, тогда все работает так, как ожидалось. К счастью, мы можем передать значение до другой функции, которая предотвращает создание длинной серии (set-process sentinel ). Это также позволяет нам генерировать процессы с дополнительными подпроцессами, если это необходимо.

Одна из моих ошибок заключалась в том, что SENTINEL называлась дискретной функцией, а не удерживала ее внутри функции (lexical-let ). Хотя подход lexical-binding: t; привлекателен, он, как правило, нарушает рабочий код, который опирается на стандарт (let ).

1
ответ дан dardisco 5 September 2018 в 09:12
поделиться

Ниже приведен пример использования динамических привязок:

(defun example-dynamic-fn ()
"Doc-string"
(interactive)
  (let ((test-variable "Hello-world!"))
    (set-process-sentinel
      (start-process "process-one" "*one*" "echo" test-variable)
      `(lambda (p e) (when (= 0 (process-exit-status p))
        (set-process-sentinel
          (start-process "process-two" "*two*" "echo" ,test-variable)
          '(lambda (p e) (when (= 0 (process-exit-status p))
            (start-process "process-three" "*three*" "echo" ,test-variable)
            (set-process-sentinel
              (start-process "process-four" "*four*" "echo" ,test-variable)
              '(lambda (p e) (when (= 0 (process-exit-status p))
                (set-process-sentinel
                  (start-process "process-five" "*five*" "echo" ,test-variable)
                  '(lambda (p e) (when (= 0 (process-exit-status p))
                    (message "test-variable:  %s" ,test-variable)))))))))))))))
1
ответ дан lawlist 5 September 2018 в 09:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: