I am learning Groovy and am pretty impressed with how it allows one to build a intelligent DSL, but I am a bit confused by the rules for when parentheses and dots are optional. Consider the following code:
Integer take(Integer x) {x}
take 3 plus 4
This works as expected and produces an output of 7 (when ran in the console), as groovy understands that last line as take(3).plus(4).
Now, println take 3 plus 4 does not work as groovy understands that as println(take).3(plus).4 which is nonsense.
Every example that I am seeing shows these sort of expression by themselves on a line, but apparently
s = take 3 plus 4
works and stores the result 7 in s. My question is, why does
println( take 3 plus 4 )
not work? Obviously, groovy will parse these sort of expressions even if they are not by themselves on a line (as shown by the assignment working). I would have thought that adding those parentheses would remove the ambiguity from the form of that line that doesn't work and that it would print out 7 as I intended.
Instead groovy gives an error 'unexpected token: 3'. As far as I can tell, groovy will not allow optional parentheses or dots inside that println, even though it doesn't seem to be ambiguous. When exactly does this sort of trick work?
This falls into the category of a nested method call, and in that case you cannot omit the parentheses. This is causing ambiguity and the results are unexpected, as the println method thinks you are passing it multiple parameters. You could reduce the ambiguity by using a groovy string in the println method.
println "${take 3 plus 4}"
More info: Omit Parentheses
Related
I found this in Groovy Syntax documentation at 4.6.1. Special cases:
As slashy strings were mostly designed to make regexp easier so a few
things that are errors in GStrings like $() or $5 will work with
slashy strings.
What $() syntax means? give some usage examples please
I also found it at Define the Contract Locally in the Repository of the Fraud Detection Service:
body([ // (4)
"client.id": $(regex('[0-9]{10}')),
loanAmount : 99999
])
but I don't understand what $() means when used with regex('[0-9]{10}').
It means nothing (or what you make of it). There are two places, you
are addressing, but they have nothing to do with each other.
The docs just mention this as "you can use slashy strings to write
things, that would give you an error with a GString" - the same is true
for just using '-Strings.
E.g.
"hello $()"
Gives this error:
unknown recognition error type: groovyjarjarantlr4.v4.runtime.LexerNoViableAltException
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/tmp/x.groovy: 1: token recognition error at: '(' # line 1, column 9.
"hello $()"
The parser either wants a { or any char, that is a valid first char
for a variable (neither ( nor 5 is).
The other place you encountered $() (in Spring cloud contract), this
is just a function with the name $.
Form the docs 8. Contract DSL:
You can set the properties inside the body either with the value method or, if you use the Groovy map notation, with $()
So this is just a function, with a very short name.
E.g. you can try this yourself:
void $(x) { println x }
$("Hello")
Trying to understand how "%s%s" %(a,a) is working in below code I have only seen it inside print function thus far.Could anyone please explain how it is working inside int()?
a=input()
b=int("%s%s" %(a,a))
this "%s" format has been borrowed from C printf format, but is much more interesting because it doesn't belong to print statement. Note that it involves just one argument passed to print (or to any function BTW):
print("%s%s" % (a,a))
and not (like C) a variable number of arguments passed to some functions that accept & understand them:
printf("%s%s,a,a);
It's a standalone way of creating a string from a string template & its arguments (which for instance solves the tedious issue of: "I want a logger with formatting capabilities" which can be achieved with great effort in C or C++, using variable arguments + vsprintf or C++11 variadic recursive templates).
Note that this format style is now considered legacy. Now you'd better use format, where the placeholders are wrapped in {}.
One of the direct advantages here is that since the argument is repeated you just have to do:
int("{0}{0}".format(a))
(it references twice the sole argument in position 0)
Both legacy and format syntaxes are detailed with examples on https://pyformat.info/
or since python 3.6 you can use fstrings:
>>> a = 12
>>> int(f"{a}{a}")
1212
% is in a way just syntactic sugar for a function that accepts a string and a *args (a format and the parameters for formatting) and returns a string which is the format string with the embedded parameters. So, you can use it any place that a string is acceptable.
BTW, % is a bit obsolete, and "{}{}".format(a,a) is the more 'modern' approach here, and is more obviously a string method that returns another string.
Basically in python 3.0 I tried to use two %s string substitutes and concatenate it. However, it seems to produce an error.
CODE
print "%s"+"%s" %("John", "rows")
I am new to programming so I would be thankful if I could get a simple explanation.
Thanks
In python-2.x, which appears to be the language that line of code was written in (you treated print as a statement), you will get an error TypeError: not all arguments converted during string formatting.
This is because the interpreter attempts to put both of the arguments into the latter string, due to the order of operations. Thus, simply wrap the string with parentheses and the code will run:
>>> print ("%s"+"%s") %("John", "rows")
Johnrows
>>>
I read a lot about AST Transformation these days and now I want to handle some arbitrary literals not known by groovy. The specific idea is to enable groovy handling plain sql.
If you write select a from tab where b = 'x' in GroovyConsole, the AST looks like this at some point
MethodCall - this.select(a).from(tab).where((b = x))
With some effort, it should be possible to turn this into a sql-statement.
So everything is fine as long as I don't use an asterisk.
If I write select * from tab no AST can be built (no matter what phase) and an error occures:
Unable to produce AST for this phase due to earlier compilation error:
startup failed:
script123.groovy: 1: expecting EOF, found 'tab' # line1, column 15.
So here's the question:
How can I turn the asterisk into something processable?
I tried to get the CST after parsing was done. But it's always null and I couldn't find out why.
But I found another approach:
http://java.dzone.com/articles/run-your-antlr-dsl-groovy
this is a fairly general question about whether people should be using brackets on method calls that take parameters or not.
i.e.
def someFunc(def p) {
...
}
then calling:
someFunc "abc"
vs...
someFunc("abc")
Is this just a question of consistency, or is there specific use cases for each?
It's primarily a question of consistency and readability, but note that Groovy won't always let you get away with omitting parentheses. For one, you can't omit parentheses in nested method calls:
def foo(n) { n }
println foo 1 // won't work
See the section entitled "Omitting parentheses" in the Style guide.
There's no specific case where you must remove them, you can always use them. It's just prettier to leave them out.
There are cases where you can't do that (where you could confuse a list/map parameter with a subscript operator for instance, nested calls, or when the statement is an assignment), but the general rule is that the outmost call can have no parenthesis if there is no ambiguity.
(deleted several lines, as I've just received notification that there is a post already with that info)
Groovy 1.8 will allow even more cases to omit parenthesis, you can check them out at
http://groovyconsole.appspot.com/script/355001
"an empty pair of parentheses is just useless syntactical noise!"
It seems to me that they are encouraging you to use parenthesis when they serve a purpose, but omit them when they are just "noise"