I want to unit-test a function that returns a complex nested data structure, but I'm only interested in certain fields of that structure. For example:
expectedResult = Right (
UserRecord {
name = "someName",
id = <don't care>
address = AddressRecord {
street = "someStreet",
id = <don't care>
}
}
)
Is there a generic way to assert a result of the above form in HSpec? That is, some way to write an expression
result `shouldBe` expectedResult
where I do not need to specify those parts of the expected result that I am not interested in? I found this answer, which requires to copy over all don't care fields from result to expectedResult; this might get rather tedious. Maybe there is a standard approach using lenses? Or some library with assertion helpers I haven't heard of?
A simple approach:
result `shouldSatisfy` \a ->
name a == "someName" &&
street (address a) == "someStreet"
Related
Control.Lens.Setter is remarkable to use Observable feature in Haskell. ( function/functor to be triggered when the value in the dataset is updated. )
However, considering the lens is not included in the standard environment, and then required to extra installation, without the lens, when I want to use just a primitive setter feature such as with a field label:
data Foo = Foo {val :: Int}
How to do this?
Does ST Monad fit this purpose?
Thanks.
It's not very clear what you're looking for here, but if you just want to update a record field, you can use the Haskell record update syntax:
x = Foo { val = 5 }
y = x { val = 42 }
This works for any record, with any number of fields, and you don't need to list all the fields, only the ones you'd like to update, for example:
data D = D { a :: String, b :: Int }
x = D { a = "foo", b = 42 }
y = x { a = "bar" } -- now y = D { a = "bar", b = 42 }
z = x { b = 43 } -- now z = D { a = "foo", b = 43 }
Keep in mind that this doesn't actually update ("change", "mutate") the values in memory, but rather creates copies of the records with all the fields equal to those of the original record, except the updated fields. Lenses work the same way, and in fact everything in Haskell does, since Haskell doesn't allow mutation at all.
I think that you're a bit confused between a few concepts; specifically, setter vs observable.
I don't know much about them, but an observable does seem to be, as you described, a way to run a function every time a value is changed. This concept does not exist in Haskell; I'm sure you could make it somehow, but it wouldn't be very useful, since (almost) every Haskell value is immutable.
By contrast, a setter is just a function which changes part of a value, the same as with Java getters and setters. The only slight complication is that in Haskell, all values are immutable (as I mentioned above), so instead of changing the value, a setter copies the value across but with the thing set. For instance, if you have a setter setName (for a record), and you invoke it with something like setName "foo" oldRecord, this will keep oldRecord as is, but return a new record with the name set to "foo". As you already know, there are other, more complex, implementations of setters, such as lenses.
You also mention ST. This is a more advanced concept; it's basically used when you have to use some sort of mutable variable locally but still retain purity (which is not very often).
Now to answer your other question: How do I use setters without lenses? Well, if you have a record like data Foo = Foo {val :: Int, val2 :: String} (your example + an extra field), and you have an old record - let's say oldRecord = Foo { val = 1, val2 = "test" }, Haskell has special setter syntax: doing oldRecord { val = 2 } will give a new record with val set to 2 - that is, it will give Foo { val = 2, val2 = "test" }. Obviously this syntax is a bit clumsy though for nested records, which is the reason lenses were invented.
"When you've found the treasure, stop digging!"
I'm wanting to use more functional programming in Groovy, and thought rewriting the following method would be good training. It's harder than it looks because Groovy doesn't appear to build short-circuiting into its more functional features.
Here's an imperative function to do the job:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
String shortestUniqueName(String nameToShorten) {
def currentLevel = 1
String shortName = ''
def separator = '/'
while (fullyQualifiedNames.findAll { fqName ->
shortName = nameToShorten.tokenize(separator)[-currentLevel..-1].join(separator)
fqName.endsWith(shortName)
}.size() > 1) {
++currentLevel
}
return shortName
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
It scans a list of fully-qualified filenames and returns the shortest unique form. There are potentially hundreds of fully-qualified names.
As soon as the method finds a short name with only one match, that short name is the right answer, and the iteration can stop. There's no need to scan the rest of the name or do any more expensive list searches.
But turning to a more functional flow in Groovy, neither return nor break can drop you out of the iteration:
return simply returns from the present iteration, not from the whole .each so it doesn't short-circuit.
break isn't allowed outside of a loop, and .each {} and .eachWithIndex {} are not considered loop constructs.
I can't use .find() instead of .findAll() because my program logic requires that I scan all elements of the list, nut just stop at the first.
There are plenty of reasons not to use try..catch blocks, but the best I've read is from here:
Exceptions are basically non-local goto statements with all the
consequences of the latter. Using exceptions for flow control
violates the principle of least astonishment, make programs hard to read
(remember that programs are written for programmers first).
Some of the usual ways around this problem are detailed here including a solution based on a new flavour of .each. This is the closest to a solution I've found so far, but I need to use .eachWithIndex() for my use case (in progress.)
Here's my own poor attempt at a short-circuiting functional solution:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
def shortestUniqueName(String nameToShorten) {
def found = ''
def final separator = '/'
def nameComponents = nameToShorten.tokenize(separator).reverse()
nameComponents.eachWithIndex { String _, int i ->
if (!found) {
def candidate = nameComponents[0..i].reverse().join(separator)
def matches = fullyQualifiedNames.findAll { String fqName ->
fqName.endsWith candidate
}
if (matches.size() == 1) {
found = candidate
}
}
}
return found
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
Please shoot me down if there is a more idiomatic way to short-circuit in Groovy that I haven't thought of. Thank you!
There's probably a cleaner looking (and easier to read) solution, but you can do this sort of thing:
String shortestUniqueName(String nameToShorten) {
// Split the name to shorten, and make a list of all sequential combinations of elements
nameToShorten.split('/').reverse().inject([]) { agg, l ->
if(agg) agg + [agg[-1] + l] else agg << [l]
}
// Starting with the smallest element
.find { elements ->
fullyQualifiedNames.findAll { name ->
name.endsWith(elements.reverse().join('/'))
}.size() == 1
}
?.reverse()
?.join('/')
?: ''
}
I am building an analytic application using Groovy and require very forgiving math operators regardless of data format. I achieve this through operator overloading, in many cases improving (in my case) on the default Groovy type flexibility. As an example, I need 123.45f + "05" to equal 128.45f. By default Groovy downgrades to String and I get 123.4505.
In most cases my overloading works very well, but not for comparison operators. I've followed a couple of discussions on this, but I'm not getting to an answer and I'm looking for ideas. I recognize that the goal is to overload compareTo() (vs. something like lessThan), but Groovy seems to ignore this and instead attempts its own smart comparison - e.g. DefaultTypeTransformation.compareTo(Object left, Object right), which fails on mixed types.
Unfortunately this is a must have for me, because improperly comparing two values compromises the whole solution and I don't have control over some of the data types being analyzed (e.g. vendor data structures).
For example, I need the following to work:
Float f = 123.45f;
String s = "0300";
Assert.assertTrue( f < s );
I have many permutations of these, but my attempt to overload includes (let's just assume my JavaTypeUtil does what I need if I can get Groovy to call it):
// overloads on startup, trying to catch all cases
Float.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
Float.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
When I try the above test, none of these are called and instead I get:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Float
at java.lang.Float.compareTo(Float.java:50)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareToWithEqualityCheck(DefaultTypeTransformation.java:585)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareTo(DefaultTypeTransformation.java:540)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareTo(ScriptBytecodeAdapter.java:690)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThan(ScriptBytecodeAdapter.java:710)
at com.modelshop.datacore.generator.GroovyMathTests.testMath(GroovyMathTests.groovy:32)
Debugging through I see that the < operator goes right to ScriptBytecodeAdapter.compareLessThan(), and the implementation of that seems to ignore the overloaded compareTo() here:
In DefaultTypeTransformations.java:584 (2.4.3)
if (!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
|| (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
|| (left instanceof GString && right instanceof String)) {
Comparable comparable = (Comparable) left;
return comparable.compareTo(right); // <--- ***
}
In a desperate attempt, I've also tried to overload compareLessThan, but I'm grasping now, I don't know that there's any way to jump in front of the < mapping in Groovy.
Float.metaClass.compareLessThan << {
Object right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
Float.metaClass.compareLessThan << {
String right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
Any thoughts on a work-around? Thanks!
Part of it is you need to include static, like this
Float.metaClass.static.compareTo = { String s -> 0 }
This makes f.compareTo(s) work, but the < operator still won't work. This is a known limitation. The only operators that can be overloaded are mentioned in the documentation. Possibly you could do a custom AST to change all those operators to a compareTo().
But this isn't the whole story. f <=> s also doesn't work, despite <=> delegating to compareTo(). I believe this is because Float doesn't implement Comparable<Object> or Comparable<String>, only Comparable<Float>. Although I'm not sure where exactly in the chain Groovy makes the decision not to use that method, you can see it's not limited to Groovy's math classes. This also doesn't work
Foo.metaClass.compareTo = { String s -> 99 }
new Foo() <=> ''
class Foo implements Comparable<Foo> {
int compareTo(Foo o) {
0
}
}
I think Groovy is doing some pre-parsing validation that's preventing the metaclass stuff from working. Whatever validation it's doing definitely inspects the interfaces implemented, because this fails for a different reason
Foo.metaClass.compareTo = { String s -> 99 }
new Foo() <=> ''
class Foo {
int compareTo(Foo o) {
0
}
}
In both of these examples, replacing <=> with compareTo() works.
This question has been asked a couple times before, but I haven't seen a good explanation for why. You might try asking on the user mailing list. I'm sure Jochen or Cedric would be able to explain why.
I guess the point is that your compareTo closure is expecting an Object; so when you invoke compareTo with a String, your closure doesn't get called at all.
I can only think of the following; being precise when specifying closure input parameter type:
Float.metaClass.compareTo = { Integer n -> aStaticHelperMethod(n) }
Float.metaClass.compareTo = { String s -> aStaticHelperMethod(s) }
Float.metaClass.compareTo = { SomeOtherType o -> aStaticHelperMethod(o) }
I got confused with this two lines of coding :
this.class.methods.name
This is called Gpath (Am I right?). Now consider this code :
count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }.each { count ++ }
println count
The line:
a.findAll { it == 5 }.each { count ++ }
is called as a method chaining or Gpath?
Literally, I got struck with these two meanings. It will be nice if some one explains the difference between these two.
Thanks in advance.
I'm not sure if I understand the question correctly.
As I see it, in both examples you are using method chaining, simply because you are calling a method in the object that is returned by another method. But, as Arturo mentions, some people confuse method chaining and fluent interfaces. A fluent interface is indeed quite handy if you want to chain methods.
In Groovy, however, you may, instead of coding a fluent interface yourself, use the with method in any object. For example, using the same Person and Address classes that Arturo defined, you can do:
def person = new Person()
person.with {
name = 'John'
age = 25
address = new Address('Boulevard St')
}
assert person.name == 'John' &&
person.age == 25 &&
person.address.name == 'Boulevard St'
Now, GPath, as I understand, is just a way of accessing the properties of an object. For example, if you have the class:
class Foo {
def bar
}
The GPath mechanism in Groovy lets you do things like:
def foo = new Foo(bar: 42)
assert foo.bar == 42
Instead of accessing the bar property with its getter, like foo.getBar(). Nothing too fancy. But other classes in Groovy also have some GPath magic and there is where things get more interesting. For example, lists let you access properties in their elements the same way you'd access normal properties:
def foos = (1..5).collect { new Foo(bar: it) } // Five Foos.
assert foos.bar == [1, 2, 3, 4, 5]
As you can see, accessing the bar property on a list of objects that have that property will result in a list with the values of that property for each object in the list. But if you access a property that the elements of the list don't have, e.g. foos.baz, it will throw a MissingPropertyException.
This is exactly what is happening in:
this.class.methods.name
I, however, consider this behavior to be a little too magic for my taste (unless you are parsing XML, in which case is totally fine). Notice that if the collection returned by the methods method would be some weird collection that had a name property, methods.name would result in that name instead of the names of each method in the collection. In these cases I prefer to use the (IMO) more explicit version:
this.class.methods*.name
Wich will give you the same result, but it's just syntax sugar for:
this.class.methods.collect { it.name }
... and let's the intention of the expression to be more clear (i.e. "I want the names of each method in methods").
Finally, and this is quite off-topic, the code:
count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }.each { count ++ }
println count
can be rewritten as:
def a = [1,2,3,4,5,5,51,2]
def count = a.count { it == 5 }
println count
:)
I think that your code is an example of method chaining.
GPath is a path expression language integrated into Groovy which allows to navigate in XML or POJOs. You can perform nested property access in objects.
Method chaining is a technique for invoking multiple method calls in object-oriented programming languages. Each method returns an object (possibly the current object itself), allowing the calls to be chained together in a single statement.
I'm going to use an example with TupleConstructor to assist in the creation of the object.
import groovy.transform.TupleConstructor
#TupleConstructor
class Address {
String name
}
#TupleConstructor
class Person {
String name
Integer age
Address address
}
def person = new Person('John', 25, new Address('Boulevard St'))
Ok, you are right, this access is called GPath:
assert person.address.name == 'Boulevard St'
A getter access could be named method chaining:
assert person.getAddress().getName() == 'Boulevard St'
But what happens if I can do something like this:
person.setName('Louise')
.setAge(40)
.setAddress(new Address('Main St'))
I need to create a fluent API, an method chaining is the way, the idea is to let methods return this rather than void.
#TupleConstructor
class Person {
String name
Integer age
Address address
def setName(name) {
this.name = name
return this
}
def setAge(age) {
this.age = age
return this
}
}
I am trying to use Parsec to parse something like this:
property :: CharParser SomeObject
property = do
name
parameters
value
return SomeObjectInstance { fill in records here }
I am implementing the iCalendar spec and on every like there is a name:parameters:value triplet, very much like the way that XML has a name:attributes:content triplet. Infact you could very easily convert an iCalendar into XML format (thought I can't really see the advantages).
My point is that the parameters do not have to come in any order at all and each paramater may have a different type. One parameter may be a string while the other is the numeric id of another element. They may share no similarity yet, in the end, I want to place them correctly in the right record fields for whatever 'SomeObjectInstance' that I wanted the parser to return. How do I go about doing this sort of thing (or can you point me to an example of where somebody had to parse data like this)?
Thankyou, I know that my question is probably a little confused but that reflects my level of understanding of what I need to do.
Edit: I was trying to avoid giving the expected output (because it is large, not because it is hidden) but here is an example of an input file (from wikipedia):
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:uid1#example.com
DTSTAMP:19970714T170000Z
ORGANIZER;CN=John Doe:MAILTO:john.doe#example.com
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR
As you can see it contains one VEvent inside a VCalendar, I have made data structures that represent them here.
I am trying to write a parser that parses that type of file into my data structures and I am stuck on the bit where I need to handle properties coming in any order with any type; date, time, int, string, uid, ect. I hope that makes more sense without repeating the entire iCalendar spec.
Parsec has the Parsec.Perm module precisely to parse unordered but linear (i.e. at the same level in the syntax tree) elements such as attribute tags in XML files.
Unfortunately the Perm module is mostly undocumented. The best reference is the Parsing Permutation Phrases paper which the Haddock doc page refers to, but even that is largely a description of the technique rather than how to use it.
Ok, so between BEGIN:VEVENT and END:VEVENT, you have many key value pairs. So write a rule keyValuePair that returns (key, value). Now inside the rule for VEVENT you do many KeyValuePair to get a list of pairs. Once you've done that you use a fold to populate a VEVENT record with the given values. In the function you give to fold, you use pattern matching to find out in which field to store the value. As the starting value for the accumulator you use a VEvent record where the optional fields are set to Nothing. Example:
pairs <- many keyValuePairs
vevent = foldr f (VEvent {sequence = Nothing}) pairs
where f ("SUMMARY", v) ve = ve {summary = v}
f ("DSTART", v) ve = ve {dstart = read v}
...and so on. Do the same for the other components.
Edit: Here's some runnable example code for the fold:
data VEvent = VEvent {
summary :: String,
dstart :: String,
sequenceSt :: Maybe String
} deriving Show
vevent pairs = foldr f (VEvent {sequenceSt = Nothing}) pairs
where f ("SUMMARY", v) ve = ve {summary = v}
f ("DSTART", v) ve = ve {dstart = v}
f ("SEQUENCEST", v) ve = ve {sequenceSt = Just v}
main = do print $ vevent [("SUMMARY", "lala"), ("DSTART", "lulu")]
print $ vevent [("SUMMARY", "lala"), ("DSTART", "lulu"), ("SEQUENCEST", "lili")]
Output:
VEvent {summary = "lala", dstart = "lulu", sequenceSt = Nothing}
VEvent {summary = "lala", dstart = "lulu", sequenceSt = Just "lili"}
Note that this will produce a warning when compiled. To avoid the warning, initialize all non-optional fields to undefined explicitly.