Received: from mout.gmx.net (mout.gmx.net [212.227.15.18]) by h1439878.stratoserver.net (8.14.2/8.14.2/Debian-2build1) with ESMTP id r6GHSk54023603 for ; Tue, 16 Jul 2013 19:28:47 +0200 Received: from relay2.uni-heidelberg.de ([129.206.210.211]) by mx-ha.gmx.net (mxgmx112) with ESMTP (Nemesis) id 0MC8OC-1UqNcu2Z6m-008rzQ for ; Tue, 16 Jul 2013 19:28:40 +0200 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [129.206.100.94]) by relay2.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id r6GHPl85017110 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 16 Jul 2013 19:25:48 +0200 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [127.0.0.1]) by listserv.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id r6GDGSGw022061; Tue, 16 Jul 2013 19:25:47 +0200 Received: by LISTSERV.UNI-HEIDELBERG.DE (LISTSERV-TCP/IP release 16.0) with spool id 10310215 for LATEX-L@LISTSERV.UNI-HEIDELBERG.DE; Tue, 16 Jul 2013 19:25:47 +0200 Received: from relay2.uni-heidelberg.de (relay2.uni-heidelberg.de [129.206.210.211]) by listserv.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id r6GHPlPc011745 for ; Tue, 16 Jul 2013 19:25:47 +0200 Received: from mail-pd0-f170.google.com (mail-pd0-f170.google.com [209.85.192.170]) by relay2.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id r6GHPa6S017059 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=FAIL) for ; Tue, 16 Jul 2013 19:25:39 +0200 Received: by mail-pd0-f170.google.com with SMTP id x11so902878pdj.15 for ; Tue, 16 Jul 2013 10:25:35 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.66.26.179 with SMTP id m19mr3713525pag.4.1373995535173; Tue, 16 Jul 2013 10:25:35 -0700 (PDT) Received: by 10.66.150.226 with HTTP; Tue, 16 Jul 2013 10:25:35 -0700 (PDT) References: Content-Type: text/plain; charset=ISO-8859-1 Message-ID: Date: Tue, 16 Jul 2013 13:25:35 -0400 Reply-To: Mailing list for the LaTeX3 project Sender: Mailing list for the LaTeX3 project From: Bruno Le Floch Subject: Re: Request for argument specifiers which generate unique csnames To: LATEX-L@LISTSERV.UNI-HEIDELBERG.DE In-Reply-To: Precedence: list List-Help: , List-Unsubscribe: List-Subscribe: List-Owner: List-Archive: Envelope-To: X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3; X-GMX-Antivirus: 0 (no virus found) X-UI-Filterresults: notjunk:1;V01:K0:pmSPnx5Za7o=:47P6W9dXGElzs8xiVwr8fh cNreY3ustPlx2orL6vzbYsIdWlceEF76Ygj/fc1qf+mAHVLa68ofHefBZdMAZt/gWCRDSFr yMpmkFTWCO3nUJ5DHffyYCQvr3xjlau6zZN478uobHKRnpnYJT3sou4l4qobhDUyzds1hrR lrRnZacQ8t0SnhuV7vRunLgJafSOHmH/qvC7cWo0k4/YgDms9rq2wKo/W0Mzq28z3Xd/aYI 1VAiDrruqWxIppjqnoNlHrCYWKoXhwu86jV00zS7VSpGrySNclSybvj+9HrKKnNbwGBFUU9 /0GvwR69OFGd0ZDc2etACluxKN7IYPwyliiUjiUe02g60zYQfoiWr8PgTWOZ58lMrmRwHKC 4Myeaybug2wVat5W1cWh8xLzRpLqNBO+3npZ7Dl0/CjfNW2KSNAjd6wKvzqBY9e0G5v/HQ9 M9AgObHEM7jlhymBNAe3D4IgsB7ZdNtkcZdht+B1s7EsQq82JFpOdmFOKIW0BvL21b2YQBa 4q9y9FoICnG6BdwOba/YsG4wQiZCcgBpwc85+VWLbUEKzeOL9yLWFtOvM3cg6aLbXzJe/Si pG9vMoiTRW1dc0j9onC5O9c4pfWdRI/Nf2hszdLQBQ/SW8j8i1i0uYWpi7tBBwwjw1GQpnW RE3a7ByyQzfVDxa8Q7I01gjdTJXlxOTbIOJB2EYWibDn/WrP6GR45ro+orZvx6xtgEaaRLY F/2Be4wT0cJolPDc26mSxIeaPv1cCfYvniz2/Ahf8DUXhyB5WlB+pCeiQiiykpk6YtQ7fuq szGuiaPBM1KMfoxgyH6fGMkklLvZUyE+o4vGl3+AVw7T7V77/1y61va7R/v9kIyzfJdQtxc tEd+kdiyjJvdVVwMBRkbk1POznZ0LfEYnKThFwWulYOQJlreDOjyAUHMYsPttEAZbia/T4w RToMqtiHyp8Q/V95V/VGwq6x74z3BlFjZ/BFLwwCAwZ0qXrm/UGe6aMJ5dMkHSXRKdqKIuv 08LT3z2hEChX1N5cD4zt+VAQX3az75yTCPoWIL8VKGYmpJvjvBAmlyl/oPicfSBQOXPGvnb zFiOHvwFZ8GLCHWPSGS0WvI7l8nW71D45haCW8wC+C/MgoCJJKl0ao0iB0//VIKWLi2/rsn +AfYGosj6YGlqbQH1QXdNuGwOFcoQQZwS3HWKJ/A/Ier7BJP8PEacYZ1f+JAKWVoTGrZZAa kmEuGFNvb1vQrOYh0jS2PqUjhpNWS4TeXTEvBK0ZyoUW+r1SZ2RFoEnMlD2VsU1IKAEa1j2 dP+BaTzJSvUDhWju6gA611yBjVBPJ8IIq017xeeO8egC8+eOivUNyaVvOiScwQEW7S3n+HH XAaM1CUnRNPk3oIGh/UfOZZOv2EESrmon6iLa/M9dTq9TR0RrQKVUhwvYMkHsYqnMTBG4Om +dVP/iTbCmbeOwH5Nx7Ewt9VsZWCk9+VTtPG8i8Vs/B5mxNZ2DO9riXF8zMMTcsAq+GApPB SpzbKaNS2L8pmqq1jd3iLc9jeUn+x/2itQrc0BgHK1zm41Xy4LF58N0WUsT6g+k+gdXVfyV gu5FtZ+9K9eMJx3+usFzT0iSlIuCHxwACni8jerja2sPdw1y/sBlvfFDoUo= X-UI-Loop:V01:onczcVwVqfU=:BYSCxtjQ2K9pgEvrg29lic3bXF4lqWUg24o/Jp9TOuc= Status: R X-Status: X-Keywords: X-UID: 7246 Hello Michiel, It is indeed useful to have unique csnames generated automatically. However, the need is sufficiently rare that it does not warrant adding a new variant letter: this is expensive, since each function would need a new variant, hence a new entry in TeX's hash table, and this adds up pretty quickly to a very large number of csnames spent, slowing TeX down. Furthermore, none of the variant types perform any assignment (with the exception of 'x', which only modifies an internal LaTeX3 variable, and within a group), hence we can rest safely assured that using \exp_args:... (or the \cs_generate_variant mechanism) to expand an argument will always yield the same result (barring two exceptions, random numbers generated with \pdfuniformdeviate and the like, and pretty elaborate code involving \csname and \ifcsname, as is done in l3fp). The proposed 'U' argument type would be altering the variable appearing as the corresponding argument, which is quite contrary to anything that any other argument type does. > \tl_new:N \l__something_map_csname_tl > \cs_new_protected:Nn \something_map_inline:Nn { > \cs_set:Upn \l__something_map_csname_tl ##1##2 {#2} > \something_map_function:Nc #1 \l__something_map_csname_tl > } I find it much more natural to provide a function which creates a unique name and stores it in its argument, along the lines of \cs_new_protected:Nn \something_map_inline:Nn { \unique_csname:N \l__something_map_csname_tl \cs_set:cpn { \l__something_map_csname_tl } ##1##2 {#2} \something_map_function:Nc #1 { \l__something_map_csname_tl } } This approach is good for cases where one wants a unique name which is used over a long span of time. I will focus on the case of defining a map_inline function, but I am interested to see other situations where such unique names are useful. In the case of map_inline, and whenever there is a need for short-lived unique identifiers, \unique_csname:N will lead to memory leaks. Indeed, \unique_csname:N has no way to know when a given unique name is not used anymore. This means that every time the map_inline function is called, a new unique csname is used. TeX will run out of hash table space relatively fast if the loop is called a few thousand times in the document (which, at least for kernel loops, is not unreasonable). Even worse, if we generate names simply by incrementing a counter, given the algorithm used by TeX to hash csnames, all of the unique names will hash to one of 30 or so different values, leading to a vast amount of hash collisions, hence slow down. I don't know how bad it is, but I believe it is not to be neglected before adding such a \unique_csname:N function. The kernel mapping functions do it differently, by incrementing a counter before constructing a csname and decrementing it after the loop (actually, the kernel is not quite consistent there, but it works and I don't yet have a very clean solution). This could be wrapped into something like \cs_new_protected:Nn \something_map_inline:Nn { \unique_csname:N \l__something_map_csname_tl \cs_set:cpn { \l__something_map_csname_tl } ##1##2 {#2} \something_map_function:Nc #1 { \l__something_map_csname_tl } \unique_free:V \l__something_map_csname_tl } where we explicitly free, in the eyes of the \unique_... functions, the unique identifier provided by \unique_csname:N. This does not leak memory anymore. Alternatives which require less typing (and don't require defining a tl variable \l__something_map_csname_tl) include \cs_new_protected:Nn \something_map_inline:Nn { \unique_csname:n { \cs_set:cpn {##1} ####1####2 {#2} \something_map_function:Nc #1 {##1} } } \cs_new_protected:Nn \something_map_inline:Nn { \unique_csname:n { \cs_set:cpn { \l_unique_tl } ##1##2 {#2} \something_map_function:Nc #1 { \l_unique_tl } } } The first one is a bit confusing since # does not need doubling, but ## does become ####. The second one is a bit risky since one can only use \l_unique_tl before any other \unique_csname:n is called: here it is safe because \cs_set:cpn does not use \unique_csname:n. However, in the context of defining mapping functions, none of the above are good enough. None of them let us provide \something_map_break:n {} that safely breaks out of both map_function:NN and of map_inline:Nn without leaving any token after in the input stream. Indeed, the map_break:n breaks out of the map_function, but there remain tokens left by \unique_csname:n to reclaim the looping function name as free. This is why the kernel map_inline do not call the corresponding map_function. The two user functions are typically implemented in terms of a common auxiliary, with a sentinel (\__prg_break_point:Nn IIRC) whose n argument stands for some code which cleans up the loop (and reclaims the used unique name) and is inserted before the argument of map_break:n. I don't know how to give this a nice wrapper. In fact, perhaps the right approach is that I revive some ideas I had about objects. Mapping a function then amounts to repeatedly popping the first item and acting with the function. I roughly see how to write a wrapper for that, which would mean that the package writer would not need to worry about defining the mapping function: rather he would define a \something_get:N or \something_pop:NN function, and the framework would do the work of defining map_function and map_inline. This is a longer term idea. In any case, most of the above concerns specifically the application of your idea to defining map_inline. If you have more examples where unique identifiers are useful, it would be very helpful to give them, so as to either find alternatives or get a better view of what would be needed. > (https://code.google.com/p/latex-with/source/browse/trunk/with.sty). Can you give a short example of use of that package? I'm curious, and slightly too lazy to figure out the code. :-) More on your other point in a separate thread. Regards, Bruno