How to specify character literal in groovy? - groovy

How do I specify a character literal in groovy since both 'a' and "a" result in string?
I do not want to declare a character variable just for this purpose.

Using the as keyword is the way to make a character literal in Groovy.
'a' as char
See the discussion here at Groovy's buglist.

If this is for a variable, you can also define the type, so:
import java.awt.image.*
new BufferedImage( 1, 1, BufferedImage.TYPE_INT_RGB ).with {
createGraphics().with {
// Declare the type
char aChar = 'a'
// Both ways are equivalent and work
assert fontMetrics.charWidth( aChar ) == fontMetrics.charWidth( 'a' as char )
dispose()
}
}
(apologies for the long example, but I had brain freeze, and couldn't think of a different standard java function that takes a char) ;-)
This also goes against the second line of the question, but I thought I'd add it for completeness

There a three ways to use char literals in Groovy:
char c = 'c' /* 1 */
'c' as char /* 2 */
(char) 'c' /* 3 */
println Character.getNumericValue(c) /* 1 */
println Character.getNumericValue('c' as char) /* 2 */
println Character.getNumericValue((char) 'c') /* 3 */
If you assign a String literal like 'c' to a variable, Groovy does the cast implicitly (see /* 1 * /). If you want use the String literals without variables, you have to cast them by using ...as char... (see /* 2 * /) or ...(char)... (see /* 3 * /).
The usage of char literals in methods without casting them is not possible as Groovy has only String literals which must be casted to char.
println Character.getNumericValue('c') // compile error

This response is rather late! But just stumbled upon it and wanted to add some clarification.
The more accurate Answer is unlike Java, Groovy does NOT have a character literal, but you can cast a string to a character. A literal is a value that is written exactly as it is to be interpreted, and the necessity of the type cast indicates it is NOT truly a literal.
Examples:
assert 'a'.class != Character.class
assert 'a'.class == String.class
assert ('a' as char).class == Character.class
assert ((char)'a').class == Character.class
char A = 'a'; // implicit coercion of string to char
assert A.class == Character.class
In contrast, both groovy and Java support numeric literals for int, long, double, and float, but do not support numeric literal for short.
Examples:
assert 42.class == Integer.class
assert 42l.class == Long.class
assert 42f.class == Float.class
assert 42d.class == Double.class
assert (42 as Short).class == Short.class

Related

Groovy Cast primitive type

I want to set fields dynamically in groovy so I have a java code that get datas from a database and I set groovy fields using Bindings.setVariable() in java.
I would like to know if it is possible to cast each primitive types in groovy.
String to int, String to float and so on.
So I could always send a string and cast in an other primitive times, it depends of the type of my groovy fields.
#Opal's as solution is good, but I also wanted to mention that the Groovy JDK adds some convenient primitive check and conversion methods to CharSequence, which String implements:
isDouble and asDobule
isFloat and asFloat
isLong and asLong
isInteger and asInteger
Interestingly, it isFloat seems to be greedy, returning true for floating points beyond its range.
['2', '2.2', '2' * 10, "${Double.MAX_VALUE}"].each { s ->
switch (s) {
case { it.isInteger() }:
int i = s.toInteger()
println "String '$s' -> int $i"
break
case { it.isLong() }:
long l = s.toLong()
println "String '$s' -> long $l"
break
case { it.isFloat() }:
float f = s.toFloat()
println "String '$s' -> float $f"
break
case { it.isDouble() }:
double d = s.toDouble()
println "String '$s' -> double $d"
break
default:
println "$s is not a supported primitive"
}
}
prints out
String '2' -> int 2
String '2.2' -> float 2.2
String '2222222222' -> long 2222222222
String '1.7976931348623157E308' -> float Infinity
It depends on what you exactly need, but the following piece of code works well:
assert '2' as Integer == 2
assert '2.2' as Double == 2.2

Range ordering and inequality comparison

I was trying to recreate Python's range as a learning exercise, and noticed that ranges had range.__gt__, range.__ge__ etc. attribute. It was specifically defined in range, as range also has 8 attributes with the qualified name of object.__...__.
I was wondering what the range comparisons are used for. Any attempt at range(*x) <= range(*y) raises a TypeError: unorderable types: range() > range()
The Python 3 range object defines the following rich comparisons (taken from the C source):
static PyObject *
range_richcompare(PyObject *self, PyObject *other, int op)
{
int result;
if (!PyRange_Check(other))
Py_RETURN_NOTIMPLEMENTED;
switch (op) {
case Py_NE:
case Py_EQ:
result = range_equals((rangeobject*)self, (rangeobject*)other);
if (result == -1)
return NULL;
if (op == Py_NE)
result = !result;
if (result)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
case Py_LE:
case Py_GE:
case Py_LT:
case Py_GT:
Py_RETURN_NOTIMPLEMENTED;
default:
PyErr_BadArgument();
return NULL;
}
}
As you can see, the only comparisons that are actually implemented are NE and EQ which are for inequality and equality. The other comparisons, like larger-equals, larger-than, etc., are all Py_RETURN_NOTIMPLEMENTED, so while they are “technically” implemented (as in the builtin object defines the comparison methods), they throw a NotImplementedError.

Char Array Returning Integers

I've been working through this exercise, and my output is not what I expect.
(Check substrings) You can check whether a string is a substring of another string
by using the indexOf method in the String class. Write your own method for
this function. Write a program that prompts the user to enter two strings, and
checks whether the first string is a substring of the second.
** My code compromises with the problem's specifications in two ways: it can only display matching substrings to 3 letters, and it cannot work on string literals with less than 4 letters. I mistakenly began writing the program without using the suggested method, indexOf. My program's objective (although it shouldn't entirely deviate from the assignment's objective) is to design a program that determines whether two strings share at least three consecutive letters.
The program's primary error is that it generates numbers instead of char characters. I've run through several, unsuccessful ideas to discover what the logical error is. I first tried to idenfity whether the char characters (which, from my understanding, are underwritten in unicode) were converted to integers, considering that the outputted numbers are also three letters long. Without consulting a reference, I know this isn't true. A comparison between java and javac outputted permutation of 312, and a comparison between abab and ababbab ouputted combinations of 219. j should be > b. My next thought was that the ouputs were indexes of the arrays I used. Once again, this isn't true. A comparison between java and javac would ouput 0, if my reasoning were true.
public class Substring {
public static char [] array;
public static char [] array2;
public static void main (String[]args){
java.util.Scanner input = new java.util.Scanner (System.in);
System.out.println("Enter your two strings here, the longer one preceding the shorter one");
String container1 = input.next();
String container2 = input.next();
char [] placeholder = container1.toCharArray();
char [] placeholder2 = container2.toCharArray();
array = placeholder;
array2 = placeholder2;
for (int i = 0; i < placeholder2.length; i++){
for (int j = 0; j < placeholder.length; j ++){
if (array[j] == array2[i]) matcher(j,i);
}
}
}
public static void matcher(int higher, int lower){
if ((higher < array.length - 2) && (lower < array2.length - 2))
if (( array[higher+1] == array2[lower+1]) && (array[higher+2] == array2[lower+2]))
System.out.println(array[higher] + array[higher+1] + array[higher+2] );
}
}
The + operator promotes shorts, chars, and bytes operands to ints, so
array[higher] + array[higher+1] + array[higher+2]
has type int, not type char which means that
System.out.println(...)
binds to
System.out.println(int)
which displays its argument as a decimal number, instead of binding to
System.out.println(char)
which outputs the given character using the PrintStream's encoding.

Groovy collect over a String

When I collect over a String I was expecting that it would be of type char, but it is java.lang.String. So why is this and how can I collect all characters of a String?
You can do something like this...
someString.collect {
def c = it as char
// carry on...
}
Or...
someString.chars.collect {
// it will be a char
// carry on...
}
In Groovy, a single character is also a String. In order to get each String as a Character use as:
"testString".collect { it as char }

How does type promotion work in Groovy?

Consider the following code snippet -
def factorial(number) {
if(number == 1)
return number;
else
return number * factorial(number - 1);
}
println factorial(50)
println factorial(50).getClass()
println()
println 45**20
println ((45**20).getClass())
The output is -
0
class java.lang.Integer
1159445329576199417209625244140625
class java.math.BigInteger
Questions -
Why doesn't groovy automatically promote the result of number * factorial(number-1) to a BigInt in the first case?
Why is the output 0? Why isn't it some random number that we should get after integer overflow?
Old question but I'll try to answer both parts of the question:
Groovy documentation on arithmetic operations states that
binary operations involving subclasses of java.lang.Number automatically convert their arguments according to the following matrix (except for division, which is discussed below)
I won't paste the matrix but it specifies no casting to BigInteger or BigDecimal unless one of the operators is of one of these types.
In the case of division:
The division operators "/" and "/=" produce a Double result if either operand is either Float or Double and a BigDecimal result otherwise
I think that the table is not considering the power operator (**) since it's not present in Java and as stated in #tim_yates comment, power implementation uses BigInteger by default.
The code in DefaultGroovyMethods.java shows clearly that the power of int's is calculated using BigInteger's and if the result is small then is cast down to int again (And that's why (2**4).class is java.lang.Integer):
public static Number power(Integer self, Integer exponent) {
if (exponent >= 0) {
BigInteger answer = BigInteger.valueOf(self).pow(exponent);
if (answer.compareTo(BI_INT_MIN) >= 0 && answer.compareTo(BI_INT_MAX) <= 0) {
return answer.intValue();
} else {
return answer;
}
} else {
return power(self, (double) exponent);
}
}
To confirm the behaviour of other operations you can go to IntegerMath, LongMath or other classes in the org.codehaus.groovy.runtime.typehandling package
With Groovy, Integer.multiply( Integer ) always returns an Integer.
The factorial method starts overflowing around step 16.
At step 34, you end up with -2147483648 * -2147483648 which returns 0 so the result will always be 0
One fix is to change your method declaration to:
def factorial( BigInteger number ) {

Resources