Pass Type into function in Kotlin - kotlin

In Swift you can pass a type into a function like so:
func foo<T>(_ type: T.Type)
foo(String.self)
Is there any equivalent in Kotlin?
I don't want to specify the type in the generic arguments, because there are multiple generic arguments and it would be annoying to have to specify them all when the compiler can work it out itself except for this one. Also I don't want to use KClass as that requires the type to by Any which I don't want to make a requirement for the type.

you can you class.java.typeName
/**
* Return an informative string for the name of this type.
*
* #return an informative string for the name of this type
* #since 1.8
*/
public String getTypeName() {
if (isArray()) {
try {
Class<?> cl = this;
int dimensions = 0;
do {
dimensions++;
cl = cl.getComponentType();
} while (cl.isArray());
StringBuilder sb = new StringBuilder();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
return getName();
}
foo(Int::class.java.typeName)
foo(String::class.java.typeName)

Related

Creating a class with implicit operators but it only works one way

A UDouble is an object that has units associated with the value (Value). The Unit is much more complex than shown here, but was converted to a string for the example.
public class UDouble
{
public string Unit { get; set; }
public double Value;
public UDouble(string unit)
{
Unit = unit;
}
public UDouble(string unit, double value)
{
Unit = unit;
Value = value;
}
public static implicit operator double(UDouble m)
{
return m.Value;
}
//public static implicit operator UDouble(double d)
//{
// return new UDouble("?????????", d); // wrong - units are lost
//}
}
static void Main()
{
UDouble p = new UDouble("mm", 2.3);
p.Value = 3;
double t = p;
p = 10.5;
}
The last line in the main() function (p = 10.5;) does not compile. What I what is the UDouble to act as if it is a double. In other words, I am trying to get p = 10.5; to work like p.Value = 10.5;
Is there a way to make it work?

vala iterator next_value method return type

From vala tutorial:
alternative iterator protocol: "T? next_value()"
If the iterator object has a .next_value() function that returns a nullable type then we iterate by calling this function until it returns null.
I write some code, but got an error.
the error message:
error: return type of `Something.next_value' must be nullable
foreach (string s in A) {
^
I don't understand, it is nullable already in my next_value return type.
How to correct this code?
public static void main() {
stdout.printf("hello\n");
var A = new Something<string> ({"aa", "bb"});
foreach (string s in A) {
stdout.puts(s);
stdout.puts ("\n");
}
}
public class Something<T> : Object {
public T[] data;
private int _size;
private int _i = 0;
public Something (owned T[] a){
this.data = a;
this._size = data.length;
}
public Something<T> iterator(){
return this;
}
// error: return type of `Something.next_value' must be nullable
// foreach (string s in A) {
// ^
public T? next_value () {
return _i < _size ? data[_i++] : null;
}
}
You have declared that the generic data type must be nullable, which is correct. So when you pass the specific data type as a type argument make sure it is also nullable. The line:
var A = new Something<string> ({"aa", "bb"});
should be:
var A = new Something<string?> ({"aa", "bb"});

hive querying records for a specific uniontype

I have a sample hive table created as
CREATE TABLE union_test(foo UNIONTYPE<int, double, array<string>, struct<a:int,b:string>>);
The data can be viewed as
SELECT foo FROM union_test;
The output is
{0:1}
{1:2.0}
{2:["three","four"]}
{3:{"a":5,"b":"five"}}
{2:["six","seven"]}
{3:{"a":8,"b":"eight"}}
{0:9}
{1:10.0}
the first field (tag) denotes the type of the union ( 0 for int, 1 for double, 2 for array etc).
My problem is if I found to select only those records where the union type is 2 (array), how should I frame my query?
There is no function in Hive to read data from UnionType. So i wrote 2 UDF´s. One to get Union tag (that you trying to do) and second to get struct from union as an example.
get_union_tag() function:
package HiveUDF;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.UnionObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
#Description(name = "get_union_tag", value = "_FUNC_(unionObject)"
+ " - Returns union object Tag", extended = "Example:\n" + " > SELECT _FUNC_(unionObject) FROM src LIMIT 1;\n one")
public class GetUnionTag extends GenericUDF {
// Global variables that inspect the input.
// These are set up during the initialize() call, and are then used during the
// calls to evaluate()
private transient UnionObjectInspector uoi;
#Override
// This is what we do in the initialize() method:
// Verify that the input is of the type expected
// Set up the ObjectInspectors for the input in global variables
// Return the ObjectInspector for the output
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
// Verify the input is of the required type.
// Set the global variables (the various ObjectInspectors) while we're doing this
// Exactly one input argument
if( arguments.length != 1 ){
throw new UDFArgumentLengthException("_FUNC_(unionObject) accepts exactly one argument.");
}
// Is the input an array<>
if( arguments[0].getCategory() != ObjectInspector.Category.UNION ){
throw new UDFArgumentTypeException(0,"The single argument to AddExternalIdToPurchaseDetails should be "
+ "Union<>"
+ " but " + arguments[0].getTypeName() + " is found");
}
// Store the ObjectInspectors for use later in the evaluate() method
uoi = ((UnionObjectInspector)arguments[0]);
// Set up the object inspector for the output, and return it
return PrimitiveObjectInspectorFactory.javaByteObjectInspector;
}
#Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
byte tag = uoi.getTag(arguments[0].get());
return tag;
}
#Override
public String getDisplayString(String[] children) {
StringBuilder sb = new StringBuilder();
sb.append("get_union_tag(");
for (int i = 0; i < children.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(children[i]);
}
sb.append(')');
return sb.toString();
}
}
function get_struct_from_union() UDF :
package HiveUDF;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.UnionObjectInspector;
#Description(name = "get_union_struct", value = "_FUNC_(unionObject)"
+ " - Returns struct ", extended = "Example:\n" + " > _FUNC_(unionObject).value \n 90.0121")
public class GetUnionStruct extends GenericUDF {
// Global variables that inspect the input.
// These are set up during the initialize() call, and are then used during the
// calls to evaluate()
//
// ObjectInspector for the list (input array<>)
// ObjectInspector for the struct<>
// ObjectInspectors for the elements of the struct<>, target, quantity and price
private UnionObjectInspector unionObjectInspector;
private StructObjectInspector structObjectInspector;
#Override
// This is what we do in the initialize() method:
// Verify that the input is of the type expected
// Set up the ObjectInspectors for the input in global variables
// Return the ObjectInspector for the output
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
// Verify the input is of the required type.
// Set the global variables (the various ObjectInspectors) while we're doing this
// Exactly one input argument
if( arguments.length != 1 ){
throw new UDFArgumentLengthException("_FUNC_(unionObject) accepts exactly one argument.");
}
// Is the input an array<>
if( arguments[0].getCategory() != ObjectInspector.Category.UNION ){
throw new UDFArgumentTypeException(0,"The single argument to AddExternalIdToPurchaseDetails should be "
+ "Union<Struct>"
+ " but " + arguments[0].getTypeName() + " is found");
}
// Set up the object inspector for the output, and return it
return structObjectInspector;
}
#Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
return ((UnionObjectInspector) unionObjectInspector).getField(arguments[0].get());
}
#Override
public String getDisplayString(String[] children) {
StringBuilder sb = new StringBuilder();
sb.append("get_union_vqtstruct(");
for (int i = 0; i < children.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(children[i]);
}
sb.append(')');
return sb.toString();
}
}
to use these UDF´s compile and create jar file. Than upload into hive (in my case HDInsight). Than just use
add jar wasb:///hive/HiveGUDF.jar;
CREATE TEMPORARY FUNCTION get_union_struct AS 'HiveUDF.GetUnionStruct';
before u run e.g.
SELECT get_union_tag(exposed) FROM test;

How to determine input datatype?

I want to accept two inputs. If both the inputs are integer then add them. If any or both the inputs are string then concatenate them. I want to know the code to determine whether the input is integer or string?
Thanks for reading...
You can use method overloading for this,
Check out Java code given below
public class MethodExample
{
public static void main (String[] args)
{
int a,b;
String string1,string2;
//accept values for all variables...;>>
System.Out.Println("Addtion is "+sum(a,b));
System.Out.Println("Contact is "+sum(string1,string2));
}
int sum(int a,int b)
{
return(a+b);
}
String sum(string a,string b)
{
return(a+b);
}
}
I have used the following logic:
Console.WriteLine("Enter two inputs:");
string s1 = Console.ReadLine();
string s2 = Console.ReadLine();
double num;
int s3;
string s4;
bool isNum1 = double.TryParse(s1, out num);
bool isNum2 = double.TryParse(s2, out num);
if( isNum1==true && isNum2==true)
{
s3 = Convert.ToInt32(s1) + Convert.ToInt32(s2);
Console.WriteLine("Output = {0}", s3);
}
else
{
s4 = s1 + s2;
Console.WriteLine("Output = {0}",s4);
}

How do I use a variable defined in an 'if' statement?

public class Help
{
public static void main (String[] args)
{
if (index = 1)
{
String greeting = "hello";
}
else
{
String greeting = "goodbye";
}
}
callAMethod(greeting);
}
When I define the String within the if statement I get a 'cannot find symbol' error. How can I get around this and still be able to create a string depending upon an above condition?
How about
public static void main (String[] args){
String greeting;
if( index == 1){
greeting = "hello";
}else{
greeting = "goodbye";
}
}
callAMethod(greeting);
}
Declare it outside the scope -
String greeting = "goodbye";
if( index == 1)
{
greeting = "hello";
}
callAMethod(greeting);
Declare the variable outside of the if block.
Right before the if statement, you can say String greeting = "";
Then, inside the if and else blocks, you say greeting = "hello"; and so on.
So you have separated declaring the variable from assigning the value to it.
You can define the greeting variable before the statement:
String greeting;
if (index == 1) {
greeting = "hello";
} else {
greeting = "bye";
}
System.out.println(greeting);