FEATURE:? binding variables to prerequisites

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

FEATURE:? binding variables to prerequisites

Cook, Malcolm-2
Hi Paul et. al.,

When a rule has multiple prerequisites I sometimes use make variables to refer to them positionally, like this:

^1=$(word 1,$^)
^2=$(word 2,$^)
^3=$(word 3,$^)
^2..=$(wordlist 2,$(words $^),$^)
^3..=$(wordlist 3,$(words $^),$^)

%.foo: %.bar %.baz %.bat1 %.bat2 %.bat3
        process --baz ${^2}--bar ${^1} --bat ${^3..} > $@

What do you think of such syntactic sugar?  

Is there any sweeter version?

Is there some way to bind pattern specific variables to prerequisite using some syntax allowing rules such as:

%.foo: a:=%.bar b:=%.baz c:=%.bat1 %.bat2 %.bat3
        process --baz ${b}--bar ${a} --bat ${c} > $@

Might this be candidate for a new feature request?  Are there any other similar such ideas percolating?

FWIW - I mainly use make to structure bioinformatics analysis pipelines.

Cheers,

Malcolm Cook
Manager, Database Applications
Big Data AI and GenomicsĀ 
Stowers Institute for Medical Research


Reply | Threaded
Open this post in threaded view
|

Re: FEATURE:? binding variables to prerequisites

Kaz Kylheku (gmake)
On 2021-01-22 13:18, Cook, Malcolm wrote:

> Hi Paul et. al.,
>
> When a rule has multiple prerequisites I sometimes use make variables
> to refer to them positionally, like this:
>
> ^1=$(word 1,$^)
> ^2=$(word 2,$^)
> ^3=$(word 3,$^)
> ^2..=$(wordlist 2,$(words $^),$^)
> ^3..=$(wordlist 3,$(words $^),$^)
>
> %.foo: %.bar %.baz %.bat1 %.bat2 %.bat3
> process --baz ${^2}--bar ${^1} --bat ${^3..} > $@
>
> What do you think of such syntactic sugar?

Arguments in macros are already $(1), $(2). (But those were used, it
would cause "optical difficulties" in rules generated by macros.)

Speaking of macros, the above can be achieved very verbosely now using
call:

prereq = $(word $(1),$^)

$(call prereq 3)  # -> $(word 3,$^)

Firstly, it would be nice if macros with arguments could be invoked
without the clunky $(call).

I propose this syntax:
For instance, the syntax

   $(prereq)     # straight old substitution with no args
   $(prereq 3)   # == $(call prereq,3): substitution with $(1) = 3.

Additional arguments use commas

   $(foo 1,2,3)  # $(call foo,1,2,3)

Now, if we define a one-letter macro, like $(p 3), we have good density.

A further abbreviation facility could then perhaps be developed which
binds dispatch characters to macros so that $(^3) can become $(prereq
3). That only saves one
space over $(p 3) though.

Of course, without $(call ...), macros now clash in the namespace of
predefined operators.
If someone does this:

   word = whatever

   $(word 1,abc def)  # this is the built-in, not a call of the above
word

Makefiles then run the risk of breaking because they
used some word that is later claimed as a new built-in by
a new version of GNU Make. Some namespace rules could be documented.
For instance, no built-ins start with a capital letter currently
and future ones likely won't also, so that seems like a safe space
for defining macros. Such names clash with the reserved environment
space in POSIX, though.

Another idea might be to have some shorthand for $(call ...) like
say $[abc x,y,z,...] <--> $(call abc,x,y,z,...).

That's eerily like what I did in TXR Lisp.

1> '(dwim f x y z)
[f x y z]
2> (car '[f x y z])
dwim
3> (cdr '[f x y z])
(f x y z)
4>


dwim is a special dispatching operator whose name you almost never
directly mention in any conceivable code due to the [ ] shorthand.
It calls functions, accesses hashes, indexes into sequences like
lists vectors and strings and also allows for LIsp-1 style
programming in a dialect that is fundamentally Lisp-2 (separate
variable and function namespace).

E.g. (mapcar cons '(1 2 3) '(a b c)) won't work, because there
is no cons variable, but [mapcar cons '(1 2 3) '(a b c)]
will, because of a name lookup semantics alteration imposed by
the dwim operator.

But I digress.

GNU Make is almost like Lisp-2 because when you create a macro, you're
essentially storing a function definition into a variable,
and that is not in the right namespace to be invoked directly;
a calling operator is required.

The [] notation works well with indices. In the Make example we would
end up with  $[p 0] $[p 1] which looks like indexing into an
array p of prerequisites.

Reply | Threaded
Open this post in threaded view
|

RE: FEATURE:? binding variables to prerequisites

Cook, Malcolm-2
>From: Kaz Kylheku (gmake) <[hidden email]>
>On 2021-01-22 13:18, Cook, Malcolm wrote:
>> Hi Paul et. al.,
>>
>> When a rule has multiple prerequisites I sometimes use make variables
>> to refer to them positionally, like this:
>>
>> ^1=$(word 1,$^)
>> ^2=$(word 2,$^)
>> ^3=$(word 3,$^)
>> ^2..=$(wordlist 2,$(words $^),$^)
>> ^3..=$(wordlist 3,$(words $^),$^)
>>
>> %.foo: %.bar %.baz %.bat1 %.bat2 %.bat3
>> process --baz ${^2}--bar ${^1} --bat ${^3..} > $@
>>
>> What do you think of such syntactic sugar?
>
>Arguments in macros are already $(1), $(2). (But those were used, it
>would cause "optical difficulties" in rules generated by macros.)

Yes, I am aware.  I do not use the above in any way with macros, but rather within rule bodies.

>
>Speaking of macros, the above can be achieved very verbosely now using
>call:
>
>prereq = $(word $(1),$^)
>
>$(call prereq 3) # -> $(word 3,$^)

Yes, of course, but the verbosity is not satisfying... using such would not make rules scan better, whereas what I do already feels familiar in that it introduces a convention similar to standard positional argument access in many scripting environments.
>
>Firstly, it would be nice if macros with arguments could be invoked
>without the clunky $(call).

I have often felt similarly, but this is really a separate issue from mine....

>
>I propose this syntax:
>For instance, the syntax
>
>$(prereq) # straight old substitution with no args
>$(prereq 3) # == $(call prereq,3): substitution with $(1) = 3.
>
>Additional arguments use commas
>
>$(foo 1,2,3) # $(call foo,1,2,3)
>
>Now, if we define a one-letter macro, like $(p 3), we have good density.
>
>A further abbreviation facility could then perhaps be developed which
>binds dispatch characters to macros so that $(^3) can become $(prereq
>3). That only saves one
>space over $(p 3) though.
>
>Of course, without $(call ...), macros now clash in the namespace of
>predefined operators.
>If someone does this:
>
>word = whatever
>
>$(word 1,abc def) # this is the built-in, not a call of the above
>word
>
>Makefiles then run the risk of breaking because they
>used some word that is later claimed as a new built-in by
>a new version of GNU Make. Some namespace rules could be documented.
>For instance, no built-ins start with a capital letter currently
>and future ones likely won't also, so that seems like a safe space
>for defining macros. Such names clash with the reserved environment
>space in POSIX, though.
>
>Another idea might be to have some shorthand for $(call ...) like
>say $[abc x,y,z,...] <--> $(call abc,x,y,z,...).
>
>That's eerily like what I did in TXR Lisp.
>
>1> '(dwim f x y z)
>[f x y z]
>2> (car '[f x y z])
>dwim
>3> (cdr '[f x y z])
>(f x y z)
>4>
>
>
>dwim is a special dispatching operator whose name you almost never
>directly mention in any conceivable code due to the [ ] shorthand.
>It calls functions, accesses hashes, indexes into sequences like
>lists vectors and strings and also allows for LIsp-1 style
>programming in a dialect that is fundamentally Lisp-2 (separate
>variable and function namespace).
>
>E.g. (mapcar cons '(1 2 3) '(a b c)) won't work, because there
>is no cons variable, but [mapcar cons '(1 2 3) '(a b c)]
>will, because of a name lookup semantics alteration imposed by
>the dwim operator.
>
>But I digress.
>

Hah.  Brings back fond memories...I first came across dwim on Xerox Dandylion lisp machines in the 1980s.  Those machines were a joy to work on, but I preferred working on the Symbolics 3600 I "cut my teeth" on.

But *I* digress.

Thanks for your thoughts,

Malcolm