I recently started to learn Groovy and found not a natural behavior.
class BasicRouter {
int method_(first){
return 1;
}
int method_(int first){
return 2;
}
int method_(short second){
return 3;
}
int method_(Integer first){
return 4;
}
}
br = new BasicRouter()
int x = 1
assert br.method_(x) == 4
assert br.method_((int)29) == 2
Why in the first case we are passing a variable of type int, we get 4 and not 2?
I expect that method int method_(int) will be called.
Thanks.
The answer is here - http://docs.groovy-lang.org/latest/html/documentation/core-differences-java.html#_primitives_and_wrappers
Groovy uses objects for everything
This changes if you use CompileStatic
#groovy.transform.CompileStatic
def fInt(int x) {new BasicRouter().method_(x)}
assert fInt(1) == 2
Related
In Groovy, I can overload operator '+' plus as follow:
class MutableInt {
int val
MutableInt(int val) { this.val = val }
MutableInt plus(int val) {
return new MutableInt(this.val += val)
}
}
The above class works fine for the following test cases:
def m1 = new MutableInt(1);
assert (m1 + 1).val == 2;
However, if I need to use it together with Map like this and compile it with static
#groovy.transform.CompileStatic
void compileItWithStatic() {
Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
assert (mutMap[1L] += 20).val == 20;
}
compileItWithStatic()
I got the following error:
*Script1.groovy: 17: [Static type checking] -
Cannot call <K,V> java.util.Map <java.lang.Long, MutableInt>#putAt(java.lang.Long, MutableInt) with arguments [long, int]*
How can I override the '+=' operator and compile it with static without error?
EDIT:
If I am doing like this without compile static it works fine:
def m1 = new MutableInt(1);
assert (m1 += 1).val == 2 // <----- caution: '+=' not '+' as in previous case
However, if it was inside the method like this:
#groovy.transform.CompileStatic
void compileItWithStatic_2() {
def m1 = new MutableInt(1);
assert (m1 += 1).val == 2
}
The error will be:
Script1.groovy: -1: Access to java.lang.Object#val is forbidden # line -1, column -1.
1 error
P.S. It won't work with static compilation not with dynamic compilation.
The assignment part is throwing the error. A simple + works:
class MutableInt {
int val
MutableInt(int val) { this.val = val }
MutableInt plus(int val) {
return new MutableInt(this.val += val)
}
}
def m1 = new MutableInt(1);
assert (m1 + 1).val == 2;
#groovy.transform.CompileStatic
def compileItWithStatic() {
Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
mutMap[1L] + 20
mutMap
}
assert compileItWithStatic()[1L].val == 20
Groovy is parsing mutMap[1L] += 20 as mutMap.putAt(1L, 20). This looks like a bug to me. This works: mutMap[1L] = mutMap[1L] + 20, albeit more verbose.
Edit: the second error seems related to the result of the expression (m1 + 1) being parsed as Object. This should work:
#groovy.transform.CompileStatic
void compileItWithStatic_2() {
def m1 = new MutableInt(1) + 1;
assert m1.val == 2
}
I have just started learning Groovy which looks really awesome!
This is very simple example.
"Groovy".each {a -> println a};
It nicely prints as given below.
G
r
o
o
v
y
My question is - 'each' method is not part of String object as per the link below. Then how come it works?
http://beta.groovy-lang.org/docs/latest/html/groovy-jdk/
How can i get the parameters list for a closure of an object?
example String.each has 1 parameter, Map.each has 1 or 2 parameters like entry or key & value.
The relevant code in DefaultGroovyMethods is
public static Iterator iterator(Object o) {
return DefaultTypeTransformation.asCollection(o).iterator();
}
which contains:
else if (value instanceof String) {
return StringGroovyMethods.toList((String) value);
}
String toList is:
public static List<String> toList(String self) {
int size = self.length();
List<String> answer = new ArrayList<String>(size);
for (int i = 0; i < size; i++) {
answer.add(self.substring(i, i + 1));
}
return answer;
}
Haxe seems to assume that certain things must be Int. In the following function,
class Main {
static function main() {
function mult_s<T,A>(s:T,x:A):A { return cast s*x; }
var bb = mult_s(1.1,2.2);
}
}
I got (with Haxe 3.01):
Main.hx:xx: characters 48-49 : mult_s.T should be Int
Main.hx:xx: characters 50-51 : mult_s.A should be Int
Can anyone please explain why T and A should be Int instead of Float?
A more puzzling example is this:
class Main {
public static function min<T:(Int,Float)>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //compile error
var b = min(1,2); //ok
}
}
I can't see why t<t2 implies that either t or t2 is Int. But Haxe seems prefer Int: min is fine if called with Int's but fails if called with Float's. Is this reasonable?
Thanks,
min<T:(Int,Float)> means T should be both Int and Float. See the constraints section of Haxe Manual.
Given Int can be converted to Float implicitly, you can safely remove the constraint of Int. i.e. the following will works:
http://try.haxe.org/#420bC
class Test {
public static function min<T:Float>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //ok
$type(a); //Float
trace(a); //1.1
var b = min(1,2); //ok
$type(b); //Int
trace(b); //1
}
}
I was recently tripped up by the fact that the expected type of a setter that sets an Int is Int -> Int.
Why does a setter return a value? What significance does this value have?
Small addition to other answers over here, it allows you to do this:
x = y = z = 5;
The value that the setter returns is the value of the assignment expression.
For instance, if you were to do something like this:
public var x(setX, getX): Int
public function setX(val: Int): Int {
return 5;
}
static function main() {
neko.Lib.print(x = 2); // Prints 5
}
Haxe would print out 5. The setter returns the value of the set expression. Of course, it's a nonsensical value in this case.
In the real world, it permits a way of implementing copy by value on assignment, eg:
public var pos(set_pos, default):Point;
function set_pos(newPos:Point) {
pos.x = newPos.x
pos.y = newPos.y;
return pos;
}
And also of having a sensible return when implementing setters that can fail, eg:
public var positiveX(default, set_positiveX):Int;
function set_positiveX(newX:Int) {
if (newX >= 0) x = newX;
return x;
}
trace(x = 10); // 10
trace(x = -4); // 10
trace(x); // 10
Whereas you would otherwise get something like this:
trace(x = 10); // 10
trace(x = -4); // -4
trace(x); // 10
Which is what happens in AS3 even if the setter does not modify the value. If you could not do this, clearly the first, where x = -4 returns 10 is better :)
I want to implement Maybe from Haskell in D, just for the hell of it.
This is what I've got so far, but it's not that great. Any ideas how to improve it?
class Maybe(a = int){ } //problem 1: works only with ints
class Just(alias a) : Maybe!(typeof(a)){ }
class Nothing : Maybe!(){ }
Maybe!int doSomething(in int k){
if(k < 10)
return new Just!3; //problem 2: can't say 'Just!k'
else
return new Nothing;
}
Haskell Maybe definition:
data Maybe a = Nothing | Just a
what if you use this
class Maybe(T){ }
class Just(T) : Maybe!(T){
T t;
this(T t){
this.t = t;
}
}
class Nothing : Maybe!(){ }
Maybe!int doSomething(in int k){
if(k < 10)
return new Just!int(3);
else
return new Nothing;
}
personally I'd use tagged union and structs though (and enforce it's a Just when getting the value)
Look at std.typecons.Nullable. It's not exactly the same as Maybe in Haskell, but it's a type which optionally holds a value of whatever type it's instantiated with. So, effectively, it's like Haskell's Maybe, though syntactically, it's a bit different. The source is here if you want to look at it.
I haven't used the Maybe library, but something like this seems to fit the bill:
import std.stdio;
struct Maybe(T)
{
private {
bool isNothing = true;
T value;
}
void opAssign(T val)
{
isNothing = false;
value = val;
}
void opAssign(Maybe!T val)
{
isNothing = val.isNothing;
value = val.value;
}
T get() #property
{
if (!isNothing)
return value;
else
throw new Exception("This is nothing!");
}
bool hasValue() #property
{
return !isNothing;
}
}
Maybe!int doSomething(in int k)
{
Maybe!int ret;
if (k < 10)
ret = 3;
return ret;
}
void main()
{
auto retVal = doSomething(5);
assert(retVal.hasValue);
writeln(retVal.get);
retVal = doSomething(15);
assert(!retVal.hasValue);
writeln(retVal.hasValue);
}
With some creative operator overloading, the Maybe struct could behave quite naturally. Additionally, I've templated the Maybe struct, so it can be used with any type.