Groovy compiler fails for nested omitted parentheses in method calls - methods

In Groovy, parentheses can be omitted when there is no ambiguity. However, the groovy compiler fails for this piece of code:
def firstChar(String str) { str[0] }
println " ".split(firstChar " ")
I have troubles understanding what is ambiguous here. The error is as follows:
Groovyc: Unexpected input: '"".split(firstChar " "'
In my actual use-case, the error reports completely unrelated element. For this code:
existingInputFile.withReader { reader ->
def outputFile = new File(/name.txt/)
outputFile.createNewFile()
outputFile.withWriter { writer ->
writer.write reader.lines()
.map { line -> line.split " " }
.map { line -> "${line.head()} ${line[1]}}" }
.collect(Collectors.joining "\n")
}
}
It complains about:
Groovyc: Unexpected input: '{'
pointing out to the very first line of the above snippet.
As you can see, I have a "nested" omitted parentheses in a method call in form of writer.write and Collectors.joining.
Is this a compiler bug or can something like that really be ambiguous?

I would use a "standard" Groovy to fulfill your use-case:
// the slashy string should be used for regex only
new File('name.txt').withWriter { writer ->
existingInputFile.splitEachLine( / / ){ __, first, second ->
writer.write "$first $second\n"
}
}
without meddling with stream api and groovyc tricks.

Related

Cannot invoke method multiply() on null object groovy

Consider below code
task circle {
doLast {
float r = Float.parseFloat(project.properties["radius"])
println (22/7)*(r ** 2)
}
}
task square {
doLast {
float s = Float.parseFloat(project.properties["side"])
println s*s
}
}
This give error as Cannot invoke method multiply() on null object
If I change the above code as below then it goes fine
task circle {
doLast {
float r = Float.parseFloat(project.properties["radius"])
println 22/7*(r ** 2)
}
}
task square {
doLast {
float s = Float.parseFloat(project.properties["side"])
println s*s
}
}
What could be the reason?
The problem here is the missing parens for the actual println, that
will lead to the following code being executed (println(22/7))*(r ** 2). The println is done first and its result (void) becomes
null. And then it throws the error you are seeing. Your "not-throwing"
example nudges the parser in the right direction.
Parens in groovy are "optional if unambiguous", which is quite a broad
term. Granted, that this got better with the new parrot-parser, you
will often see things like this blow up. Simple rule of thumb: just
don't leave out the parens for calling functions unless you are dealing
with a trivial term.

Rust proc_macro_derive (with syn crate) generating enum variant for matching

I'm a rust newbie, I started one week ago but this language is already very exciting. I'm rewritting a nodejs project in rust to get better performance and for the moment it's just crazy how faster it is.
I'm actually writting a proc_derive_macro (using the "syn" crate) to generate method on some specific struct. I'm almost done but i don't find how to generate enum variant. I will try to explain myself.
That's my code generation (using quote!)
quote! {
// The generated impl.
impl #name /*#ty_generics #where_clause*/ {
pub fn from_config(config: &IndicatorConfig) -> Result<Self, Error> {
let mut #name_lower = #name::default()?;
for (k, v) in config.opts.iter() {
println!("{:?} {:?}", k, v);
match (k.as_str(), v) {
("label", Values::String(val)) => {
#name_lower.label = val.clone();
}
("agg_time", Values::String(val)) => {
#name_lower.agg_time = Some(val.clone());
}
#(
(#fields_name_str, Values::Unteger(val)) => {
#name_lower.#fields_name = val.clone();
}
)*
(&_, _) => {}
}
}
#name_lower.init()?;
Ok(#name_lower)
}
}
};
As we can see I'm generating much of my code here
(#fields_name_str, Values::Unteger(val)) => {
#name_lower.#fields_name = val.clone();
}
But I didn't find a way to generate an "enum variant for the matching" (I don't know how we call that, i hope you will understand):
Values::String(val)
OR
Values::Unteger(val)
...
I'm writting a function which will create the variant matching according to parameter type found inside the struct:
fn create_variant_match(ty: &str) -> PatTupleStruct {
let variant = match ty {
"u32" => Ident::new("Unteger", Span::call_site()),
...
_ => unimplemented!(),
};
}
Actually I'm creating an Ident but I want to create the "enum variant match" -> Values::Unteger(val).
I watched the doc of the syn crate, spend hours trying to find a way, but it's a bit complex for my actual level, so I hope someone will explain me how to do that.
I found a simple way of doing that. Just need to parse a string (which i can format before) using the syn parser.
Didn't think about it before was trying to construct the Expr by hand (a bit stupid ^^)
syn::parse_str::<Expr>("Values::Unteger(val)")
which will generate the Expr needed

What does Some() do on the left hand side of a variable assignment?

I was reading some Rust code and I came across this line
if let Some(path) = env::args().nth(1) {
Inside of this function
fn main() {
if let Some(path) = env::args().nth(1) {
// Try reading the file provided by the path.
let mut file = File::open(path).expect("Failed reading file.");
let mut content = String::new();
file.read_to_string(&mut content);
perform_conversion(content.as_str()).expect("Conversion failed.");
} else {
println!(
"provide a path to a .cue file to be converted into a MusicBrainz compatible tracklist."
)
}
}
The line seems to be assigning the env argument to the variable path but I can't work out what the Some() around it is doing.
I took a look at the documentation for Option and I understand how it works when used on the right hand side of = but on the left hand side I am a little confused.
Am I right in thinking this line is equivalent to
if let path = Some(env::args().nth(1)) {
From the reference :
An if let expression is semantically similar to an if expression but
in place of a condition expression it expects the keyword let followed
by a refutable pattern, an = and an expression. If the value of the
expression on the right hand side of the = matches the pattern, the
corresponding block will execute, otherwise flow proceeds to the
following else block if it exists. Like if expressions, if let
expressions have a value determined by the block that is evaluated.
In here the important part is refutability. What it means refutable pattern in here it can be in different forms. For example :
enum Test {
First(String, i32, usize),
Second(i32, usize),
Third(i32),
}
You can check the x's value for a value for 3 different pattern like :
fn main() {
let x = Test::Second(14, 55);
if let Test::First(a, b, c) = x {}
if let Test::Second(a, b) = x {} //This block will be executed
if let Test::Third(a) = x {}
}
This is called refutability. But consider your code like this:
enum Test {
Second(i32, usize),
}
fn main() {
let x = Test::Second(14, 55);
if let Test::Second(a, b) = x {}
}
This code will not compile because x's pattern is obvious, it has single pattern.
You can get more information from the reference of refutability.
Also you are not right thinking for this:
if let path = Some(env::args().nth(1)) {
Compiler will throw error like irrefutable if-let pattern because as the reference says: "keyword let followed by a refutable pattern". In here there is no refutable pattern after "let". Actually this code tries to create a variable named path which is an Option and this make no sense because there is no "If" needed,
Instead Rust expects from you to write like this:
let path = Some(env::args().nth(1)); // This will be seem like Some(Some(value))
The other answers go into a lot of detail, which might be more than you need to know.
Essentially, this:
if let Some(path) = env::args().nth(1) {
// Do something with path
} else {
// otherwise do something else
}
is identical to this:
match env::args().nth(1) {
Some(path) => { /* Do something with path */ }
_ => { /* otherwise do something else */ }
}

Throw error for unclosed comment block javacc

I am creating a lexer in javacc that skips block comments that start with /* and end with */. I have it working correctly for valid block comments but I am trying to figure out a way to throw an error when a block comment is unclosed...
Example:
/* this is not a valid block comment
/* this is a valid block comment*/
Here is what I have to skip valid block comments:
MORE: { <"/*"> : BLC_CMNT_ST}
<BLC_CMNT_ST> SKIP: { <"*/">: DEFAULT >
<BLC_CMNT_ST> MORE: { <~[]>}
Currently when I run the lexer a TokenMgrError is thrown when there is unclosed block comment. I would like to catch this error and/or throw my own error that displays the matchedToken.image. I have tried a few different ways but have ran into issues so any help would be greatly appreciated
How about
SKIP: { <"/*"> : BLC_CMNT_ST}
<BLC_CMNT_ST> SKIP: { "*/" : DEFAULT }
<BLC_CMNT_ST> SKIP: { < ~[] > }
<*> TOKEN : { <EOF>
{ System.out.println("Lexical state is " + curLexState ) ;
if(curLexState==BLC_CMNT_ST) throw new Error("Unmatched comment at end of file.") ; } }
I had to use SKIP instead of MORE for reasons I don't fully understand.
If you want to disallow "/*" inside of block comments you can add this production
<BLC_CMNT_ST> TOKEN: { < "/*" >
{ if(true) throw new Error("Unmatched comment at line "
+ matchedToken.beginLine
+ ", column "
+ matchedToken.beginColumn + ".") ; } }
Unfortunately this solution does not give you access to the image of the comment.

Slow Scala assert

We've been profiling our code recently and we've come across a few annoying hotspots. They're in the form
assert(a == b, a + " is not equal to " + b)
Because some of these asserts can be in code called a huge amount of times the string concat starts to add up. assert is defined as:
def assert(assumption : Boolean, message : Any) = ....
why isn't it defined as:
def assert(assumption : Boolean, message : => Any) = ....
That way it would evaluate lazily. Given that it's not defined that way is there an inline way of calling assert with a message param that is evaluated lazily?
Thanks
Lazy evaluation has also some overhead for the function object created. If your message object is already fully constructed (a static message) this overhead is unnecessary.
The appropriate method for your use case would be sprintf-style:
assert(a == b, "%s is not equal to %s", a, b)
As long as there is a speciaized function
assert(Boolean, String, Any, Any)
this implementation has no overhead or the cost of the var args array
assert(Boolean, String, Any*)
for the general case.
Implementing toString would be evaluated lazily, but is not readable:
assert(a == b, new { override def toString = a + " is not equal to " + b })
It is by-name, I changed it over a year ago.
http://www.scala-lang.org/node/825
Current Predef:
#elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}
Thomas' answer is great, but just in case you like the idea of the last answer but dislike the unreadability, you can get around it:
object LazyS {
def apply(f: => String): AnyRef = new {
override def toString = f
}
}
Example:
object KnightSpeak {
override def toString = { println("Turned into a string") ; "Ni" }
}
scala> assert(true != false , LazyS("I say " + KnightSpeak))
scala> println( LazyS("I say " + KnightSpeak) )
Turned into a string
I say Ni
Try: assert( a==b, "%s is not equals to %s".format(a,b))
The format should only be called when the assert needs the string. Format is added to RichString via implicit.

Resources