Question 1
Is it irrelevant whether a List (list of objects) or a List<String> (list of Strings) is used in Groovy?
In the code example below, both lists end up being an ArrayList (ArrayList of objects). Would have expected the second list to be an ArrayList<String> (ArrayList of Strings).
Does Groovy lose the type information when the class is compiled and infer it when the compiled class is executed?
Example 1
List untypedList = ["a", "b", "c"]
List<String> typedList = ["a", "b", "c"]
println "Untyped list List: ${untypedList.getClass()}"
println "Typed list List<String>: ${typedList.getClass()}"
Output 1
Untyped list List: class java.util.ArrayList
Typed list List<String>: class java.util.ArrayList // Would have expected ArrayList<String>
Question 2
I would have expected the line typedList << new Integer(1) in the example below to fail with an exception because I'm trying to put an int into a list of Strings. Can anyone explain why I can add an int to the String-typed List?
The output shows that it remains an Integer, i.e. it's not on-the-fly converted to a String "1".
Example 2
List untypedList = ["a", "b", "c"]
List<String> typedList = ["a", "b", "c"]
untypedList << new Integer(1)
typedList << new Integer(1) // Why does this work? Shouldn't an exception be thrown?
println "Types:"
println "Untyped list List: ${untypedList.getClass()}"
println "Typed list List<String>: ${typedList.getClass()}"
println "List contents:"
println untypedList
println typedList
println "Untyped list:"
untypedList.each { println it.getClass() }
println "Typed list:"
typedList.each { println it.getClass() }
Output 2
Types:
Untyped list List: class java.util.ArrayList
Typed list List<String>: class java.util.ArrayList
List contents:
[a, b, c, 1]
[a, b, c, 1]
Untyped list:
class java.lang.String
class java.lang.String
class java.lang.String
class java.lang.Integer
Typed list:
class java.lang.String
class java.lang.String
class java.lang.String
class java.lang.Integer
When running Groovy "normally", generics are thrown away before compilation, so only exist in the source as helpful reminders to the developer.
However, you can use #CompileStatic or #TypeChecked to make Groovy honour these Generics and check the types of things at compilation.
As an example, consider I have the following project structure:
project
|---- src
| |---- main
| |---- groovy
| |---- test
| |---- ListDelegate.groovy
| |---- Main.groovy
|---- build.gradle
With the code:
build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.2.1'
}
task( runSimple, dependsOn:'classes', type:JavaExec ) {
main = 'test.Main'
classpath = sourceSets.main.runtimeClasspath
}
ListDelegate.groovy
package test
class ListDelegate<T> {
#Delegate List<T> numbers = []
}
Main.groovy
package test
class Main {
static main( args ) {
def del = new ListDelegate<Integer>()
del << 1
del << 'tim'
println del
}
}
Now, running gradle runSimple gives us the output:
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:runSimple
[1, tim]
BUILD SUCCESSFUL
Total time: 6.644 secs
So as you can see, the generics were thrown away, and it just worked adding Integers and Strings to out List of supposedly only Integers
Now, if we change ListDelegate.groovy to:
package test
import groovy.transform.*
#CompileStatic
class ListDelegate<T> {
#Delegate List<T> numbers = []
}
And run again:
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:runSimple
[1, tim]
BUILD SUCCESSFUL
Total time: 6.868 secs
We get the same output!! This is because whilst ListDelegate is now statically compiled, our Main class is still dynamic, so still throws away generics before constructing the ListDelegate... So we can also change Main.groovy to:
package test
import groovy.transform.*
#CompileStatic
class Main {
static main( args ) {
def del = new ListDelegate<Integer>()
del << 1
del << 'tim'
println del
}
}
And now re-running gradle runSimple give us:
:compileJava UP-TO-DATE
:compileGroovy
startup failed:
/Users/tyates/Code/Groovy/generics/src/main/groovy/test/Main.groovy: 10:
[Static type checking] - Cannot find matching method test.ListDelegate#leftShift(java.lang.String).
Please check if the declared type is right and if the method exists.
# line 10, column 9.
del << 'tim'
^
1 error
:compileGroovy FAILED
Which is, as you'd expect, failing to add a String to our declared List of Integer.
In fact, you only need to CompileStatic the Main.groovy class and this error will be picked up, but I always like to use it where I can, not just where I need to.
As #tim_yates notes, it is possible to enable compile time checks with the #TypeChecked/#CompileStatic annotations.
Another alternative is to enable runtime type checking by wrapping the collection with Collections.checkedList(). While this doesn't use the generics or the declared type, enforcing it at runtime sometimes fits in better with loosely typed dynamic code. This is a Java platform feature not specific to groovy.
Example:
// no type checking:
list1 = ["a", "b", "c"]
list1 << 1
assert list1 == ["a", "b", "c", 1]
// type checking
list2 = Collections.checkedList(["a", "b", "c"], String)
list2 << 1
// ERROR java.lang.ClassCastException:
// Attempt to insert class java.lang.Integer element into collection with element type class java.lang.String
From Wikipedia, for Java:
Generics are checked at compile-time for type-correctness. The generic
type information is then removed in a process called type
erasure. For example, List will be converted to the
non-generic type List, which ordinarily contains arbitrary objects.
The compile-time check guarantees that the resulting code is
type-correct.
This type information is for compiler and IDE. Groovy is based on Java and inherits same principles for generics.
At other hand, Groovy is more dynamic language, so probably, it's the reason why it doesn't check types on compile time. IMO for Groovy it's some kind of code comment, sometimes very useful.
PS #tim_yates suggested a link to Groovy docs about Generics, that confirms:
Groovy currently does a little further and throws away generics information "at the source level".
Related
I have two objects that have some features in common that I would like to compare
data class Pet(val colour: String, val owner: Human, val legCount: Int)
data class Car(val colour: String, val owner: Human, val isElectric: Boolean)
I would like to assert that some element in a List<Car> contains an element with the same colour and owner as a given Pet.
Here's a fake code example to illustrate what I'm trying to do:
cars.containsElementSatisfying { car ->
pet.colour shouldBe car.colour
pet.owner shouldBe car.owner
}
How might I do this using kotest? I can accomplish the desired functionality using assertJ's anySatisfy assertion.
I found the solution. The "Inspectors" kotest library contains a number of functions similar to assertJ's anySatisfy assertion, in particular the collection functions forAtLeastOne and forAtLeast(k)
Here's example usage:
cars.forAtLeastOne { car ->
pet.colour shouldBe car.colour
pet.owner shouldBe car.owner
}
https://kotest.io/docs/assertions/inspectors.html
I am trying to use Foq to testing an interface with Foq.
So far, all examples I have seen for this have been relatively simple, such as the following:
let users = [|{ID = 1; pass = true};{ID = 2; pass= false}|]
type IFoo =
abstract member Bar: int -> bool
//tests with Foq
let dataAccess =
Mock<IFoo>()
.Setup(fun x-> <# x.Bar(users.[0].ID) #>).Returns(users.[0].pass)
.Setup(fun x-> <# x.Bar(users.[1].ID) #>).Returns(users.[1].pass)
.Create()
The examples have been sourced from 'Testing with F# - Mikael Lundin'
I have also researched this through a bit of googling (this link was helpful - http://trelford.com/blog/post/Foq.aspx)
However, the real Interfaces I want to test are the following:
type IParameters =
abstract member ParameterDate : int->string->DateTime
type IDataSource =
abstract member MortParameters: IParameters
I have tried a number of different ways to test these (e.g. defining a function with a signature of int->string to be used as the input to the setup. Alternatively, having the return value as a string->DateTime and the Setup as just an integer.
My question is really the following: When testing interfaces using Foq, how can I extend the testing to interfaces with function signatures of any general length (e.g. a->b->c->d->e etc.)
Since ParameterDate a property with a function type, you could just set it up as a property that returns a lambda value. See an example of property set-up in Foq. This should be easy to modify for your case:
let instance =
Mock<System.Collections.IList>()
.Setup(fun x -> <# x.Count #>).Returns(1)
.Create()
However, I guess you would lose the ability to have a strict mock with fixed expectations on the function inputs.
To enforce only expected inputs for the function returned by the mock property you could provide a function like this:
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Invalid mock input"
I would probably stop here, but if you're working with code where you need to verify a function was called, as opposed to just ensuring you get the correct output, you could add a helper like this:
type Verifiable<'a, 'b> (f : 'a -> 'b) =
let called = ref false
member this.Func x =
called := true
f x
member this.Verify() =
if not called.Value then failwith "Mock function was not called"
And here's how you would use it:
let parameterDateMock =
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Unexpected mock input"
|> Verifiable
let parameters =
{ new IParameters with member this.ParameterDate i s = parameterDateMock.Func i s }
parameters.ParameterDate 1 ""
parameterDateMock.Verify()
Caveat: This only verifies the function was called with at least one parameter. It may have returned another function by currying and not actually run the code in the mock function body. To get around that you'd need a variation of the Verifiable class for every function arity and use the right one in each case.
So my short code snippet looks like the following:
Source.fromFile(fileName).getLines().foldLeft(List[CsvEntry]())((csvList, currentLine) =>
currentLine match {
case pattern(organisation,yearAndQuartal,medKF,trueOrFalse,name,money) => new CsvEntry(organisation,yearAndQuartal,medKF.toInt,trueOrFalse.toInt,name,money) :: csvList
case default => csvList
The "fileName" is only the Name of the file, but it doesn't matter for my question.
And my csvList is defined like this:
type csvList = List[CsvEntry]
val list: csvList = List()
my class look like this:
class CsvEntry(val organisation: String, val yearAndQuartal : String, val medKF:Int, val trueOrFalse: Int, val name: String, val money:String){
override def toString = s"$organisation, $yearAndQuartal, $medKF,$trueOrFalse, $name, $money"
So my question is, whenever I am loading a file and writing it to my csvList it works, but when I am loading another 2nd file the old content gets overwirtten.
How can I change it in order to not get overwirtten, so it should only add it to the preceding data ?
The call beginning Source.fromFile... returns a list that you should then combine with the next call.
For example:
List("filename1", "filename2").map(processFile).flatten
where processFile is:
def processFile(fileName: String) = {
Source.fromFile(fileName).getLines().foldLeft... all the code in question
}
Nothing here can possibly get "overwritten", since there's no mutable state. Your type csvList and csvList in your foldLeft call are two very different things: the former is the type, the latter is the parameter.
Each time your snippet is executed, it returns a list of your CSV objects of a particular file. As an immutable list.
What you want is:
Make a function out of your snippet: def readFile(name: String): List[CsvFile]
Call it on the two files and save results to vals
Concat the two lists: list1 ++ list2
As I am working a design model, I am torn between two different methods of indicating a parameter of type List must be nonEmpty. I began by using List[Int] with an accompanying require statement to verify the List is nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
I then needed to make the list optional. If the List is provided, it must be nonEmpty. I'm using using Option[List[Int]] with an accompanying require statement to verify, if the Option is nonEmpty, the list must also be nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
However, I need to use this non-empty List all over the system I am modeling. This means that my code has these same require statements duplicated everywhere. Is there a (non-ScalaZ) way to have a new type, say NeList, which is defined and behaves identically to List, with the only change being an exception is thrown when NeList attempts to be instantiated with no elements?
I tried to Google for this and couldn't find a set of search terms to hone on this area. I either got really simple List how-tos, or all sorts of references to ScalaZ's NEL (Non Empty List). So, if there is a link out there that would help with this, I would love to see it.
If you
def foo[A](x: ::[A]) = "List has length "+x.length
then you insist that the list be nonempty. But of course your lists are all typed as List, so you need a helper method to give you a nonempty list:
implicit class NonEmptyList[A](private val underlying: List[A]) {
def ifNonEmpty[B](f: ::[A] => B): Option[B] = {
underlying match {
case x: ::[A #unchecked] => Some(f(x))
case _ => None
}
}
}
Now you can safely apply the operation to get an Option out. (You could also run side-effecting functions in a foreach-like method.)
Now, this is rather non-idiomatic Scala. But it is safe at compile time (the #unchecked notwithstanding--Scala's compiler isn't quite smart enough to realize that the type parameter hasn't changed).
You could implement a non-empty list yourself with implicit conversions between List[A] and Nel[A]:
case class Nel[A](val head: A, val tail: List[A] = Nil)
implicit def list2Nel[A](list: List[A]): Nel[A] = {
require(!list.isEmpty)
Nel(list.head, list.tail)
}
implicit def nel2List[A](nel: Nel[A]): List[A] = nel.head :: nel.tail
Then you can define your functions where this is needed such that they take a Nel[A] as a parameter:
def f(l: Option[Nel[String]]) = { ... }
And call them with normal lists (assuming the implicit defs are in scope):
f(Some(List("hello", "world")) // works
f(Some(Nil)) // throws IllegalArgumentException
f(None) // works
EDIT: It should be noted that this does not provide compile time guarantees that the List[A] passed in will not be empty. If that's what you want, then get rid of the implicit def list2Nel and require clients of your function to pass in an Nel[A] explicitly, thus guaranteeing at compile time that the list is not empty.
Also, this is a very basic NonEmptyList implementation. A more complete solution is found in scalaz (granted it was specifically requested in the question that scalaz not be used): https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/NonEmptyList.scala
In order to test a domain class, which has a transient field, I tried to put a value for that field by the two following ways:
Requirement requirement = new Requirement(linearProduct: linearProduct, periodIndexes: [1,2,3])
requirement.periodIndexes = [1,2,3]
Both of them made the field appear as null object when getting into the tested function.
My question is how to make the values pass although it transient field?
Transient properties are bindable:false by default. If you want the periodIndexes field to be bindable with named arguments you have to be explicit about that:
class Requirement {
transient List periodIndexes
static constraints = {
periodIndexes bindable: true
}
}
It isn't clear why your requirement.periodIndexes = [1,2,3] results in null. It shouldn't. If you can show a more complete test I can help you with that.
EDIT:
As an example...
A domain class:
// grails-app/domain/demo/Widget.groovy
package demo
class Widget {
String name
transient List firstTransientList
transient List secondTransientList
static constraints = {
secondTransientList bindable: true
}
}
This test will pass:
// test/unit/demo/WidgetSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(Widget)
class WidgetSpec extends Specification {
void "test binding to transient fields"() {
when: 'binding to transient properties using named arguments'
def widget = new Widget(firstTransientList: [1, 2, 3],
secondTransientList: [4, 5, 6])
then: 'by default transient fields are not bindable'
widget.firstTransientList == null
and: 'transient fields configured with bindable:true are bindable'
widget.secondTransientList == [4, 5, 6]
when: 'a value is assigned directly to a transient property'
widget.firstTransientList = [7, 8, 9]
then: 'the assignment succeeds'
widget.firstTransientList == [7, 8, 9]
}
}
You haven't said which version of Grails you are using. Some of this behavior changed in the 2.3.x line. The test above should pass with recent versions of Grails.
ANOTHER EDIT (to answer a question in a comment below):
The transient properties may be defined without the transient keyword but instead using the transients property, as shown below:
// grails-app/domain/demo/Widget.groovy
package demo
class Widget {
String name
List firstTransientList
List secondTransientList
static transients = ['firstTransientList', 'secondTransientList']
static constraints = {
secondTransientList bindable: true
}
}
Ok,
The solution was to have a mocked get function to the field in it's domain class:
Requirement.metaClass.'static'.getPeriodIndexes = {[1,2,3]}