Print

Print


On 18/09/2011 10:53, Philipp Stephani wrote:
>> Part of the reasoning we had here is that \tl_new:Nn was being used
>> almost entirely for declaring constants. We have a conceptually-separate
>> \tl_const:Nn for that job.
> 
> I think both make sense, just like in other programming languages,
> where you have e.g. "const int x = ..." as well as "int x = ...".

This very much depends on the other languages you are used to. Like
Will, I guess I prefer the separate 'declare' and 'assign' operations.

>> The other part to the reasoning was that while we had \tl_new:Nn, we did
>> not have \int_new:Nn, etc. So we were not exactly consistent in that
>> regard. I guess based on the underlying TeX concept that registers have
>> to be allocated separately to assignment, it seemed easier to take a
>> similar approach to everything. (I also note that we'd have issues with,
>> for example, property lists as they can't really be created and
>> fully-assigned in one shot, at least through anything like the
>> documented interface.)
> 
> I would indeed propose having both _new:N and _new:Nn for all variable
> types. Adding them should not be a big deal (since all parts are
> already there), but simulating them manually is quite cumbersome,
> especially because variable names tend to be quite long due to the
> lack of namespaces:
> 
> \int_new:N \l_package_foo_bar_int
> \int_set:Nn \l_package_foo_bar_int { 1 + 2 }

I'm still not sure how many real use cases there are where these are not
either constants or better handled as keyval-assigned variables (where
'define' and 'set' are separate).

>>> Also a \cs_new:N command is missing which reserves a "function" name
>>> without assigning it. Both \io[rw]_new:N and \cs_new:N can essentially
>>> be aliases for \chk_if_free_cs.
>>
>> Well, they can't simply be \chk_if_free... as there has to be a
>> 'reserve' stage too. With \cs_new:N, the problem was that you don't know
>> how many arguments there may be, or in what form they could be. So you'd
>> at the least need \cs_new:Np, and then have to work out how to delimit
>> the end of the primitive argument specification. That's before you worry
>> about long and protected status (which apart from a small number of
>> tmp:w functions should not vary). So for functions I'm not sure I see a
>> gain over \cs_new(_protected)(_nopar):N(p)n.
> 
> This is only for the situation where one wants to reserve a macro name
> for later use. In fact, \cs_new:N could be \chk_if_free_cs (then it is
> irrelevant what arguments will be there—I'm using this regularly to
> make sure a certain name is not taken yet), or \cs_new_eq:NN #1 \q_nil
> or \cs_new_eq:NN #1 \prg_do_nothing:c, with different semantics.

I've got two concerns here. First, you can't simply use
\chk_if_free_cs:N, as it does not reserve the name. For example,

  \cs_set_eq:NN \cs_new:N \chk_if_free_cs:N
  \cs_new:N \test
  \cs_new:Npn \test { }

does not raise an error, even though \test has apparently already been
'taken' by \cs_new:N. Once something has been set 'new', it's supposed
to be globally defined. (There are a few internal variations on that,
for example some key properties in l3keys. We've tried to minimise these.)

Secondly, I stick by my point about arguments and so forth. With the
exception of ":w" functions, the arguments for a function should not
change. So

  \mod_foo:nn

always needs to absorb two arguments, If it performs an assignment has
to be protected, whereas if it's used in an expandable context then it
should not be protected. So using

  \cs_new...:Npn \mod_foo:nn #1#2 { }

for 'reserving' a name seems the best way to me. I don't see a gain
adding an entire set of \cs_new:N-type functions.
-- 
Joseph Wright