1
votes

I want to create a method/function in scala which can take variable arguments of type string or int and return the result of type String or Int.

def Hello(name: String, Param: int*/string*): Int/String= {

var index = 0

while(index < Param.length) {

var n = name

var ar = Param(index)

if ( n.equals(ar) ) return Param(index + 1) 

else index = index + 1

}

return Param(index.length -1)

}

If we call the Hello function then it should return the result as given below.

val Res1 = Hello("Jack", "rakesh", 1, "Jack", 2, "No one") 

println(Res1)

=> this should return value 2

val Res2 = Hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one") 

println(Res2)

=> this should return value "No one"
4
May be using Any can be helpful although not exact? def func1(a: String, s: Any*): AnySabuj Hassan
Have you considered Either? def Hello(name: String, Param: Either[Array[Int]/Array[String]]): Either[Int/String]? You could overload it for varargs and have common code in function with Either.Mateusz Kubuszok

4 Answers

1
votes

Using Any should work:

def hello(name: Any, param: Any*): Any= {
    var list = param.dropWhile(_ != name)
    list.drop(1).headOption.orElse(param.lastOption).getOrElse("")
}

Depending on how type safe you want it to be, you can try to use generics or other means to restrict the types used. Or you can just pattern match the response type:

hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one") match {
  case i: Int => println("Got a int:" + i)
  case s: String=> println("Got a string:" + s)
}
0
votes

This will help you

def Hello( name: String,args: Any* ) = {

      val index = args.indexOf(name)
      if(index == -1)
        args(args.length - 1)            
      else
      args(index + 1)

 } 
0
votes

Your whole approach is faulty, but here's how it can be done in a type-safe manner.

def Hello(name: String, param: Either[Int,String]*): Either[Int,String] = {
  param.sliding(2,2)
       .find(_(0).fold(_ => false, _ == name))
       .fold(param.last)(_(1))
}

Usage:

Hello("Jack", Right("rakesh"), Left(1), Right("Jack"), Left(2), Right("No one"))
// res0: Either[Int,String] = Left(2)

Hello("ABC", Right("rakesh"), Left(1), Right("Jack"), Left(2),
             Right("Vik"), Left(3), Right("ram"), Left(4), Right("No one"))
// res1: Either[Int,String] = Right(No one)

But it would be better to rethink it from the ground up.

0
votes

I believe, what you want to achieve, is to get an index of a String element(if start counting from 1) in varargs, or return "No one". No need to pass indices to the method. You can do it like this:

def hello(name: String, params: String*): Any = {
  val idx = params.indexOf(name)
  if (idx != -1) idx + 1 else "No One"
}

Unfortunately both this:

def Hello(name: String, args: Any* ) = {
  val index = args.indexOf(name)
  if(index == -1)
    args(args.length - 1)
  else
    args(index + 1)
}

and this:

def hello(name: String, param: Any*): Any= {
  var index = 0
  while(index < param.length) {
    var n = name
    var ar = param(index)
    if ( n.equals(ar) ) return param(index + 1)
    else index = index + 1
  }
  param(index -1)
}

are broken, as they throw an exception if you try to find the index of "No one", as index + 1 will equal to the size of the array. And it's better to compare things in Scala with == for logical equality.

But it's better not to return Any at all, but return Option[Int]:

def hello(name: String, params: String*): Option[Int] =
  Option(params.indexOf(name)).filter(_ != -1).map(_ + 1)

So then you can use it like this:

val message1 = hello("Jack", "rakesh" ,"Jack").getOrElse("No one")
val message2 = hello("ABC", "rakesh", "Jack", "Vik", "ram").getOrElse("No one")

Answering the comment:

I want to know how can i pass mixed datatypes to "param".

The simplest way is to have them all of type Any

and also get string or integer as return type

The same way, defining return type as Any

The only small issue here, is that there will be no compile time check against other types. E.g. somebody might pass Boolean or any complex object along with String's and Int's to your function. But you can check at runtime against it or play with types to limit them. I don't know your requirement here, maybe it's even advantage for you.

If having Any is fine, then I would solve it like this:

def Hello(name: Any, params: Any*): Any = Option(params)
  .withFilter(_.nonEmpty)
  .map(_.indexOf(name))
  .filter(i => i != -1 && i < params.length - 1)
  .map(i => params(i + 1))
  .getOrElse("No one")

Or, if you can assume, params are never empty and you have to use the last param as the default, instead of just hard coded "No one":

def Hello(name: Any, params: Any*): Any = Option(params)
  .withFilter(_.nonEmpty)
  .map(_.indexOf(name))
  .filter(i => i != -1 && i < params.length - 1)
  .map(i => params(i + 1))
  .getOrElse(params.last)

Notice the check against "No one" attack: i < params.length - 1. Notice that name now is also of type Any.

Now, even if you pass "No one" as a name, the Option will evaluate to None thanking to the filter, and getOrElse will give you the default "No one" instead of an exception.