What do I do wrong:
assert 'foo' == 'foo' //PASS
assert '500' == '500' //PASS
assert '500' < '1000' //FAIL <-- Supposed to pass
assert '500' <= '1000' //FAIL <-- Supposed to pass
assert '1000' > '500' //FAIL <-- Supposed to pass
assert '1000' >= '500' //FAIL <-- Supposed to pass
It is for a customizable "condition" object:
class Condition {
static def compareClosure = [
'==' : { a, b -> a == b},
'!=' : { a, b -> a != b},
'<' : { a, b -> a < b},
'<=' : { a, b -> a <= b},
'>' : { a, b -> a > b},
'>=' : { a, b -> a >= b}
]
String comparator
def value
Condition(String comparator, String value) {
this.value = value
this.comparator = comparator
}
boolean isSatisfiedBy(def value) {
compareClosure[comparator](value, this.value)
}
}
So
assert new Condition('<=', '1000').isSatisfiedBy('500') //FAIL
Is there a way to do this without converting value to a numeric type ?
The short answer to your question is no.
However, I have a feeling this is for sorting purposes. If that is the case. Here is the sort function I use for this purpose.
Example in action: Groovy Web Console
Closure customSort = { String a, String b ->
def c = a.isBigDecimal() ? new BigDecimal(a) : a
def d = b.isBigDecimal() ? new BigDecimal(b) : b
if (c.class == d.class) {
return c <=> d
} else if (c instanceof BigDecimal) {
return -1
} else {
return 1
}
}
['foo','500','1000', '999', 'abc'].sort(customSort)
Related
a metaclass that works with number value string value and null value
like this code ; please help me
String.metaClass.formatx = { delegate.toString().replaceAll(/null/, '0.0').toFloat() }
m= "4".formatx()
m2=4.formatx()
m3=null.formatx()
If I were you, I'd do the following:
String.metaClass.formatx = { -> delegate.toFloat() }
String a = "3"
String b = null
assert 3.0f == (a?.formatx() ?: 0.0f)
assert 0.0f == (b?.formatx() ?: 0.0f)
That is, defend against null in your code with ?. and ?:
If you have to try and catch the null, and format it, you could do:
import org.codehaus.groovy.runtime.NullObject
String.metaClass.formatx = { -> delegate.toFloat() }
NullObject.metaClass.formatx = { -> 0.0f }
String a = "3"
String b = null
assert 3.0f == a.formatx()
assert 0.0f == b.formatx()
But adding a method to NullObject feels wrong, and I've never done it before
Edit
This is shorter
import org.codehaus.groovy.runtime.NullObject
[String, Integer].each { it.metaClass.formatx = { -> delegate.toFloat() } }
NullObject.metaClass.formatx = { -> 0.0f }
println null.formatx()
println 3.formatx()
println "4".formatx()
I put this for example but I think THat I use much code
I repeat metaClass.formatx three times ; I dont know if is possible use OR setences INSTEAD
import org.codehaus.groovy.runtime.NullObject
String.metaClass.formatx = { -> delegate.toString().replaceAll(/null/, '0.0').toFloat() }
NullObject.metaClass.formatx = { -> delegate.toString().replaceAll(/null/, '0.0').toFloat() }
Integer.metaClass.formatx = { -> delegate.toString().replaceAll(/null/, '0.0').toFloat() }
m2= 4.formatx()
m= "4".formatx()
println null.formatx()
edit
import org.codehaus.groovy.runtime.NullObject
[String, Integer,NullObject].each { it.metaClass.formatx = { -> delegate.toString().replaceAll(/null/, '0.0').toFloat() } }
m2= 4.formatx()
m= "4".formatx()
println null.formatx()
Working on some translation / mapping functionality using Maps/JsonBuilder in Groovy.
Is is possible (without creating extra code outside of the map literal creation) .. to conditionally include/exclude certain key/value pairs ? Some thing along the lines of the following ..
def someConditional = true
def mapResult =
[
"id":123,
"somethingElse":[],
if(someConditional){ return ["onlyIfConditionalTrue":true]}
]
Expected results:
If someConditional if false, only 2 key/value pairs will exist in mapResult.
If someConditional if true, all 3 key/value pairs will exist.
Note that I'm sure it could be done if I create methods / and split things up.. for to keep things concise I would want to keep things inside of the map creation.
You can help yourself with with:
[a:1, b:2].with{
if (false) {
c = 1
}
it
}
With a small helper:
Map newMap(m=[:], Closure c) {
m.with c
m
}
E.g.:
def m = newMap {
a = 1
b = 1
if (true) {
c = 1
}
if (false) {
d = 1
}
}
assert m.a == 1
assert m.b == 1
assert m.c == 1
assert !m.containsKey('d')
Or pass an initial map:
newMap(a:1, b:2) {
if (true) {
c = 1
}
if (false) {
d = 1
}
}
edit
Since Groovy 2.5, there is an alternative for with called tap. It
works like with but does not return the return value from the closure,
but the delegate. So this can be written as:
[a:1, b:2].tap{
if (false) {
c = 1
}
}
You could potentially map all false conditions to a common key (e.g. "/dev/null", "", etc) and then remove that key afterwards as part of a contract. Consider the following:
def condA = true
def condB = false
def condC = false
def mapResult =
[
"id":123,
"somethingElse":[],
(condA ? "condA" : "") : "hello",
(condB ? "condB" : "") : "abc",
(condB ? "condC" : "") : "ijk",
]
// mandatory, arguably reasonable
mapResult.remove("")
assert 3 == mapResult.keySet().size()
assert 123 == mapResult["id"]
assert [] == mapResult["somethingElse"]
assert "hello" == mapResult["condA"]
There is no such syntax, the best you can do is
def someConditional = true
def mapResult = [
"id":123,
"somethingElse":[]
]
if (someConditional) {
mapResult.onlyIfConditionalTrue = true
}
I agree with Donal, without code outside of map creation it is difficult.
At least you would have to implement your own ConditionalMap, it is a little work but perfectly doable.
Each element could have it's own condition like
map["a"] = "A"
map["b"] = "B"
map.put("c","C", true)
map.put("d","D", { myCondition })
etc...
Here an incomplete example (I did only put, get, keySet, values and size to illustrate, and not typed - but you probably don't need types here?), you will probably have to implement few others (isEmpty, containsKey etc...).
class ConditionalMap extends HashMap {
/** Default condition can be a closure */
def defaultCondition = true
/** Put an elemtn with default condition */
def put(key, value) {
super.put(key, new Tuple(defaultCondition, value))
}
/** Put an elemetn with specific condition */
def put(key, value, condition) {
super.put(key, new Tuple(condition, value))
}
/** Get visible element only */
def get(key) {
def tuple = super.get(key)
tuple[0] == true ? tuple[1] : null
}
/** Not part of Map , just to know the real size*/
def int realSize() {
super.keySet().size()
}
/** Includes only the "visible" elements keys */
def Set keySet() {
super.keySet().inject(new HashSet(),
{ result, key
->
def tuple = super.get(key)
if (tuple[0])
result.add(key)
result
})
}
/** Includes only the "visible" elements keys */
def Collection values() {
this.keySet().asCollection().collect({ k -> this[k] })
}
/** Includes only the "visible" elements keys */
def int size() {
this.keySet().size()
}
}
/** default condition that do not accept elements */
def map = new ConditionalMap(defaultCondition: false)
/** condition can be a closure too */
// def map = new ConditionalMap(defaultCondition : {-> true == false })
map["a"] = "A"
map["b"] = "B"
map.put("c","C", true)
map.put("d","D", false)
assert map.size() == 1
assert map.realSize() == 4
println map["a"]
println map["b"]
println map["c"]
println map["d"]
println "size: ${map.size()}"
println "realSize: ${map.realSize()}"
println "keySet: ${map.keySet()}"
println "values: ${map.values()}"
/** end of script */
You can use the spread operator to do this for for both maps and lists:
def t = true
def map = [
a:5,
*:(t ? [b:6] : [:])
]
println(map)
[a:5, b:6]
This works in v3, haven't tried in prior versions.
I'm having trouble figuring out how to use optionals inside a tuple inside a switch. The below .Some(let ...) ... syntax works as non-tuple, but inside a tuple I get expected separator stuff :(
var dict = Dictionary<String,Bool>()
dict["a"] = true
switch (dict["a"],dict["b") {
case (.Some(let a) where !a, .Some(let b) where b):
println("false/nil, true")
case (.Some(let a) where a, .Some(let b) where !b):
println("true, false/nil")
I want to avoid doing the following
if let a = self.beaconList["a"] {
if let b = self.beaconList["b"] {
// a, b
} else {
// a, !b
}
} else {
if let b = self.beaconList["b"] {
// !a, b
} else {
// !a, !b
}
}
There are a bunch of ways to do this, but to fix the syntax of what you are trying to do literally, you need to explicitly unbox the Optional, either by matching against .Some(false), or unwrapping it with ! (which I think is kind of weird, as you'll see)
var dict = Dictionary<String,Bool>()
dict["a"] = true
dict["c"] = false
func matchOneOrTheOtherWithOptionals(a: Bool?, b: Bool?) -> String {
switch (a, b) {
case (.Some(true), let b) where b == .None || !b!: // gross
return "a was true, but b was None or false"
case (let a, .Some(true)) where a == .None || a == .Some(false):
return "a was None or false and b was true"
default:
return "They both had a value, or they were both missing a value"
}
}
matchOneOrTheOtherWithOptionals(true, .None) // "a was true, but b was None or false"
matchOneOrTheOtherWithOptionals(true, false) // "a was true, but b was None or false"
matchOneOrTheOtherWithOptionals(.None, true) // "a was None or false and b was true"
matchOneOrTheOtherWithOptionals(false, true) // "a was None or false and b was true"
matchOneOrTheOtherWithOptionals(false, false) // "They both had a value, or they were both missing a value"
matchOneOrTheOtherWithOptionals(true, true) // "They both had a value, or they were both missing a value"
matchOneOrTheOtherWithOptionals(.None, .None) // "They both had a value, or they were both missing a value"
You could also try the following:
func noneToFalse(bool: Bool?) -> Bool {
if let b = bool {
return b
} else {
return false
}
}
func matchOneOrTheOther(a: Bool, b: Bool) -> String {
switch (a, b) {
case (true, false):
return "a is true, b was false or None"
case (false, true):
return "a was false/None, b was true"
default:
return "both were true, or both were false/None"
}
}
matchOneOrTheOther(noneToFalse(dict["a"]), noneToFalse(dict["b"]))
Here's a gist of the Playground I used while writing this answer: https://gist.github.com/bgrace/b8928792760159ca58a1
Simplify!
var dict = Dictionary<String,String>()
dict["a"] = "the letter a"
switch (dict["a"],dict["b"]) {
case (.None, let b):
println("false/nil, true \(b)")
case (let a, .None):
println("true, false/nil \(a)")
default:
println("don't know")
}
The accepted answer is out of date. So I rewrote it in Swift 5.
var dict = Dictionary<String,Bool>()
dict["a"] = true
dict["c"] = false
func matchOneOrTheOtherWithOptionals(_ a: Bool?, _ b: Bool?) -> String {
switch (a, b) {
case (.some(true), .none), (.some(true), .some(false)):
return "a was true, but b was None or false"
case (.none, .some(true)), (.some(false), .some(true)):
return "a was None or false and b was true"
default:
return "They both had a value, or they were both missing a value"
}
}
let xs: [Bool?] = [true, false, .none]
for a in xs {
for b in xs {
print("a = \(String(describing: a)), b=\(String(describing: b))")
print(matchOneOrTheOtherWithOptionals(a,b))
}
}
I want to use either a value of expected property or a specified default.
How to achieve this in groovy?
Let's look at the example:
def printName(object) {
//if object has initialized property 'name' - print 'name', otherwise print ToString
if (object<some code here>name && object.name) {
print object.name
} else {
print object
}
}
You can use hasProperty. Example:
if (object.hasProperty('name') && object.name) {
println object.name
} else {
println object
}
If you're using a variable for the property name, you can use this:
String propName = 'name'
if (object.hasProperty(propName) && object."$propName") {
...
}
Assuming your object is a Groovy class, you can use hasProperty in the object metaClass like so:
def printName( o ) {
if( o.metaClass.hasProperty( o, 'name' ) && o.name ) {
println "Printing Name : $o.name"
}
else {
println o
}
}
So, then given two classes:
class Named {
String name
int age
String toString() { "toString Named:$name/$age" }
}
class Unnamed {
int age
String toString() { "toString Unnamed:$age" }
}
You can create instance of them, and test:
def a = new Named( name: 'tim', age: 21 )
def b = new Unnamed( age: 32 )
printName( a )
printName( b )
Which should output:
Printing Name : tim
toString Unnamed:32
You can write your own method via meta-programming:
class Foo {
def name = "Mozart"
}
def f = new Foo()
Object.metaClass.getPropertyOrElse = { prop, defaultVal ->
delegate.hasProperty(prop) ? delegate."${prop}" : defaultVal
}
assert "Mozart" == f.getPropertyOrElse("name", "")
assert "Salzburg" == f.getPropertyOrElse("city", "Salzburg")
If I simply want to assert that an object has some property, I just test the following:
assertNotNull(myObject.hasProperty('myProperty').name)
If myObject does not have myProperty the assertion will fail with a null pointer exception:
java.lang.NullPointerException: Cannot get property 'name' on null object
I want to define a function, which accepts another function (closure) as a parameter.
The second function should accept 1 parameter.
Currently, I have just a simple signature:
def func1(func2) {
func2("string")
}
Is there a way to explicitly specify, that func2 should accept 1 parameter (or less)?
Not in the definition of func1, but you can check the maximumNumberOfParameters for a Closure at runtime, like so:
def func1( func2 ) {
if( func2.maximumNumberOfParameters > 1 ) {
throw new IllegalArgumentException( 'Expected a closure that could take 1 parameter or less' )
}
func2( 'string' )
}
Testing success:
def f2 = { a -> "returned $a" }
assert func1( f2 ) == 'returned string'
And failure:
def f3 = { a, b -> "returned $a" }
try {
func1( f3 )
assert true == false // Shouldn't get here
}
catch( e ) {
assert e.message == 'Expected a closure that could take 1 parameter or less'
}