How does switch statements work in java 1.5 with string arguments? - switch-statement

Can i implement switch statements(by passing string arguments) in java 5 without making use of enums?I tried doing it using hashcode but i got an error
package com.list;
import java.util.Scanner;
public class SwitchDays implements Days {
static final int str = "sunday".hashCode();
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String day= in.nextLine();
switch (day.hashCode()) {
case str:
System.out.println(day);
break;
default:
break;
}
}
}
str in case str given an error:
case expressions must be constant expressions
Please guide.

The problem is that str is referring to the expression "sunday".hashCode(), which is not a compile time constant expression as described by the JLS:
A constant expression is an expression denoting a value of primitive
type or a String that does not complete abruptly and is composed using
only the following: ... Qualified names (§6.5.6.2) of the form
TypeName . Identifier that refer to constant variables (§4.12.4).
When you check the definition of constant variables:
A constant variable is a final variable of primitive type or type
String that is initialized with a constant expression (§15.28).
Whether a variable is a constant variable or not may have implications
with respect to class initialization (§12.4.1), binary compatibility
(§13.1, §13.4.9), and definite assignment (§16 (Definite Assignment)).
Since "sunday".hashCode() does not meet this requirements, you get the error.
If you would change "sunday".hashCode() to a real compile time constant like 3 it would compile.

The most straight forward solution is to make an enum, ie.
enum Days{
sunday, monday;
}
Then it could be used as:
Day d = Day.valueOf("sunday");
switch(d){
case sunday:
System.out.println("ONE");
break;
case monday:
System.out.println("TWO");
break;
}

Related

Misleading exception message in GatewayMethodInboundMessageMapper with un-annotated parameters

The following code throws a MessagingException with message At most one parameter (or expression via method-level #Payload) may be mapped to the payload or Message. Found more than one on method [public abstract java.lang.Integer org.example.PayloadAndGatewayHeader$ArithmeticGateway.add(int,int)].
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "add.input", headers = #GatewayHeader(name = "operand", expression = "#args[1]"))
Integer add(#Payload final int a, final int b);
}
The desired functionality could be achieved with something like:
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "add.input", headers = #GatewayHeader(name = "operand", expression = "#args[1]"))
#Payload("#args[0]")
Integer add(final int a, final int b);
}
Should the first version also work? Nevertheless I believe the error message could be improved.
A sample project can be found here. Please check org.example.PayloadAndGatewayHeader and org.example.PayloadAndGatewayHeaderTest.
EDIT
The purpose of #GatewayHeader was to show why one may want to have additional parameters that will not be part of the payload but I am afraid it created confusion. Here is a more streamlined example:
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "identity.input")
Integer identity(#Payload final int a, final int unused);
}
Shouldn't the unused parameter be ignored since there is already another one that is annotated with #Payload?
You can't mix parameter annotations (which are static) with expressions (which are dynamic) because the static code analysis can't anticipate what the dynamic expression will resolve to at runtime. It is probably unlikely, but there theoretically could be conditions in the expression. In any case, it can't determine at analysis time that the expression will provide a value for #args[1] at runtime (it could, of course for this simple case, but not all cases are this simple).
Use one or the other; use your second approach or
Integer add(#Payload final int a, #Header("operand") final int b);

Difference between String and StaticString

I was browsing the docs, and I found StaticString. It states:
An simple string designed to represent text that is "knowable at compile-time".
I originally thought that String has the same behaviour as NSString, which is known at compile time, but it looks like that I was wrong. So my question is when should we use StaticString instead of a String, and is the only difference is that StaticString is known at compile-time?
One thing I found is
var a: String = "asdf" //"asdf"
var b: StaticString = "adsf" //{(Opaque Value), (Opaque Value), (Opaque Value)}
sizeofValue(a) //24
sizeofValue(b) //17
So it looks like StaticString has a little bit less memory footprint.
It appears that StaticString can hold string literals. You can't assign a variable of type String to it, and it can't be mutated (with +=, for example).
"Knowable at compile time" doesn't mean that the value held by the variable will be determined at compile time, just that any value assigned to it is known at compile time.
Consider this example which does work:
var str: StaticString
for _ in 1...10 {
switch arc4random_uniform(3) {
case 0: str = "zero"
case 1: str = "one"
case 2: str = "two"
default: str = "default"
}
print(str)
}
Any time you can give Swift more information about how a variable is to be used, it can optimize the code using it. By restricting a variable to StaticString, Swift knows the variable won't be mutated so it might be able to store it more efficiently, or access the individual characters more efficiently.
In fact, StaticString could be implemented with just an address pointer and a length. The address it points to is just the place in the static code where the string is defined. A StaticString doesn't need to be reference counted since it doesn't (need to) exist in the heap. It is neither allocated nor deallocated, so no reference count is needed.
"Knowable at compile time" is pretty strict. Even this doesn't work:
let str: StaticString = "hello " + "world"
which fails with error:
error: 'String' is not convertible to 'StaticString'
StaticString is knowable at compile time. This can lead to optimizations. Example:
EDIT: This part doesn't work, see edit below
Suppose you have a function that calculates an Int for some String values for some constants that you define at compile time.
let someString = "Test"
let otherString = "Hello there"
func numberForString(string: String) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
let some = numberForString(someString)
let other = numberForString(otherString)
Like this, the function would be executed with "Test" and "Hello there" when it really gets called in the program, when the app starts for example. Definitely at runtime. However if you change your function to take a StaticString
func numberForString(string: StaticString) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
the compiler knows that the passed in StaticString is knowable at compile time, so guess what it does? It runs the function right at compile time (How awesome is that!). I once read an article about that, the author inspected the generated assembly and he actually found the already computed numbers.
As you can see this can be useful in some cases like the one mentioned, to not decrease runtime performance for stuff that can be done at compile time.
EDIT: Dániel Nagy and me had a conversation. The above example of mine doesn't work because the function stringValue of StaticString can't be known at compile time (because it returns a String). Here is a better example:
func countStatic(string: StaticString) -> Int {
return string.byteSize // Breakpoint here
}
func count(string: String) -> Int {
return string.characters.count // Breakpoint here
}
let staticString : StaticString = "static string"
let string : String = "string"
print(countStatic(staticString))
print(count(string))
In a release build only the second breakpoint gets triggered whereas if you change the first function to
func countStatic(string: StaticString) -> Int {
return string.stringValue.characters.count // Breakpoint here
}
both breakpoints get triggered.
Apparently there are some methods which can be done at compile time while other can't. I wonder how the compiler figures this out actually.

Constants in Haxe

How do you create public constants in Haxe? I just need the analog of good old const in AS3:
public class Hello
{
public static const HEY:String = "hey";
}
The usual way to declare a constant in Haxe is using the static and inline modifiers.
class Main {
public static inline var Constant = 1;
static function main() {
trace(Constant);
trace(Test.Constant);
}
}
If you have a group of related constants, it can often make sense to use an enum abstract. Values of enum abstracts are static and inline implicitly.
Note that only the basic types (Int, Float, Bool) as well as String are allowed to be inline, for others it will fail with this error:
Inline variable initialization must be a constant value
Luckily, Haxe 4 has introduced a final keyword which can be useful for such cases:
public static final Regex = ~/regex/;
However, final only prevents reassignment, it doesn't make the type immutable. So it would still be possible to add or remove values from something like static final Values = [1, 2, 3];.
For the specific case of arrays, Haxe 4 introduces haxe.ds.ReadOnlyArray which allows for "constant" lists (assuming you don't work around it using casts or reflection):
public static final Values:haxe.ds.ReadOnlyArray<Int> = [1, 2, 3];
Values = []; // Cannot access field or identifier Values for writing
Values.push(0); // haxe.ds.ReadOnlyArray<Int> has no field push
Even though this is an array-specific solution, the same approach can be applied to other types as well. ReadOnlyArray<T> is simply an abstract type that creates a read-only "view" by doing the following:
it wraps Array<T>
it uses #:forward to only expose fields that don't mutate the array, such as length and map()
it allows implicit casts from Array<T>
You can see how it's implemented here.
For non-static variables and objects, you can give them shallow constness as shown below:
public var MAX_COUNT(default, never):Int = 100;
This means you can read the value in the 'default' way but can 'never' write to it.
More info can be found http://adireddy.github.io/haxe/keywords/never-inline-keywords.

Accumulating Lexer errors in ANTLR 4

I am trying to accumulate lexer errors when Lexing in run time. I have followed the exact way of achieving this for parser errors as in this answer. But when I try to do this to the Lexer.
class Class2 : IAntlrErrorListener<IToken>
{
public void SyntaxError(IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
{
Console.WriteLine("Error in lexer at line " + ":" + e.OffendingToken.Column + e.OffendingToken.Line + e.Message);
}
}
and register this listener as below.
Class2 z = new Class2();
lexer.AddErrorListener(z);
But this gives a error which is unexpected.
Argument 1: cannot convert from 'CSSParserAntlr.Class2' to 'Antlr4.Runtime.IAntlrErrorListener<int>'
and
The best overloaded method match for 'Antlr4.Runtime.Recognizer<int,Antlr4.Runtime.Atn.LexerATNSimulator>.AddErrorListener(Antlr4.Runtime.IAntlrErrorListener<int>)' has some invalid arguments
Please give me some reason why this is happening.
First, the reason you are getting this exception is because you need to declare Class2 as follows:
class Class2 : IAntlrErrorListener<int>
in order to match the class signature of Lexer defined as follows:
public abstract class Lexer : Recognizer<int, LexerATNSimulator>, ITokenSource
The method signature for AddErrorListener is defined in Recognizer to match the Symbol type from the class definition as follows:
public abstract class Recognizer<Symbol, ATNInterpreter> : IRecognizer
This means that Lexer specifies "int" as the "Symbol" when extending Recognizer, and so the AddErrorListener method requires an IAntlrErrorListener of type int.
Now, the real answer to your question: don't write an error listener for a lexer. Errors in the lexing are the fault of the lex grammar, not of the user input. Error listeners are useful for handling bad user input in a Parser. Lexer grammars should be tested for coverage during development - i.e., all possible input will match some token. If you encounter a lex error during development, the default error listener will do just fine.
For more information, see the answer here: ANTLR4 Lexer error reporting (length of offending characters)

duck typing in D

I'm new to D, and I was wondering whether it's possible to conveniently do compile-time-checked duck typing.
For instance, I'd like to define a set of methods, and require that those methods be defined for the type that's being passed into a function. It's slightly different from interface in D because I wouldn't have to declare that "type X implements interface Y" anywhere - the methods would just be found, or compilation would fail. Also, it would be good to allow this to happen on any type, not just structs and classes. The only resource I could find was this email thread, which suggests that the following approach would be a decent way to do this:
void process(T)(T s)
if( __traits(hasMember, T, "shittyNameThatProbablyGetsRefactored"))
// and presumably something to check the signature of that method
{
writeln("normal processing");
}
... and suggests that you could make it into a library call Implements so that the following would be possible:
struct Interface {
bool foo(int, float);
static void boo(float);
...
}
static assert (Implements!(S, Interface));
struct S {
bool foo(int i, float f) { ... }
static void boo(float f) { ... }
...
}
void process(T)(T s) if (Implements!(T, Interface)) { ... }
Is is possible to do this for functions which are not defined in a class or struct? Are there other/new ways to do it? Has anything similar been done?
Obviously, this set of constraints is similar to Go's type system. I'm not trying to start any flame wars - I'm just using D in a way that Go would also work well for.
This is actually a very common thing to do in D. It's how ranges work. For instance, the most basic type of range - the input range - must have 3 functions:
bool empty(); //Whether the range is empty
T front(); // Get the first element in the range
void popFront(); //pop the first element off of the range
Templated functions then use std.range.isInputRange to check whether a type is a valid range. For instance, the most basic overload of std.algorithm.find looks like
R find(alias pred = "a == b", R, E)(R haystack, E needle)
if (isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{ ... }
isInputRange!R is true if R is a valid input range, and is(typeof(binaryFun!pred(haystack.front, needle)) : bool) is true if pred accepts haystack.front and needle and returns a type which is implicitly convertible to bool. So, this overload is based entirely on static duck typing.
As for isInputRange itself, it looks something like
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = void; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
It's an eponymous template, so when it's used, it gets replaced with the symbol with its name, which in this case is an enum of type bool. And that bool is true if the type of the expression is non-void. typeof(x) results in void if the expression is invalid; otherwise, it's the type of the expression x. And is(y) results in true if y is non-void. So, isInputRange will end up being true if the code in the typeof expression compiles, and false otherwise.
The expression in isInputRange verifies that you can declare a variable of type R, that R has a member (be it a function, variable, or whatever) named empty which can be used in a condition, that R has a function named popFront which takes no arguments, and that R has a member front which returns a value. This is the API expected of an input range, and the expression inside of typeof will compile if R follows that API, and therefore, isInputRange will be true for that type. Otherwise, it will be false.
D's standard library has quite a few such eponymous templates (typically called traits) and makes heavy use of them in its template constraints. std.traits in particular has quite a few of them. So, if you want more examples of how such traits are written, you can look in there (though some of them are fairly complicated). The internals of such traits are not always particularly pretty, but they do encapsulate the duck typing tests nicely so that template constraints are much cleaner and more understandable (they'd be much, much uglier if such tests were inserted in them directly).
So, that's the normal approach for static duck typing in D. It does take a bit of practice to figure out how to write them well, but that's the standard way to do it, and it works. There have been people who have suggested trying to come up with something similar to your Implements!(S, Interface) suggestion, but nothing has really come of that of yet, and such an approach would actually be less flexible, making it ill-suited for a lot of traits (though it could certainly be made to work with basic ones). Regardless, the approach that I've described here is currently the standard way to do it.
Also, if you don't know much about ranges, I'd suggest reading this.
Implements!(S, Interface) is possible but did not get enough attention to get into standard library or get better language support. Probably if I won't be the only one telling it is the way to go for duck typing, we will have a chance to have it :)
Proof of concept implementation to tinker around:
http://dpaste.1azy.net/6d8f2dc4
import std.traits;
bool Implements(T, Interface)()
if (is(Interface == interface))
{
foreach (method; __traits(allMembers, Interface))
{
foreach (compareTo; MemberFunctionsTuple!(Interface, method))
{
bool found = false;
static if ( !hasMember!(T, method) )
{
pragma(msg, T, " has no member ", method);
return false;
}
else
{
foreach (compareWhat; __traits(getOverloads, T, method))
{
if (is(typeof(compareTo) == typeof(compareWhat)))
{
found = true;
break;
}
}
if (!found)
{
return false;
}
}
}
}
return true;
}
interface Test
{
bool foo(int, double);
void boo();
}
struct Tested
{
bool foo(int, double);
// void boo();
}
pragma(msg, Implements!(Tested, Test)());
void main()
{
}

Resources