[emacs-w3m:13519] Re: lexical-binding question

Katsumi Yamaoka <[email protected]>
Newsgroups gmane.emacs.w3m
Organization Emacsen advocacy group
Message-ID <[email protected]>
In [emacs-w3m:13517]
On Tue, 06 Aug 2019 10:47:56 +0200, Michael Heerdegen wrote:
> Katsumi Yamaoka <[email protected]> writes:

>> The following forms are utmost simplified model of the functions
>> that the above form uses:

--8<---------------cut here---------------start------------->8---
;; -*- lexical-binding: t -*-
(defun fn1 () ;; simplified `w3m-w3m-expand-arguments'
  (eval '`,charset))

(defun fn2 (charset) ;; simplified `w3m-rendering-half-dump'
  (ignore charset) ;; Silence the byte compiler.
  (fn1))

(defun fn3 (&optional charset) ;; simplified `w3m-rendering-buffer'
  (fn2 charset))
--8<---------------cut here---------------end--------------->8---

> CHARSET is a lexical variable in fn2 and fn3.  Its scope is limited to
> (textual) references in those functions.  The lexical binding is not
> visible in fn1 no matter what eval '`, tricks you try, because it's out
> of scope.  It would only work as you expect with a dynamically bound
> variable.

Yes, I believe that's absolutely true.  But my wonder is why the
current w3m.el code works.  Please try:

・Eval: (setq w3m-input-coding-system 'binary)
・Perform `edebug-defun' on the function `w3m-w3m-expand-arguments'.
・Run M-x w3m for visiting some web page.

Then, you will see '`,charset and `,charset, that the constant
`w3m-halfdump-command-arguments' defines, are substituted with
a certain charset value successfully, even though the value of
`charset' is not passed to `w3m-w3m-expand-arguments' explicitly.

While edebugging `w3m-w3m-expand-arguments', it is notable that
the form (boundp 'charset) returns t and (symbol-value 'charset)
returns a certain charset value.  Does it mean that `charset' is
not a lexical variable?  If it is true, why it happens, and why
it does not happen with the simplified forms (i.e., fn1~fn3)?

Before turning on lexical-binding, the w3m.el code was like this:

--8<---------------cut here---------------start------------->8---
;; -*- lexical-binding: nil -*-
(defun fn4 () ;; simplified `w3m-w3m-expand-arguments'
  (eval 'charset))

(defun fn5 (charset) ;; simplified `w3m-rendering-half-dump'
  (fn4))

(defun fn6 (&optional charset) ;; simplified `w3m-rendering-buffer'
  (fn5 charset))
--8<---------------cut here---------------end--------------->8---

(fn6 'big5) returns big5.  But it got to cause the void variable
error after turning on lexical-binding in w3m.el.  First I tried
was changing   charset   with   `,charset   in the value form of
the `w3m-halfdump-command-arguments' constant, and saw it made it
work.  Please don't ask me why I did so, it was just at random.

> You can either make `charset' special (that can even be done locally in
> the function) to reuse the old code, or you rewrite that stuff so that
> it's really lexical binding code.  Then w3m-halfdump-command-arguments
> would probably become a function `w3m-halfdump-get-command-arguments'
> that depends on an CHARSET argument, or something similar.

I think changing the constant to a function is TRT, too.  But I
don't want to do it before clearing this charset mystery. ;)

Thanks.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.