unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Another question about lambdas
@ 2022-12-10 17:23 Michael Heerdegen
  2022-12-10 19:33 ` tomas
                   ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-10 17:23 UTC (permalink / raw)
  To: Emacs mailing list

Hello,

My new question for today is:

What's the result of the following expression - and why?  Or maybe it is
invalid?

#+begin_src emacs-lisp
  (let* ((x 'l)
         (f (lambda () x))
         (x 'd))
    (funcall f))
#+end_src


Regards,

Michael.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 17:23 Another question about lambdas Michael Heerdegen
@ 2022-12-10 19:33 ` tomas
  2022-12-10 20:29   ` Michael Heerdegen
  2022-12-10 20:03 ` Emanuel Berg
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2022-12-10 19:33 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

On Sat, Dec 10, 2022 at 06:23:38PM +0100, Michael Heerdegen wrote:
> Hello,
> 
> My new question for today is:
> 
> What's the result of the following expression - and why?  Or maybe it is
> invalid?
> 
> #+begin_src emacs-lisp
>   (let* ((x 'l)
>          (f (lambda () x))
>          (x 'd))
>     (funcall f))
> #+end_src

I had to look that up in the elisp manual, and I must admit
I didn't find it very clear, but ultimately it says what will
happen.

Scheme docs are typically clearer, by explaining (let* ...) in
terms of nested (let ...). Perhaps that should go into the
Elisp manual, what do people think?

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 17:23 Another question about lambdas Michael Heerdegen
  2022-12-10 19:33 ` tomas
@ 2022-12-10 20:03 ` Emanuel Berg
  2022-12-12  1:50   ` Michael Heerdegen
  2022-12-10 21:58 ` Arash Esbati
  2022-12-11  0:13 ` Gregory Heytings
  3 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg @ 2022-12-10 20:03 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

> What's the result of the following expression - and why?
> Or maybe it is invalid?
>
>   (let* ((x 'l)
>          (f (lambda () x))
>          (x 'd))
>     (funcall f))

d!

Isn't this the same lambda thing again?

(setq f (lambda () x))

(funcall f) ; DNC

(setq x "marks the spot")

(funcall f) ; marks the spot too

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 19:33 ` tomas
@ 2022-12-10 20:29   ` Michael Heerdegen
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-10 20:29 UTC (permalink / raw)
  To: help-gnu-emacs

<tomas@tuxteam.de> writes:

> On Sat, Dec 10, 2022 at 06:23:38PM +0100, Michael Heerdegen wrote:
> > Hello,
> > 
> > My new question for today is:
> > 
> > What's the result of the following expression - and why?  Or maybe it is
> > invalid?
> > 
> > #+begin_src emacs-lisp
> >   (let* ((x 'l)
> >          (f (lambda () x))
> >          (x 'd))
> >     (funcall f))
> > #+end_src
>
> I had to look that up in the elisp manual, and I must admit
> I didn't find it very clear, but ultimately it says what will
> happen.

The shadowing is only one aspect of the exercise.  The question of the
return value is still not trivial.

> Scheme docs are typically clearer, by explaining (let* ...) in
> terms of nested (let ...). Perhaps that should go into the
> Elisp manual, what do people think?

+1.

I've skimmed over (info "(elisp) Local Variables").  Saying that `let*' is
equivalent to nested `let's would be helpful to understand the matter.

OTOH, shadowing is explained quite well.

Another thing that should be changed on that page is that it (still) says
that "The default scoping rule in Emacs Lisp is called “dynamic
scoping”" - that's not really true any more since *scratch* defaults to
lexical scoping.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 17:23 Another question about lambdas Michael Heerdegen
  2022-12-10 19:33 ` tomas
  2022-12-10 20:03 ` Emanuel Berg
@ 2022-12-10 21:58 ` Arash Esbati
  2022-12-11  0:00   ` Michael Heerdegen
  2022-12-11  0:13 ` Gregory Heytings
  3 siblings, 1 reply; 28+ messages in thread
From: Arash Esbati @ 2022-12-10 21:58 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Emacs mailing list

Michael Heerdegen <michael_heerdegen@web.de> writes:

> What's the result of the following expression - and why?  Or maybe it is
> invalid?
>
> #+begin_src emacs-lisp
>   (let* ((x 'l)
>          (f (lambda () x))
>          (x 'd))
>     (funcall f))
> #+end_src

With lexical or with dynamic binding?  I presume you tried it under
lexical binding and didn't get `d'.  This portion of the lisp reference
manual might be interesting:

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

Best, Arash



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 21:58 ` Arash Esbati
@ 2022-12-11  0:00   ` Michael Heerdegen
  2022-12-11  0:09     ` Michael Heerdegen
                       ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-11  0:00 UTC (permalink / raw)
  To: help-gnu-emacs

Hello Arash,

it seems you didn't notice that you participated in a quiz!

> > What's the result of the following expression - and why?  Or maybe
> > it is invalid?
> >
> > #+begin_src emacs-lisp
> >   (let* ((x 'l)
> >          (f (lambda () x))
> >          (x 'd))
> >     (funcall f))
> > #+end_src

> With lexical or with dynamic binding?

"With lexical or with dynamic binding?" is the correct answer to the
question.

Yes, the result depends on whether the expression is evaluated with
lexical binding or with dynamic.  The symbol names intended to give a
discrete hint (maybe too discrete).

So if we did not have the variable `lexical-binding' to check whether
lexical binding is used for evaluation, you could use a test like this:

#+begin_src emacs-lisp
(let* ((lb t)
       (getlex (lambda () lb))
       (lb nil))
  (funcall getlex))
#+end_src

I'm sorry that this was again a type "trap" question (everybody in the
trap can come out again now).

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-11  0:00   ` Michael Heerdegen
@ 2022-12-11  0:09     ` Michael Heerdegen
  2022-12-11  7:02     ` tomas
  2022-12-13 11:26     ` Arash Esbati
  2 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-11  0:09 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Hello Arash,
> it seems you didn't notice that you participated in a quiz!

Didn't mean to be derogatory, this was not intended.  On the contrary,
nice to see how many people hang around here who just kindly want to
help answering questions :-)

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 17:23 Another question about lambdas Michael Heerdegen
                   ` (2 preceding siblings ...)
  2022-12-10 21:58 ` Arash Esbati
@ 2022-12-11  0:13 ` Gregory Heytings
  2022-12-11  0:38   ` Michael Heerdegen
  3 siblings, 1 reply; 28+ messages in thread
From: Gregory Heytings @ 2022-12-11  0:13 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs


>
> (let* ((x 'l)
>        (f (lambda () x))
>        (x 'd))
>   (funcall f))
>

I think the following is clearer:

(let ((x 'l))
   (let ((f (lambda () x)))
     (let ((x 'd))
       (funcall f))))




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-11  0:13 ` Gregory Heytings
@ 2022-12-11  0:38   ` Michael Heerdegen
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-11  0:38 UTC (permalink / raw)
  To: help-gnu-emacs

Gregory Heytings <gregory@heytings.org> writes:

> > (let* ((x 'l)
> >        (f (lambda () x))
> >        (x 'd))
> >   (funcall f))

> I think the following is clearer:
>
> (let ((x 'l))
>   (let ((f (lambda () x)))
>     (let ((x 'd))
>       (funcall f))))

Yes, I think so too.

It was a question for this only 98% serious (and 2% funny) kind of quiz,
so I tried to obfuscate a bit what is going on.  OTOH using let* I could
add the implicit question about how shadowing works in `let*' - that
question had been asked just some days ago, so I guess I couldn't
withstand.

Your form is better to demonstrate the binding aspect.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-11  0:00   ` Michael Heerdegen
  2022-12-11  0:09     ` Michael Heerdegen
@ 2022-12-11  7:02     ` tomas
  2022-12-12  1:56       ` Michael Heerdegen
  2022-12-13 11:26     ` Arash Esbati
  2 siblings, 1 reply; 28+ messages in thread
From: tomas @ 2022-12-11  7:02 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 352 bytes --]

On Sun, Dec 11, 2022 at 01:00:15AM +0100, Michael Heerdegen wrote:

[...]

> I'm sorry that this was again a type "trap" question (everybody in the
> trap can come out again now).

No, no -- I think most are enjoying :-)

(now let me get out of the trap: I have to admit that I didn't stop
to think about dynamic binding).

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-10 20:03 ` Emanuel Berg
@ 2022-12-12  1:50   ` Michael Heerdegen
  2023-01-18 11:52     ` Emanuel Berg
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-12  1:50 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> >   (let* ((x 'l)
> >          (f (lambda () x))
> >          (x 'd))
> >     (funcall f))
>
> d!
>
> Isn't this the same lambda thing again?

Emmanuel thinks it's the same question about closures and solves it using
dynamic binding.  Creative :-)

Michael.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-11  7:02     ` tomas
@ 2022-12-12  1:56       ` Michael Heerdegen
  2022-12-12  5:24         ` tomas
  2023-01-18 11:33         ` Emanuel Berg
  0 siblings, 2 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-12  1:56 UTC (permalink / raw)
  To: help-gnu-emacs

<tomas@tuxteam.de> writes:

> (now let me get out of the trap: I have to admit that I didn't stop
> to think about dynamic binding).

At university I learned that lexical binding would be more intuitive to
understand, but harder to implement.  I thought I was special because I
always found dynamic binding more intuitive.  I thought it was because I
learned Lisp mostly by using Emacs, at a time where lexical binding was
only available using a strange thing called `lexical-let' (AFAIR you had
to require cl to use it).

But it seems that dynamic binding is the more intuitive scoping rule for
a lot of people.  And a lot have their problems with lexical binding and
closures.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  1:56       ` Michael Heerdegen
@ 2022-12-12  5:24         ` tomas
  2022-12-12  6:22           ` Michael Heerdegen
  2023-01-18 11:47           ` Emanuel Berg
  2023-01-18 11:33         ` Emanuel Berg
  1 sibling, 2 replies; 28+ messages in thread
From: tomas @ 2022-12-12  5:24 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 1349 bytes --]

On Mon, Dec 12, 2022 at 02:56:03AM +0100, Michael Heerdegen wrote:
> <tomas@tuxteam.de> writes:
> 
> > (now let me get out of the trap: I have to admit that I didn't stop
> > to think about dynamic binding).
> 
> At university I learned that lexical binding would be more intuitive to
> understand, but harder to implement.  I thought I was special because I
> always found dynamic binding more intuitive.  I thought it was because I
> learned Lisp mostly by using Emacs, at a time where lexical binding was
> only available using a strange thing called `lexical-let' (AFAIR you had
> to require cl to use it).

I think it depends on socialization. Those comning from shell languages
are clearly in the dynamic camp.

The most enriching experience is when you grow up with a language which
makes the transformation (the Lisps and Perl come to mind: do you know
others?)

> But it seems that dynamic binding is the more intuitive scoping rule for
> a lot of people.  And a lot have their problems with lexical binding and
> closures.

Now it would be interesting to know whether this is a general rule or
there are people more at ease with the one or the other side.

When I try to explain that, one of the devices I use is the idea of
"space" (static) vs. "time" (dynamic). It sticks with some people.

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  5:24         ` tomas
@ 2022-12-12  6:22           ` Michael Heerdegen
  2023-01-18 11:51             ` Emanuel Berg
  2023-01-18 11:47           ` Emanuel Berg
  1 sibling, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-12  6:22 UTC (permalink / raw)
  To: help-gnu-emacs

<tomas@tuxteam.de> writes:

> > But it seems that dynamic binding is the more intuitive scoping rule for
> > a lot of people.  And a lot have their problems with lexical binding and
> > closures.
>
> Now it would be interesting to know whether this is a general rule or
> there are people more at ease with the one or the other side.

I would be interested in other opinions.

My feeling is that lexical binding comes - while the principle is not
hard to understand - with a larger space of non-trivial implications and
stuff that you can do, or techniques to learn, all things that are work
to understand for the human brain that can only grasp one aspect at a
time.  Like knowing how to build a wardrobe is not the same as
knowing what a hammer, nails, a saw and wood is.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-11  0:00   ` Michael Heerdegen
  2022-12-11  0:09     ` Michael Heerdegen
  2022-12-11  7:02     ` tomas
@ 2022-12-13 11:26     ` Arash Esbati
  2022-12-14  2:22       ` Michael Heerdegen
  2 siblings, 1 reply; 28+ messages in thread
From: Arash Esbati @ 2022-12-13 11:26 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

> it seems you didn't notice that you participated in a quiz!

I think I grasped that, I've obviously missed the rule "No clarifying
questions allowed" ;-)

>> > What's the result of the following expression - and why?  Or maybe
>> > it is invalid?
>> >
>> > #+begin_src emacs-lisp
>> >   (let* ((x 'l)
>> >          (f (lambda () x))
>> >          (x 'd))
>> >     (funcall f))
>> > #+end_src
>
>> With lexical or with dynamic binding?
>
> "With lexical or with dynamic binding?" is the correct answer to the
> question.

So here another one for you: What's the result of this expression under
lexical binding?

(let (_)
  (defvar x)
  (let* ((x 'l)
         (f (lambda () x))
         (x 'd))
    (funcall f)))

Best, Arash



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-13 11:26     ` Arash Esbati
@ 2022-12-14  2:22       ` Michael Heerdegen
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2022-12-14  2:22 UTC (permalink / raw)
  To: help-gnu-emacs

Arash Esbati <arash@gnu.org> writes:

> So here another one for you: What's the result of this expression under
> lexical binding?
>
> (let (_)
>   (defvar x)
>   (let* ((x 'l)
>          (f (lambda () x))
>          (x 'd))
>     (funcall f)))

For me?

Ok: the `defvar' marks the variable `x` special in the lexical scope
where it is called - which is the lexical scope introduced by the
outermost `let'.  So both bindings of `x` in the inner `let' get dynamic
scope, one is shadowing the other, and the result is `d` (the result is
also `d` when evaluated with lexical binding off).

That's described in (info "(elisp) Defining Variables") for anyone who
wants to read about backgrounds.  `dlet' is using this "trick" for its
own implementation.

A nice addition to the original version!

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  1:56       ` Michael Heerdegen
  2022-12-12  5:24         ` tomas
@ 2023-01-18 11:33         ` Emanuel Berg
  2023-01-19 13:32           ` Michael Heerdegen
  1 sibling, 1 reply; 28+ messages in thread
From: Emanuel Berg @ 2023-01-18 11:33 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

> At university I learned that lexical binding would be more
> intuitive to understand, but harder to implement. I thought
> I was special because I always found dynamic binding more
> intuitive. I thought it was because I learned Lisp mostly by
> using Emacs, at a time where lexical binding was only
> available using a strange thing called `lexical-let' (AFAIR
> you had to require cl to use it).

It's just how those `let' behaves, one only complicates matter
by speaking of dynamic vs lexical scope in general.
Have a `dlet' and a `llet' and both would be easy
to understand with no need to theorize, at least not to
understand them, it can be interesting for other reasons ...

And yes, the lexical one would be more intuitive since it's in
line with all the data hiding/encapsulation/sandboxing stuff
one has been up to longe before one heard those buzzwords ...

I mean, why do we have all this f(x) and g() { x } notation in
programming if it is, or can be, actually the same x as some
x outside of that? Just looking at it, and writing it, tells
me, "hey, this is an x of it's own". But with dynamic scope it
sometimes isn't and you have to look somewhere else, execute
code in your head etc to find out.

(With `let' it's actually the other way around but it's just
the other side of thinking the same thing, with `let', i.e.,
the lexical one, it's "those x stays here".)

> And a lot have their problems with lexical binding
> and closures.

What do you mean, what's up with them?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  5:24         ` tomas
  2022-12-12  6:22           ` Michael Heerdegen
@ 2023-01-18 11:47           ` Emanuel Berg
  1 sibling, 0 replies; 28+ messages in thread
From: Emanuel Berg @ 2023-01-18 11:47 UTC (permalink / raw)
  To: help-gnu-emacs

tomas wrote:

> When I try to explain that, one of the devices I use is the
> idea of "space" (static) vs. "time" (dynamic). It sticks
> with some people.

What about just explaining the the dynamic `let' and the lexical
(static) let? Theory doesn't help IME.

With the lexical `let', those variables stay _here_ ...

Unless they are already dynamic/special.

Don't see any other use case of dynamic/special variables than
options, but then isn't it that they are _global_ and now set
temporarily to whatever value for the duration of the scope
defined by the opening and closing parenthesis?

So one should drop the talk of dynamic/special vs
lexical/static and instead have one `locals' (with the same
syntax and as let, but always lexical/static, even for
dynamic/special ones) and then one `options', also with the
same syntax, to set globals for a limited scope.

That covers the global variables and the local ones so what's
more to cover?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  6:22           ` Michael Heerdegen
@ 2023-01-18 11:51             ` Emanuel Berg
  2023-01-19 13:24               ` Michael Heerdegen
  2023-01-19 13:38               ` Michael Heerdegen
  0 siblings, 2 replies; 28+ messages in thread
From: Emanuel Berg @ 2023-01-18 11:51 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

> My feeling is that lexical binding comes - while the
> principle is not hard to understand - with a larger space of
> non-trivial implications [...]

And those are ... ?

Lexical/static scope makes for more modular programming ...
with less errors since the building blocks are smaller, more
self-contained.

You write it, read it, use it, and that's all there is to it.

Hey, what's *this*? Doesn't happen.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2022-12-12  1:50   ` Michael Heerdegen
@ 2023-01-18 11:52     ` Emanuel Berg
  2023-01-19 13:23       ` Michael Heerdegen
  0 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg @ 2023-01-18 11:52 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

>>>   (let* ((x 'l)
>>>          (f (lambda () x))
>>>          (x 'd))
>>>     (funcall f))
>>
>> d!
>>
>> Isn't this the same lambda thing again?
>
> Emanuel thinks it's the same question about closures and
> solves it using dynamic binding. Creative :-)

??? :)

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-18 11:52     ` Emanuel Berg
@ 2023-01-19 13:23       ` Michael Heerdegen
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2023-01-19 13:23 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> Michael Heerdegen wrote:
>
> >>>   (let* ((x 'l)
> >>>          (f (lambda () x))
> >>>          (x 'd))
> >>>     (funcall f))
> >>
> >> d!
> >>
> >> Isn't this the same lambda thing again?
> >
> > Emanuel thinks it's the same question about closures and
> > solves it using dynamic binding. Creative :-)
>
> ??? :)

You did not understand my comment?

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-18 11:51             ` Emanuel Berg
@ 2023-01-19 13:24               ` Michael Heerdegen
  2023-01-19 13:38               ` Michael Heerdegen
  1 sibling, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2023-01-19 13:24 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> Michael Heerdegen wrote:
>
> > My feeling is that lexical binding comes - while the
> > principle is not hard to understand - with a larger space of
> > non-trivial implications [...]
>
> And those are ... ?

The more sophisticated programming techniques that come with it.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-18 11:33         ` Emanuel Berg
@ 2023-01-19 13:32           ` Michael Heerdegen
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Heerdegen @ 2023-01-19 13:32 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> I mean, why do we have all this f(x) and g() { x } notation in
> programming if it is, or can be, actually the same x as some
> x outside of that? Just looking at it, and writing it, tells
> me, "hey, this is an x of it's own". But with dynamic scope it
> sometimes isn't and you have to look somewhere else, execute
> code in your head etc to find out.
> [...]
>
> > And a lot have their problems with lexical binding
> > and closures.
>
> What do you mean, what's up with them?

As long as there are only individual closures that only treat one
individual variable it's all trivial, yes.

The non-trivial aspects start when several closures, used in different
parts of a program, share the same variables of the same environment,
or partly share an environment partly.  Or a variable of the same name
appears multiple times in different environments with different bindings.

The "execute code in your head" thing is a question of code complexity,
not one of scoping.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-18 11:51             ` Emanuel Berg
  2023-01-19 13:24               ` Michael Heerdegen
@ 2023-01-19 13:38               ` Michael Heerdegen
  2023-01-30 17:44                 ` Emanuel Berg
  1 sibling, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2023-01-19 13:38 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> > My feeling is that lexical binding comes - while the
> > principle is not hard to understand - with a larger space of
> > non-trivial implications [...]
>
> And those are ... ?

An example: try to write something that transforms code into a CPS,
continuation passing style, form.  Therefore you really need closures.

Michael.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-19 13:38               ` Michael Heerdegen
@ 2023-01-30 17:44                 ` Emanuel Berg
  2023-02-03  0:20                   ` Michael Heerdegen
  0 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg @ 2023-01-30 17:44 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

>>> My feeling is that lexical binding comes - while the
>>> principle is not hard to understand - with a larger space of
>>> non-trivial implications [...]
>>
>> And those are ... ?
>
> An example: try to write something that transforms code into
> a CPS, continuation passing style, form. Therefore you
> really need closures.

Are we talking lexical/static `let' inside or outside
`defun's?

Inside defuns they are very practical, local variables,
basically, outside defuns they are interesting, rather, I have
found 2 use cases so far, first, what in other languages are
refered to as static variables (whose value don't reset
between calls), second, the possibility to share such
variables between functions.

This file demonstrate those use cases, other than that I don't
know what one is supposed to do with them, really, and so far
they don't do anything global variables don't. So they are
a method to not have those, basically?

;;; -*- lexical-binding: t -*-
;;
;; this file:
;;   https://dataswamp.org/~incal/emacs-init/w3m/w3m-survivor.el

(require 'w3m-search)
(require 'cl-lib)

(let ((opts   "torrent magnet 720p")
      (show   "Survivor")
      (prompt "episode: ") )

  (let ((next 1))
    (defun australian-survivor (ep)
      (interactive (list (read-number prompt next)))
      (w3m-search w3m-search-default-engine
        (format "\"S10E%02d\" Australian %s %s" ep show opts) )
      (setq next (1+ ep)) ))

  (declare-function australian-survivor nil)
  (defalias 'aus #'australian-survivor)

  (let ((next 1))
    (defun us-survivor (ep)
      (interactive (list (read-number prompt next)))
      (w3m-search w3m-search-default-engine
        (format "\"S43E%02d\" %s %s" ep show opts) )
      (setq next (1+ ep)) ))

  (declare-function us-survivor nil)
  (defalias 'us #'us-survivor) )

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-01-30 17:44                 ` Emanuel Berg
@ 2023-02-03  0:20                   ` Michael Heerdegen
  2023-02-25  7:31                     ` Emanuel Berg
  0 siblings, 1 reply; 28+ messages in thread
From: Michael Heerdegen @ 2023-02-03  0:20 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <incal@dataswamp.org> writes:

> Are we talking lexical/static `let' inside or outside
> `defun's?
>
> Inside defuns they are very practical, local variables,
> basically, outside defuns they are interesting, rather, I have
> found 2 use cases so far, first, what in other languages are
> refered to as static variables (whose value don't reset
> between calls), second, the possibility to share such
> variables between functions.
>
> This file demonstrate those use cases, other than that I don't
> know what one is supposed to do with them, really, and so far
> they don't do anything global variables don't. So they are
> a method to not have those, basically?

Dunno if this is a good summary, I would be careful.  I find the
question a bit artificial - how is the classification global vs local
functions motivated?  The top-level lexical environment is empty, so
top-level defuns are not interesting as closures.

So we are actually only speaking about the case of functions defined
anywhere besides top-level that are given a global name.  In a
functional language functions with a globally accessible name that have
an alterable state are probably not that sexy - we are instead trying to
make those functions pure, or try to restrict side effects to obvious
well-defined things like creating a window.

Useful cases that come to my mind are more of kind where the state is
never altered but lexical binding eases the definition of bunches of
functions - in a very simple case e.g.

#+begin_src emacs-lisp
(defun my-make-adder (n)
  (lambda (m) (+ m n)))

(defalias 'my-1+ (my-make-adder 1))
(defalias 'my-1- (my-make-adder -1))
#+end_src


Such lexical variables are still different from special top-level
variables (`defvar's): They are private (not accessible "from the
outside").  You can have several of them having the same name.  They
don't clobber a name space.  And no binding created in any context
outside of the lexical context where the functions are defined can ever
change the value of those variables.


Michael.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-02-03  0:20                   ` Michael Heerdegen
@ 2023-02-25  7:31                     ` Emanuel Berg
  2023-02-27  8:28                       ` tomas
  0 siblings, 1 reply; 28+ messages in thread
From: Emanuel Berg @ 2023-02-25  7:31 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

>> Are we talking lexical/static `let' inside or outside
>> `defun's?
>>
>> Inside defuns they are very practical, local variables,
>> basically, outside defuns they are interesting, rather,
>> I have found 2 use cases so far, first, what in other
>> languages are refered to as static variables (whose value
>> don't reset between calls), second, the possibility to
>> share such variables between functions.
>>
>> This file demonstrate those use cases, other than that
>> I don't know what one is supposed to do with them, really,
>> and so far they don't do anything global variables don't.
>> So they are a method to not have those, basically?
>
> Dunno if this is a good summary, I would be careful. I find
> the question a bit artificial - how is the classification
> global vs local functions motivated?

With top-level let-closures "enclosed" defuns can use the
variables defined in the VARLIST of `let' as if they were
global variables, but they are not.

So perceived and real disadvantages of global variables won't
pester your Elisp.

And the advantages are, compared to local variables - also
using `let' - they keep their values between function calls,
and they can be shared/accessed by several functions.

Here is an example showing these two advantages/use cases:
  https://dataswamp.org/~incal/emacs-init/w3m/w3m-survivor.el

If there are other use cases I'm unaware of them.

And if you think about those two use cases, they do nothing
that global variables don't.

So, it's all about avoiding the downsides of global variables?

If so, it's enough - I'll take it. It makes the code more
pretty/cool and you don't use global variables.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Another question about lambdas
  2023-02-25  7:31                     ` Emanuel Berg
@ 2023-02-27  8:28                       ` tomas
  0 siblings, 0 replies; 28+ messages in thread
From: tomas @ 2023-02-27  8:28 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 206 bytes --]

On Sat, Feb 25, 2023 at 08:31:22AM +0100, Emanuel Berg wrote:

[...]

> So, it's all about avoiding the downsides of global variables?

They make your compiled code FASTER, too!!1!

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2023-02-27  8:28 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-10 17:23 Another question about lambdas Michael Heerdegen
2022-12-10 19:33 ` tomas
2022-12-10 20:29   ` Michael Heerdegen
2022-12-10 20:03 ` Emanuel Berg
2022-12-12  1:50   ` Michael Heerdegen
2023-01-18 11:52     ` Emanuel Berg
2023-01-19 13:23       ` Michael Heerdegen
2022-12-10 21:58 ` Arash Esbati
2022-12-11  0:00   ` Michael Heerdegen
2022-12-11  0:09     ` Michael Heerdegen
2022-12-11  7:02     ` tomas
2022-12-12  1:56       ` Michael Heerdegen
2022-12-12  5:24         ` tomas
2022-12-12  6:22           ` Michael Heerdegen
2023-01-18 11:51             ` Emanuel Berg
2023-01-19 13:24               ` Michael Heerdegen
2023-01-19 13:38               ` Michael Heerdegen
2023-01-30 17:44                 ` Emanuel Berg
2023-02-03  0:20                   ` Michael Heerdegen
2023-02-25  7:31                     ` Emanuel Berg
2023-02-27  8:28                       ` tomas
2023-01-18 11:47           ` Emanuel Berg
2023-01-18 11:33         ` Emanuel Berg
2023-01-19 13:32           ` Michael Heerdegen
2022-12-13 11:26     ` Arash Esbati
2022-12-14  2:22       ` Michael Heerdegen
2022-12-11  0:13 ` Gregory Heytings
2022-12-11  0:38   ` Michael Heerdegen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).