[ https://issues.apache.org/jira/browse/GROOVY-10259?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17420044#comment-17420044 ]
mgroovy commented on GROOVY-10259: ---------------------------------- * NameAndValue is a very small helper class that has 3 goals: ## Supply a practical/convenient default behavior for logging purposes when its toString method is called when the GString it will typically be embedded in gets converted to a String ## Support easy processing through standard Groovy string-interpolation/collect/join functionality to get custom string conversion behavior ## Support additional applications such as supplying the relevant properties of a class for one-source-of-truth, trait based hashCode/equals/compare/toString functionality ** all with a low overhead * The existing classes you mention seem imho to be too far away from this functionality to replace NameAndValue with them * Specifically with regards to NamedTuple: I have never had any case where I would have needed/wanted a map instead of a list for the name-value pairs > Groovy4 NV Macros: Rename NV* -> SV* > ------------------------------------ > > Key: GROOVY-10259 > URL: https://issues.apache.org/jira/browse/GROOVY-10259 > Project: Groovy > Issue Type: Proposal > Affects Versions: 4.0.0-beta-1 > Reporter: mgroovy > Priority: Major > > According to the release notes > ([https://groovy-lang.org/releasenotes/groovy-4.0.html]) "stringify" macros > will be released with Groovy 4, using a NV* naming convention. > I propose to change the "stringify variable" macro names from > NV/NVI/NVD > to > SV/SVI/SVD > Rationale: > * The planned Groovy4 NV macros immediately (G)Stringify their arguments, > always creating the same fixed textual representation (which cannot be > processed further in any meaningful way). > * NV is the macro name I originally proposed (and currently use), but it > returns a NameAndValue instance (see below for a slightly simplified version > of my in any case trivial NameAndValue class), instead of directly returning > a String representation > ** The NV macro name was chosen since it mirrors the name of the class it > creates, which holds the stringified expression ("name") that has been passed > to the NV macro, together with a reference to the result ("value") of > evaluating said expression, i.e. in the end holds a name together with a > value. > ** Note: A 2nd macro, NVL, in my implementation takes multiple arguments and > creates a list of NameAndValue objects, i.e. NVL(x0,x1,x2) === > [NV(x0),NV(x1),NV(x3)] > *** NV was kept to take only one argument, so additional arguments regarding > output formatting could be supported in the future. > * The returned NameAndValue objects can then be used flexibly to process > further to e.g. create regex expressions, XML, test output, etc (or log/print > directly if you like). > * Both approaches by default create the same output when converted into a > string, namely {code}NV(x) -> "x=$x"{code} > * The current Groovy4 variety trades flexibility for performance (no > intermediate NameAndValue objects are created), which is a good thing to have. > * However it blocks both concepts from coexisting while using a concise, 2 > letter macro name. > I therefore propose to change the naming convention of the Groovy 4 macros > from NV* to SV*, since it > # better expresses what happens ("stringify variable"), and > # allows for the name & value pairs of the (more flexible/powerful) NV* > macro and NameAndValue class to coexist with it. > Basic NameAndValue class: > {code:java} > class NameAndValue<T> { > final String name > final T val > NameAndValue(String name, val) { > this.name = name > this.val = val > } > @Override > String toString() { > "$name=$val" > } > } > {code} > NameAndValue class I actually use (with quote functionality): > {code:java} > class NameAndValue<T> { > final String name > final T val > static <T0> NameAndValue<T0> nava(String name, T0 val) { > new NameAndValue<T0>(name, val) > } > NameAndValue(String name, val) { > this.name = name > this.val = val > } > String quote(final Object o) { > if(null == o) { > return null > } > else if(o instanceof GString) { > return '"' + o + '"' > } > else if(o instanceof String) { > return "'" + o + "'" > } > else if(o instanceof Character) { > return "C'" + o + "'" > } > else { > try { > return o.toString() > } > catch(Throwable throwable0) { > try { > return > "NV(${o.getClass().simpleName}.toString() threw > ${throwable0.getClass().simpleName})" > } > catch(Throwable throwable1) { > return "NV(o.getClass() threw > ${throwable1.getClass().simpleName})" > } > } > } > } > @Override > String toString() { > "$name=${quote(val)}" > } > } > {code} -- This message was sent by Atlassian Jira (v8.3.4#803005)