You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by MG <mg...@arscreat.com> on 2021/09/24 17:45:23 UTC

Groovy 4 NV* Macros: NV -> SV

Hi,

I propose to change the "stringify variable" macro names in Groovy 4 from
NV/NVI/NVD
to
SV/SVI/SVD

Rationale:
I just saw in the Groovy 4 release notes 
(https://groovy-lang.org/releasenotes/groovy-4.0.html) that a variety of 
the "Named Variable" macros (which I have been using extensively in my 
code for some time now) are officially coming to Groovy, which is great G-)

The only thing I am not happy with is the names chosen, for the 
following reasons:

 1. NV and NVL are the macro names I currently use, and they return a
    single or a list of NameAndValue class instances respectively.
 2. I could of course change my name, but it expresses perfectly what
    happens: You get NameAndValue objects with name and val fields,
    which you can then use flexibly to process further to e.g. create
    regex expressions, XML, test output, etc (or log/print directly if
    you like).
 3. What the planned Groovy 4 NV/... macros do instead is basically
    (G)Stringify their arguments, always creating the same fixed textual
    representation (which cannot be processed further in any meaningful
    way).
     1. Both approaches by default create the same or very similar
        output when converted into a string, namely NV(x) -> "x=$x"
     2. The currently proposed Groovy 4 variety trades flexibility for
        efficiency (no intermediate NameAndValue objects are created),
        so I understand why this approach has been favored.
     3. However it blocks having both concepts from coexisting while
        using a concise, 2/3 letter syntax.

I therefore propose to change the naming convention of the Groovy 4 
macros from NV* to SV*, since it a) better expresses what happens 
("stringify"), and b) allows for the name pairs of the (more 
flexible/powerful) NV* macro and NameAndValue class to coexist with it.

Cheers,
mg


PS: I would also propose for Groovy to actually support both approaches, 
since I see them as orthogonal to each other, serving different 
purposes, but that is a different topic G-)
PPS: Here is another example, using NVL macros to create input -> result 
test output:

@Test
void oracleOffsetFetchSql() {
     final sqb = createSqlBuilder()
     final p = Table.reference(PersonTestTable.it)

     // NVL macro used here, which creates a list of NameAndValue 
objects holding the stringified passed expressions and their resprective 
resulting value
     final List<NameAndValue> resultList = NVL(
           sqb.oracleOffsetFetchSql(null, 13),
           sqb.oracleOffsetFetchSql(73, 999),
           sqb.takeStartingAtSql("select $p.LAST_NAME from $p order by 
$p.EID_IDH", 654, 321),
           sqb.takeSql("select $p.FIRST_NAME from $p order by $p.SEX", 123)
       )

     // NameAndValue objects stored in resultList and combined to a 
string representation in a non-standard way
     final String result = resultList.collect { 
renumberReferenceNamesSql("$it.name: $it.val") }.join('\n')
     tetd.exportOrAssertTestResult("oracleOffsetFetchSql", result, 9999)
}

which creates the resulting test string:

sqb.oracleOffsetFetchSql(null, 13): fetch next 13 rows only
sqb.oracleOffsetFetchSql(73, 999): offset 73 rows fetch next 999 rows only
sqb.takeStartingAtSql(select $p.LAST_NAME from $p order by $p.EID_IDH, 
654, 321): select ps0.LAST_NAME from PERSON ps0 order by ps0.EID_IDH 
offset 654 rows fetch next 321 rows only
sqb.takeSql(select $p.FIRST_NAME from $p order by $p.SEX, 123): select 
ps0.FIRST_NAME from PERSON ps0 order by ps0.SEX fetch next 123 rows only