I remember from my Perl days the "use strict" statement that cause the runtime to do extra validations. Is there an equivalent for Groovy?
I do not enjoy being bitten during runtime by what can be detected on compilation, like passing too few arguments to a constructor.
Groovy 2.0 now has optional static type checking. If you place a #groovy.transform.TypeChecked annotation on a class or method, groovy will use strict, Java-like static typing rules.
In addition, there's another annotation #groovy.transform.CompileStatic that is similar, except it goes a step further and actually compiles it without dynamic typing. The byte code generated for these classes or methods will be very similar to straight Java.
These annotations can be applied to an individual class or method:
import groovy.transform.TypeChecked
#TypeChecked
class MyClass {
...
}
You can also apply them globally to an entire project without adding annotations to the source files with a compiler config script. The config script should look something like this:
withConfig(configuration) {
ast(groovy.transform.TypeChecked)
}
Run groovy or groovyc with the -configscript command line option:
groovyc -configscript config.groovy MyClass.groovy
There's more information in the Groovy manual:
http://groovy-lang.org/semantics.html#static-type-checking
http://groovy-lang.org/semantics.html#_static_compilation
Is there an equivalent for Groovy?
Not that I know of.
I do not enjoy being bitten during
runtime by what can be detected on
compilation, like passing too few
arguments to a constructor.
Then Groovy is probably the wrong language for you and you should use something like Java or C# instead. Alternatively, there is a version of Groovy, known as Groovy++ which has much stronger type-checking, but I don't consider it sufficiently mature for production use.
IntelliJ (and possibly other IDEs) provides a lot of warnings about dodgy Groovy code. Although these warnings don't prevent compilation, they almost give you the best of both worlds, i.e. the safety of a static language and the flexibility of a dynamic language
No, there is no such thing, and there can't be. Perl's "use strict" only prevents the use of undeclared variables (and some very Perl-specific things that I don't think have equivalents in Groovy).
In dynamic languages like Groovy, "passing too few arguments to a constructor" is fundamentally not something the compiler can detect, because class definitions can be changed at runtime via metaprogramming. Also, you usually don't have the type information necessary to know what class to look at.
If you want maximum compile-time checks, use a statically typed language with no metaprogramming, i.e. Java.
Related
I'd like to take advantage of #CompileStatic annotation in my groovy scripts in jmeter environment. It helps a lot to discover issues in compile time.
I already started to use it in my classes but I don't know how to use it in case of plain groovy scripts. For example, I have the script below and there are the log and vars variables which are kind of global variables in JMeter environment. So, eventually they will be used.
If I add the #CompileStatic annotation to the method below IntelliJ paints red everything and compile will fail because the compiler doesn't know what these variables are.
So, the question is how to tell the compiler in a case of a script these variables has type and what type they have, and how an instance will be provided for the script?
I apologize, I'm not a groovy expert at all.
void checkingInputParameters() {
log.info("variable value:" + vars.get("some_variable_name"))
}
checkingInputParameters()
I think you are in the wrong path,
because CompileStatic is a groovy compiler option
let the Groovy compiler use compile time checks in the style of Java then perform static compilation, thus bypassing the Groovy meta object protocol.
JMeter (and I assume your tests in Intellij ) is using a java compiler
I don't think you should mix them for tests.
In JMeter use Cache compiled checkbox/feature
checking Cache compiled script if available
Is it possible to get a list of all the arguments a constructor takes?
With the names and types of the parameters?
I want to automatically check the values of a JSON are good to use for building their equivalent as a class instance.
Preferably without macros... I have build a few, but I still find them quiet confusing.
Must work with neko and JS, if that maters.
Thanks.
I think you want to look at Runtime Type Information (rtti)
From the Haxe Manual: The Haxe compiler generates runtime type information (RTTI) for classes that are annotated or extend classes that are annotated with the #:rtti metadata. This information is stored as a XML string in a static field __rtti and can be processed through haxe.rtti.XmlParser. The resulting structure is described in RTTI structure.
Alternative; If you want to go with macros, this might be a good start
http://code.haxe.org/category/macros/add-parameters-as-fields.html
I've been tasked with creating conformance tests of user input, the task if fairly tricky and we need very high levels of reliability. The server runs on PHP, the client runs on JS, and I thought Haxe might reduce duplicative work.
However, I'm having trouble with deadcode removal. Since I am just creating helper functions (utilObject.isMeaningOfLife(42)) I don't have a main program that calls each one. I tried adding #:keep: to a utility class, but it was cut out anyway.
I tried to specify that utility class through the -main switch, but I had to add a dummy main() method and this doesn't scale beyond that single class.
You can force the inclusion of all the files defined in a given package and its sub packages to be included in the build using a compiler argument.
haxe --macro include('my.package') ..etc
This is a shortcut to the macro.Compiler.include function.
As you can see the signature of this function allows you to do it recursive and also exclude packages.
static include (pack:String, rec:Bool = true, ?ignore:Array<String>, ?classPaths:Array<String>):Void
I think you don't have to use #:keep in that case for each library class.
I'm not sure if this is what you are looking for, I hope it helps.
Otherwise this could be helpful checks:
Is it bad that the code is cut away if you don't use it?
It could also be the case some code is inlined in the final output?
Compile your code using the compiler flag -dce std as mentioned in comments.
If you use the static analyzer, don't use it.
Add #:keep and reference the class+function somewhere.
Otherwise provide minimal setup if you can reproduce.
I know that since Groovy 2.0 there are annotations for static compilation.
However it's ease to omit such annotation by accident and still run into troubles.
Is there any way to achieve the opposite compiler behaviour, like compile static all project files by default and compile dynamic only files chosen by purpose with some kind #CompileDynamic annotation for example?
I have found some (I believe recently introduced) feature which allows doing so with Gradle.
In build.gradle file for the project containing groovy sources we need to add following lines:
compileGroovy {
configure(groovyOptions) {
configurationScript = file("$rootDir/config/groovy/compiler-config.groovy")
}
}
or compileTestGroovy { ... for applying the same to test sources. Keep in mind that neither static compilation nor type checking works well with Spock Framework though. Spock by its nature utilizes dynamic 'groovyness' a lot.
Then on a root of the project create folder config/groovy/ and a file named compiler-config.groovy within. The content of the file is as follows:
import groovy.transform.CompileStatic
withConfig(configuration) {
ast(CompileStatic)
}
Obviously path and name of the configurationScript may vary and it's up to you. It shouldn't rather go to the same src/main/groovy though as it would be mixing totally separate concerns.
The same may be done with groovy.transform.TypeChecked or any other annotation, of course.
To reverse applied behaviour on certain classes or methods then #CompileDynamic annotation or #TypeChecked(TypeCheckingMode.SKIP) respectively may be used.
I'm not sure how to achieve the same when no Gradle is in use as build tool. I may update this answer in the future with such info though.
Not at this time, but there is an open Jira issue here you can follow to watch progress for this feature
There was also a discussion about methods for doing this on the Groovy developers list
With Java on one side and Ruby/Groovy on the other, I know that in the second camp I'm free to make typos which will not get caught until run-time. Is this true of all dynamically-typed languages?
Edit: I've been asked to elaborate on the type of typo. In Ruby and in Groovy, you can assign to a variable with an accidental name that is never read. You can call methods that don't exist (obviously your tests should catch this, it's been said). You can refer to classes that don't exist, etc. etc. Basically any valid syntax, even with typographical errors, is valid in both Ruby and Groovy.
In Perl, if you declare use strict in your code, then you must declare your variables with my. Typos in variable names will then be caught at compile-time. This is one of the biggest things I miss when coding in Python.
Python is typo-friendly in the way you described in your question.
But this does not mean that these 'typos' can only be caught # runtime.
When using a code analyzer like pylint (ideally integrated into your development environment) you'll catch 'most' of these consistently before hitting 'run'.
For the most part, yes. Dynamic typing and not requiring declaration of variables are language properties that are frequently found together.
However, these are not inherently related. A language can easily have dynamic typing while requiring variable names to be declared before use. As ire_and_curses mentions, this can be achieved in Perl via the "use strict" directive.
Here's what happens when I try to get into the pitfalls you mentioned in Squeak and Dolphin, two implementations of the dynamic language Smalltalk 80.
You can assign to a variable with an accidental name that is never read
The Smalltalk language requires temp and instance variables to be declared. If I try to compile a method containing an undefined variable I get a compile-time error.
| anArray |
anArrray := Array with: 2 with: 1. "Unknown variable anArrray"
Creating variables dynamically is not something dynamic languages have to allow. There's a difference between typeless declarations and no declaration at all.
You can call methods that don't exist
The compiler issue a warning if you use a selector (i.e. method name) that is entirely unknown.
The compiler won't bother if I call the method paint on an array because there's another class in the system implementing paint. That error will only be caught at runtime.
If however I call the method sortt (while I intend to call sort) the compiler generates a warning. When developing top-down you can proceed pass these warnings.
| anArray |
anArray := Array with: 2 with: 1.
anArray paint. "Runtime error. You can't paint an array but perhaps a Shape"
anArray sortt. "Compile-time warning"
You can refer to classes that don't
exist
This is not allowed. Though in Squeak you can quickly create a new class from the error dialog if needed.