1

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"
2
  • May be using Any can be helpful although not exact? def func1(a: String, s: Any*): Any Commented Jan 23, 2017 at 17:30
  • 1
    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. Commented Jan 23, 2017 at 17:53

4 Answers 4

1

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)
}
Sign up to request clarification or add additional context in comments.

2 Comments

1. It doesn't compile for this case: val Res3 = Hello(5, "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, 5, "Five", "No one") ==> return "five"See the first comment. 2. And throws exception in this case: Hello("No one", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one")
@zhelezoglo see my updated answer, I simplified the code. when it can not find the element I return the last element. Not sure if you want to change it to something else
0

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)

 } 

Comments

0

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.

Comments

0

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.

2 Comments

variable arguments for "param" can be a string or integer in my requirement, so i want to know how can I pass string or integer and also get string or integer as return type, based on input to my program. My "param" list has both string and Integer type. I want to know how can i pass mixed datatypes to "param". val Res2 = Hello("Vik", "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, "No one") ==> return "vinccent" val Res3 = Hello(5, "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, 5, "Five", "No one") ==> return "five"
I've modified the answer to address your comment. I apologize, that my first guess was incorrect. Btw, is it required, that you can pass only Int's or String's and it should be checked at compile time?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.