Re: New conditional assignment facility

2024-01-11 Thread N. Thiebaud
> I'm pretty uncomfortable with this inversion of expectation,

Indeed.
This inversion sounds confusing and that use case is already possible,
just not with a 'shortcut' notation.

> Or maybe we should say the "?+=" operator isn't supported and give an
> error since it has no function

that also leave open the future use of that notation, if usage and
experience point to a 'better' solution

If it not an error, there won't be any practical way to change that
decision in the future



Re: New conditional assignment facility

2024-01-11 Thread Paul Smith
On Thu, 2024-01-11 at 01:44 -0500, Paul Smith wrote:
> I've implemented a new capability for conditional assignments (not
> pushed yet).
> 
> After these changes, a "?" can precede any type of assignment
> operation, not just "=", and make it conditional (that is, it only
> takes effect if the variable is not already set).
> 
> There is one question I wanted to ask for opinions on: what should we
> do with the "?+=" operator?

Having thought about this more the answer seems obvious.

Better would be to say that BOTH "?" AND "+" are modifiers to
assignment statements, and that you can have only one of them; this
makes sense since either you want to set a value if it doesn't exist or
you want to append to a value that does exist, but not both.

Thus, the "base" assignment operators would be "=", ":=", "::=" (for
POSIX), and ":::=".

Then you could prefix any of those with either "?" so the assignment
only happens if the variable is not defined, or "+" so the assignment
is appended to any existing value.

So we would allow assignments like "+=", "+:=", "+::=", "+:::=" as well
as the "?" variants.  This is useful because something like "+:=" has
long been requested.


So the new confusion becomes, what happens if you use "+" to append to
an existing variable that has a different type?

Due to decades of history (and, to be honest, significant technical
incentive), we have to say that in this case:

bar = xx
biz = yy
FOO := $(bar)
FOO += $(biz)
bar = 1
biz = 2

FOO is a simply-expanded variable and $(biz) is expanded immediately
even though it uses a "+=" assignment, and FOO is "xx yy".

But then, what do we say about this case:

bar = xx
biz = yy
FOO = $(bar)
FOO +:= $(biz)
bar = 1
biz = 2

? There appear to be two options:

Either we could follow the example of "+=" and say that the assignment
type in "+:=" only takes effect if the variable doesn't already have a
type but if it does that type is preserved, so in the above example FOO
would continue to be recursively expanded in spite of "+:=", so FOO has
a value of "$(bar) $(biz)" and $(FOO) gives "1 2".

Or we could say that "+=" is a special case where we follow the type of
the existing variable, but for the other operators we first expand the
right hand side then append the result regardless of the original type.
So in the above example FOO is still a recursive variable, BUT $(baz)
is expanded immediately before appending so the value of FOO would be
"$(bar) yy" and $(FOO) gives "1 yy".

Neither of these is great, in that they both will cause people to be
surprised, in different situations.  Given that, I'm leaning more
towards the second option above, which leaves "+=" as a special case
but seems more useful and less confusing overall.

Comments welcome.

-- 
Paul D. Smith Find some GNU make tips at:
https://www.gnu.org   http://make.mad-scientist.net
"Please remain calm...I may be mad, but I am a professional." --Mad
Scientist



Re: New conditional assignment facility

2024-01-11 Thread Alejandro Colomar
Hi Paul!

On Thu, Jan 11, 2024 at 01:44:19AM -0500, Paul Smith wrote:
> I've implemented a new capability for conditional assignments (not
> pushed yet).
> 
> After these changes, a "?" can precede any type of assignment
> operation, not just "=", and make it conditional (that is, it only
> takes effect if the variable is not already set).
> 
> So for example, in addition to "?=" which creates a recursive variable
> if the variable is not set yet, GNU Make will support "?:=" which
> creates a simple variable if the variable is not set yet.

Thanks!!

>  Of course if
> it's already set then the right-hand side of the assignment is not
> expanded.
> 
> Similarly the assignments "?::=" and "?:::=" are also supported.
> 
> 
> There is one question I wanted to ask for opinions on: what should we
> do with the "?+=" operator?

There's a use for it:  appending to a variable if it wasn't set in the
environment (ignoring what happened in the Makefile).

Here's what += does:

alx@debian:~/tmp$ cat Makefile 
var ?= foo
var += bar
$(info $(var))
alx@debian:~/tmp$ make
foo bar
make: *** No targets.  Stop.
alx@debian:~/tmp$ make var=foo
foo
make: *** No targets.  Stop.
alx@debian:~/tmp$ var=foo make
foo bar
make: *** No targets.  Stop.

And here's what ?+= could do:

alx@debian:~/tmp$ cat Makefile 
var ?= foo
var ?+= bar
$(info $(var))
alx@debian:~/tmp$ make-9000
foo bar
make: *** No targets.  Stop.
alx@debian:~/tmp$ make-9000 var=foo
foo
make: *** No targets.  Stop.
alx@debian:~/tmp$ var=foo make-9000
foo
make: *** No targets.  Stop.

In the last case (environment variable), since var was set, ?+= would do
nothing, unlike +=.

Have a lovely day,
Alex

-- 

Looking for a remote C programming job at the moment.


signature.asc
Description: PGP signature


Re: New conditional assignment facility

2024-01-11 Thread Alejandro Colomar
On Thu, Jan 11, 2024 at 02:22:19PM +0100, Alejandro Colomar wrote:
> Hi Paul!
> 
> On Thu, Jan 11, 2024 at 01:44:19AM -0500, Paul Smith wrote:
> > I've implemented a new capability for conditional assignments (not
> > pushed yet).
> > 
> > After these changes, a "?" can precede any type of assignment
> > operation, not just "=", and make it conditional (that is, it only
> > takes effect if the variable is not already set).
> > 
> > So for example, in addition to "?=" which creates a recursive variable
> > if the variable is not set yet, GNU Make will support "?:=" which
> > creates a simple variable if the variable is not set yet.
> 
> Thanks!!
> 
> >  Of course if
> > it's already set then the right-hand side of the assignment is not
> > expanded.
> > 
> > Similarly the assignments "?::=" and "?:::=" are also supported.
> > 
> > 
> > There is one question I wanted to ask for opinions on: what should we
> > do with the "?+=" operator?
> 
> There's a use for it:  appending to a variable if it wasn't set in the
> environment (ignoring what happened in the Makefile).
> 
> Here's what += does:
> 
>   alx@debian:~/tmp$ cat Makefile 
>   var ?= foo
>   var += bar
>   $(info $(var))
>   alx@debian:~/tmp$ make
>   foo bar
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ make var=foo
>   foo
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ var=foo make
>   foo bar
>   make: *** No targets.  Stop.

Sorry for reusing "foo".  I'll rewrite with quux, which will be clearer.

alx@debian:~/tmp$ cat Makefile 
var ?= foo
var += bar
$(info $(var))
alx@debian:~/tmp$ make 
foo bar
make: *** No targets.  Stop.
alx@debian:~/tmp$ make var=quux
quux
make: *** No targets.  Stop.
alx@debian:~/tmp$ var=quux make
quux bar
make: *** No targets.  Stop.

> 
> And here's what ?+= could do:

alx@debian:~/tmp$ cat Makefile 
var ?= foo
var += bar
$(info $(var))
alx@debian:~/tmp$ make 
foo bar
make: *** No targets.  Stop.
alx@debian:~/tmp$ make var=quux
quux
make: *** No targets.  Stop.
alx@debian:~/tmp$ var=quux make
quux
make: *** No targets.  Stop.

>   alx@debian:~/tmp$ cat Makefile 
>   var ?= foo
>   var ?+= bar
>   $(info $(var))
>   alx@debian:~/tmp$ make-9000
>   foo bar
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ make-9000 var=foo
>   foo
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ var=foo make-9000
>   foo
>   make: *** No targets.  Stop.
> 
> In the last case (environment variable), since var was set, ?+= would do
> nothing, unlike +=.
> 

-- 

Looking for a remote C programming job at the moment.


signature.asc
Description: PGP signature


Re: New conditional assignment facility

2024-01-11 Thread Alejandro Colomar
On Thu, Jan 11, 2024 at 02:25:25PM +0100, Alejandro Colomar wrote:
> On Thu, Jan 11, 2024 at 02:22:19PM +0100, Alejandro Colomar wrote:
> > Hi Paul!
> > 
> > On Thu, Jan 11, 2024 at 01:44:19AM -0500, Paul Smith wrote:
> > > I've implemented a new capability for conditional assignments (not
> > > pushed yet).
> > > 
> > > After these changes, a "?" can precede any type of assignment
> > > operation, not just "=", and make it conditional (that is, it only
> > > takes effect if the variable is not already set).
> > > 
> > > So for example, in addition to "?=" which creates a recursive variable
> > > if the variable is not set yet, GNU Make will support "?:=" which
> > > creates a simple variable if the variable is not set yet.
> > 
> > Thanks!!
> > 
> > >  Of course if
> > > it's already set then the right-hand side of the assignment is not
> > > expanded.
> > > 
> > > Similarly the assignments "?::=" and "?:::=" are also supported.
> > > 
> > > 
> > > There is one question I wanted to ask for opinions on: what should we
> > > do with the "?+=" operator?
> > 
> > There's a use for it:  appending to a variable if it wasn't set in the
> > environment (ignoring what happened in the Makefile).
> > 
> > Here's what += does:
> > 
> > alx@debian:~/tmp$ cat Makefile 
> > var ?= foo
> > var += bar
> > $(info $(var))
> > alx@debian:~/tmp$ make
> > foo bar
> > make: *** No targets.  Stop.
> > alx@debian:~/tmp$ make var=foo
> > foo
> > make: *** No targets.  Stop.
> > alx@debian:~/tmp$ var=foo make
> > foo bar
> > make: *** No targets.  Stop.
> 
> Sorry for reusing "foo".  I'll rewrite with quux, which will be clearer.
> 
>   alx@debian:~/tmp$ cat Makefile 
>   var ?= foo
>   var += bar
>   $(info $(var))
>   alx@debian:~/tmp$ make 
>   foo bar
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ make var=quux
>   quux
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ var=quux make
>   quux bar
>   make: *** No targets.  Stop.
> 
> > 
> > And here's what ?+= could do:
> 
>   alx@debian:~/tmp$ cat Makefile 
>   var ?= foo
>   var += bar

D'oh!  I can't write an email without typos.

var ?+= bar

>   $(info $(var))
>   alx@debian:~/tmp$ make 
>   foo bar
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ make var=quux
>   quux
>   make: *** No targets.  Stop.
>   alx@debian:~/tmp$ var=quux make
>   quux
>   make: *** No targets.  Stop.
> 
> > alx@debian:~/tmp$ cat Makefile 
> > var ?= foo
> > var ?+= bar
> > $(info $(var))
> > alx@debian:~/tmp$ make-9000
> > foo bar
> > make: *** No targets.  Stop.
> > alx@debian:~/tmp$ make-9000 var=foo
> > foo
> > make: *** No targets.  Stop.
> > alx@debian:~/tmp$ var=foo make-9000
> > foo
> > make: *** No targets.  Stop.
> > 
> > In the last case (environment variable), since var was set, ?+= would do
> > nothing, unlike +=.
> > 
> 
> -- 
> 
> Looking for a remote C programming job at the moment.



-- 

Looking for a remote C programming job at the moment.


signature.asc
Description: PGP signature


Re: New conditional assignment facility

2024-01-11 Thread Paul Smith
On Thu, 2024-01-11 at 14:28 +0100, Alejandro Colomar wrote:
> > >   alx@debian:~/tmp$ cat Makefile 
> > >   var ?= foo
> > >   var ?+= bar
> > >   $(info $(var))
> > >   alx@debian:~/tmp$ make-9000
> > >   foo bar
> > >   make: *** No targets.  Stop.
> > >   alx@debian:~/tmp$ make-9000 var=foo
> > >   foo
> > >   make: *** No targets.  Stop.
> > >   alx@debian:~/tmp$ var=foo make-9000
> > >   foo
> > >   make: *** No targets.  Stop.

Sorry Alejandro; maybe you need to rewrite your examples again without
all the corrections, because I don't understand what you mean.

In all your examples, the value of var is set by the first line if it's
not already set:

var ?= foo

After this line, var will either be "foo" or it will be whatever value
var had before that assignment (from the environment or command line or
whatever, it doesn't matter).  But it's definitely defined.

Once that happens, any subsequent "?" assignments, of any type, are
simply ignored and useless because "?" means "set if not defined" but
after the above line, var is always defined.

So it doesn't matter if the next line is "var ?= bar" or "var ?+= bar"
or whatever: it is just ignored.

-- 
Paul D. Smith Find some GNU make tips at:
https://www.gnu.org   http://make.mad-scientist.net
"Please remain calm...I may be mad, but I am a professional." --Mad
Scientist



Re: New conditional assignment facility

2024-01-11 Thread Alejandro Colomar

Hi Paul,

On 1/11/24 14:38, Paul Smith wrote:

On Thu, 2024-01-11 at 14:28 +0100, Alejandro Colomar wrote:

    alx@debian:~/tmp$ cat Makefile
    var ?= foo
    var ?+= bar
    $(info $(var))
    alx@debian:~/tmp$ make-9000
    foo bar
    make: *** No targets.  Stop.
    alx@debian:~/tmp$ make-9000 var=foo
    foo
    make: *** No targets.  Stop.
    alx@debian:~/tmp$ var=foo make-9000
    foo
    make: *** No targets.  Stop.


Sorry Alejandro; maybe you need to rewrite your examples again without
all the corrections, because I don't understand what you mean.

In all your examples, the value of var is set by the first line if it's
not already set:

 var ?= foo

After this line, var will either be "foo" or it will be whatever value
var had before that assignment (from the environment or command line or
whatever, it doesn't matter).  But it's definitely defined.

Once that happens, any subsequent "?" assignments, of any type, are
simply ignored and useless because "?" means "set if not defined" but
after the above line, var is always defined.


Hmm, after thinking about it again, I think my suggestion was dumb.

I was thinking of "?" meaning "set if not defined in the environment",
which is how I always used it.  But that's not what it means.

Cheers,
Alex



So it doesn't matter if the next line is "var ?= bar" or "var ?+= bar"
or whatever: it is just ignored.