bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC] Scoped variables, supercharged


From: Jouke Witteveen
Subject: Re: [RFC] Scoped variables, supercharged
Date: Fri, 27 Dec 2019 07:59:58 +0100

On Thu, Dec 26, 2019 at 10:52 PM Paul Smith <address@hidden> wrote:
>
> On Thu, 2019-12-26 at 21:24 +0100, Jouke Witteveen wrote:
> > >   Your proposal has the potential to create variables that would have
> > >   scope local to a single invocation of a user-defined function, but it
> > >   wouldn't provide scoping to Make-proper.  For that reason alone, I
> > >   would suggest narrowing down the naming of the feature.  Perhaps
> > >   something like:
> >
> > What other meaning of 'scoping to Make-proper' do you have in mind? I
> > fail to see a scoping scenario that is not covered by my $(let)
> > proposal.
>
> I believe thutt is thinking of creating new scopes in makefiles themselves,
> not within a variable/function context, for example within included
> makefiles or even within subsections of a particular makefile.

Ah, now I understand. With $(let), the scope is determined by the
parentheses, but theoretically, a file-scope could be a thing too.

> For example something where you could say:
>
>    FOO = bar
>
>    push scope
>    local FOO = baz
>
>    $(FOO): blah
>    pop scope
>
>    $(FOO): yuck
>
> Of course if you wanted to write a bunch of define/endif stuff and use eval
> you could use $(let ...) to do something like this but it can get pretty
> gross.

Let's run a little test. I have a Makefile containing:
----
X=global
$(let X,local,$(eval include inc.mk))
$(info $X)
----
And a file callend inc.mk containing:
----
$(info $X)
X=included
$(info $X)
----
We can see what happens even without recompiling make by replacing the
instance of $(let) by $(foreach). The resulting behavior is the same
(because 'local' is only one word). We get the following:
----
$ make
local
local
included
----

To me, it would make more sense if the second line read 'included' and
the last line read 'global', so maybe there is a bug in how make
currently deals with variable scopes.

> That is a separate feature that wouldn't help you do what you want to do,
> but that's probably why thutt suggests finding a more specific term.  In
> Lisp, "let" creates "local bindings" not a new scope.  I'm not sure if that
> is more or less clear for people not familiar with Lisp.

I modeled $(let) after let expressions of Haskell. I am sure many
other (especially functional) languages have similar let constructs.
There is even a Wikipedia page on the 'Let expression', which mainly
deals with its use in mathematics, but is still very much applicable
to my $(let) proposal. For familiarity in the greater programming
language ecosystem, I think $(let) bindings with a scope defined by
the parentheses is a sensible choice of naming and behavior.

> Here's another question: will this "do what you expect" if you invoke an
> include within an eval within a let?  For example:
>
>   $(let FOO BAR,,$(eval include myfile.mk))
>
> will ensure that any "global" settings of FOO or BAR that are made inside
> of myfile.mk are forgotten about afterwards?
>
> What other sorts of tricks or issues could we get into using eval within
> let, I wonder...

Whatever breaks with the above expression probably also breaks with

  $(foreach FOO,_,$(foreach BAR,_,$(eval include myfile.mk)))

One way to think of why $(let) would be a reasonable addition to make
is precisely because it does not deviate from established behavior too
much. Yet, it provides a clear value. Outside of the scoping, it also
enables basic list unpacking similar to `read` in the shell. My
example with reverse demonstrates this aspect too.

Regards,
- Jouke



reply via email to

[Prev in Thread] Current Thread [Next in Thread]