On Thu, Dec 26, 2019 at 10:52 PM Paul Smith <psm...@gnu.org> 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