declare val with a loop in scala - scala

Im learning scala and Im wondering if it's possible to declare a val in the following way :
val aLotOfZero : String = for(i<-0 to 63) {"0"}
instead of
var tmp : String = ""
for(i<-0 to 63)
{
tmp += "0"
}
val aLotOfZero : String = tmp
And if it's possible to replace the "0" by other stuff.
Thanks you

If what you want is to build a String value with n zeroes, you could use a for yielding the character 0 and then making the returning Vectorto a string using mkString as follows:
scala> val aLotOfZeroes: String = (for (i <- 0 to 63) yield "0").mkString
aLotOfZeroes: String = 0000000000000000000000000000000000000000000000000000000000000000
And then, you could generalize it by adding a parameter likewise:
scala> def aLotOfZeroes(n: Int): String = (for (i <- 0 to n) yield "0").mkString
aLotOfZeroes: (n: Int)String
scala> aLotOfZeroes(10)
res2: String = 00000000000
scala> val zeroes: String = aLotOfZeroes(10)
zeroes: String = 00000000000
scala> zeroes
res3: String = 00000000000
Also, from #dividebyzero's comment, you can use *:
scala> "0" * 64
res13: String = 0000000000000000000000000000000000000000000000000000000000000000
And define:
scala> def aLotOfZeroes: Int => String = "0" * _
aLotOfZeroes: Int => String
scala> aLotOfZeroes(10)
res16: String = 0000000000

Related

How to define variables by list droping extra parts?

This is working fine,
val Array(a,b) = "Hello,Bye".split(',')
But it is an error because extra-information is not ignored:
val Array(a,b) = "Hello,Bye,etc".split(',')
// scala.MatchError: ...
how to ignore extra-information?
Same error in the case of less items:
val Array(a,b) = "Hello".split(',')
IMPORTANT: no elegant way like the Javascript Destructuring assignment?
Add a placeholder using underscore:
val Array(a,b, _) = "Hello,Bye,etc".split(',')
EDIT: Using match-case syntax is generally more preferred and more flexible (and you can catch all possible outcome):
val s = "Hello,Bye,etc"
s.split(',') match {
case Array(a) => //...
case Array(a, b) => //...
case Array(a, b, rest#_*) => //...
case _ => //Catch all case to avoid MatchError
}
#_ will cover both instances.
val Array(a,b,x#_*) = "Hello,Bye,etc".split(',')
//a: String = Hello
//b: String = Bye
//x: Seq[String] = ArraySeq(etc)
val Array(c,d,z#_*) = "Hello,Bye".split(',')
//c: String = Hello
//d: String = Bye
//z: Seq[String] = ArraySeq()
From your comments it looks like you want to default to "", an empty String. I found a way to do it with Stream, which has been deprecated in Scala 2.13, but so far it is the cleanest solution I've found.
val Stream(a,b,c,d,_*) = "one,two,etc".split(",").toStream ++ Stream.continually("")
//a: String = one
//b: String = two
//c: String = etc
//d: String = ""
I would consider making the result values of type Option[String] by lift-ing the split Array[String] (viewed as a partial function) into an Int => Option[String] function:
val opts = "Hello".split(",").lift
// opts: Int => Option[String] = <function1>
opts(0)
// res1: Option[String] = Some(Hello)
opts(1)
// res2: Option[String] = None
Or, if String values are preferred with None translated to "":
val strs = "Hello,world".split(",").lift.andThen(_.getOrElse(""))
// strs: Int => String = scala.Function1$$Lambda$...
strs(0)
// res3: String = Hello
strs(1)
// res4: String = "world"
strs(2)
// res5: String = ""
Note that with this approach, you can take as many opts(i) or strs(i), i = 0, 1, 2, ..., as wanted.
You can do this by converting to List first:
val a :: b :: _ = "Hello,Bye,etc".split(',').toList

Scala List[Any] has a element as function. How to get return value?

I'm a novice in Scala and this moment I'm learning about it... I'm testing code and I have a list[Any] like this:
var list: List[Any] = List(
"a string",
732, // an integer
'c', // a character
true, // a boolean value
(x: String) => "String return " + x)
I want to get return value of index 4, but I obtain an error. I don't know how to get the return value.. that is my doubt.
var test = list(4);
test("hello") // Error
You need to cast the function from Any to String => String before invoking it:
var test = list(4)
test.asInstanceOf[String => String]("hello")
// res21: String = String return hello
Or:
val test = list(4).asInstanceOf[String => String]
// test: String => String = <function1>
test("hello")
// res23: String = String return hello
You can call it like so:
scala> val f = (x: String) => "String return " + x
f: String => String = <function1>
scala> val y = f.asInstanceOf[ String => String ].apply("x")
y: String = String return x
scala> val y = f.asInstanceOf[ String => String ]("x")
y: String = String return x

scala string interpolation with a variable length

I use scala f string interpolator as follows:
def format(id: Int) = f"A$id%04d"
format(21) // A0021
However, I would like to be able to define a length once and for all (before fixed to 4), and get a function that it is going to format the string with that length.
So, instead of having
def format(length: Int, id: Int) = ???
f(5, 21) // A00021
I would like to have this:
def format(length: Int)(id: Int) = ???
val f = format(5)
f(21) // A00021
How can I implement this using scala f interpolator or other?
Update
I was not looking for such a solution involving the compiler at runtime, but I appreciate som-snytt's answer. Here there is a working solution based on his answer:
import scala.tools.reflect._,scala.reflect.runtime._,universe._
def defFormat(length: Int): Int => String = {
val code = raw"""(i: Int) => f"A$$i%0${length}d""""
tb.eval(tb.parse(code)).asInstanceOf[Int => String]
}
val format = defFormat(length = 5)
format(21)
scala> def format(n: Int)(i: Int) =
| f"A%%0${n}d" format i
format: (n: Int)(i: Int)String
scala> format(5) _
res0: Int => String = <function1>
scala> .apply(21)
res1: String = A00021
Edit:
scala> import scala.tools.reflect._,scala.reflect.runtime._,universe._
import scala.tools.reflect._
import scala.reflect.runtime._
import universe._
scala> val tb = currentMirror.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl#2d10e0b1
scala> def f(n: Int)(i: Int): String = {
| val code = raw"""f"A$${$i}%0${n}d""""
| tb.eval(tb.parse(code)).asInstanceOf[String]
| }
f: (n: Int)(i: Int)String
scala> val g = f(5) _
g: Int => String = <function1>
scala> g(21)
res9: String = A00021
That doesn't actually help much. You really want to
scala> tb.typecheck(tb.parse(code))
scala.tools.reflect.ToolBoxError: reflective typecheck has failed: illegal conversion character 'k'
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$typecheck$1.apply(ToolBoxFactory.scala:178)
which throws if the format is bad.
scala> val code = raw"""(i: Int) => f"A$${i}%k0${10}d""""
code: String = (i: Int) => f"A${i}%k010d"
scala> tb.typecheck(tb.parse(code))
scala.tools.reflect.ToolBoxError: reflective typecheck has failed: illegal conversion character 'k'
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$typecheck$1.apply(ToolBoxFactory.scala:178)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$typecheck$1.apply(ToolBoxFactory.scala:170)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$11.apply(ToolBoxFactory.scala:148)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$11.apply(ToolBoxFactory.scala:148)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$9.apply(ToolBoxFactory.scala:138)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$9.apply(ToolBoxFactory.scala:138)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$withContext$1$1.apply(ToolBoxFactory.scala:139)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$withContext$1$1.apply(ToolBoxFactory.scala:139)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$7.apply(ToolBoxFactory.scala:137)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1$$anonfun$7.apply(ToolBoxFactory.scala:137)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1.apply(ToolBoxFactory.scala:148)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal$$anonfun$transformDuringTyper$1.apply(ToolBoxFactory.scala:121)
at scala.reflect.internal.Trees$class.wrappingIntoTerm(Trees.scala:1716)
at scala.reflect.internal.SymbolTable.wrappingIntoTerm(SymbolTable.scala:16)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.withWrapping$1(ToolBoxFactory.scala:120)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.transformDuringTyper(ToolBoxFactory.scala:121)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.typecheck(ToolBoxFactory.scala:169)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$typecheck$2.apply(ToolBoxFactory.scala:375)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$typecheck$2.apply(ToolBoxFactory.scala:367)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:355)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:355)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.typecheck(ToolBoxFactory.scala:367)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.typecheck(ToolBoxFactory.scala:27)
... 32 elided
scala> val code = raw"""(i: Int) => f"A$${i}%0${10}d""""
code: String = (i: Int) => f"A${i}%010d"
scala> tb.typecheck(tb.parse(code))
res19: tb.u.Tree =
((i: Int) => ({
val arg$macro$9: Int = i;
new scala.collection.immutable.StringOps("A%010d").format(arg$macro$9)
}: String))
You can't do it using f because its whole point is to make sure it can check the format string for type errors, so the format string has to be static. f could support this scenario explicitly, but it doesn't.
You could make format a macro, but this seems like an overkill. Not to mention that it would have to be defined in a separate module, which looks very inconvenient for this scenario.

Hex String to Int,Short and Long in Scala

Just can't find a way to transform an Hex String to a number (Int, Long, Short) in Scala.
Is there something like "A".toInt(base)?
You can use the Java libs:
val number = Integer.parseInt("FFFF", 16)
> number: Int = 65535
Or if you are feeling sparky :-):
implicit def hex2int (hex: String): Int = Integer.parseInt(hex, 16)
val number: Int = "CAFE" // <- behold the magic
number: Int = 51966
Also, if you aren't specifically trying to parse a String parameter into hex, note that Scala directly supports hexadecimal Integer literals. In this case:
val x = 0xCAFE
> x: Int = 51966
Isn't Scala wonderful? :-)
7zark7 answer is correct, but I want to make some additions.
Implicit from String to Int can be dangerous. Instead you can use implicit conversion to wrapper and call parsing explicitly:
class HexString(val s: String) {
def hex = Integer.parseInt(s, 16)
}
implicit def str2hex(str: String): HexString = new HexString(str)
val num: Int = "CAFE".hex
What about a one-liner?
def hexToInt(s: String): Int = {
s.toList.map("0123456789abcdef".indexOf(_)).reduceLeft(_ * 16 + _)
}
scala> hexToInt("cafe")
res0: Int = 51966
And to answer your second item:
Is there something like "A".toInt(base)?
Yes, still as a one-liner:
def baseToInt(s: String, base: String): Int = {
s.toList.map(base.indexOf(_)).reduceLeft(_ * base.length + _)
}
scala> baseToInt("1100", "01")
res1: Int = 12
Anyone wanting to convert a UUID from hex to a decimal number can borrow from Benoit's answer and use BigDecimal for the job:
scala> "03cedf84011dd11e38ff0800200c9a66".toList.map(
| "0123456789abcdef".indexOf(_)).map(
| BigInt(_)).reduceLeft( _ * 16 + _)
res0: scala.math.BigInt = 5061830576017519706280227473241971302
Or more generally:
def hex2dec(hex: String): BigInt = {
hex.toLowerCase().toList.map(
"0123456789abcdef".indexOf(_)).map(
BigInt(_)).reduceLeft( _ * 16 + _)
}
def uuid2dec(uuid: UUID): BigInt = {
hex2dec(uuid.toString.replace("-",""))
}
Then:
scala> import java.util.UUID
scala> val id = UUID.fromString("3CEDF84-011D-D11E-38FF-D0800200C9A66")
id: java.util.UUID = 03cedf84-011d-d11e-38ff-0800200c9a66
scala> uuid2dec(id)
res2: BigInt = 5061830576017519706280227473241971302
One practical application for this is encoding the UUID in a barcode, where Code128 produces a shorter barcode for all digits than it does with alphanumeric strings. See notes about subtype "128A" on http://en.wikipedia.org/wiki/Code128#Subtypes.
For Long and Short, it is also possible to use the Java methods directly like
Long2long(java.lang.Long.valueOf(hexString, 16))
where Long2long can be even be omitted in some cases.

Scala reverse string

I'm a newbie to scala, I'm just writing a simple function to reverse a given string:
def reverse(s: String) : String
for(i <- s.length - 1 to 0) yield s(i)
the yield gives back a scala.collection.immutable.IndexedSeq[Char], and can not convert it to a String. (or is it something else?)
how do i write this function ?
Note that there is already defined function:
scala> val x = "scala is awesome"
x: java.lang.String = scala is awesome
scala> x.reverse
res1: String = emosewa si alacs
But if you want to do that by yourself:
def reverse(s: String) : String =
(for(i <- s.length - 1 to 0 by -1) yield s(i)).mkString
or (sometimes it is better to use until, but probably not in that case)
def reverse(s: String) : String =
(for(i <- s.length until 0 by -1) yield s(i-1)).mkString
Also, note that if you use reversed counting (from bigger one to less one value) you should specify negative step or you will get an empty set:
scala> for(i <- x.length until 0) yield i
res2: scala.collection.immutable.IndexedSeq[Int] = Vector()
scala> for(i <- x.length until 0 by -1) yield i
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
Here's a short version
def reverse(s: String) = ("" /: s)((a, x) => x + a)
edit
: or even shorter, we have the fantastically cryptic
def reverse(s: String) = ("" /: s)(_.+:(_))
but I wouldn't really recommend this...
You could also write this using a recursive approach (throwing this one in just for fun)
def reverse(s: String): String = {
if (s.isEmpty) ""
else reverse(s.tail) + s.head
}
As indicated by om-nom-nom, pay attention to the by -1 (otherwise you are not really iterating and your result will be empty). The other trick you can use is collection.breakOut.
It can also be provided to the for comprehension like this:
def reverse(s: String): String =
(for(i <- s.length - 1 to 0 by -1) yield s(i))(collection.breakOut)
reverse("foo")
// String = oof
The benefit of using breakOut is that it will avoid creating a intermediate structure as in the mkString solution.
note: breakOut is leveraging CanBuildFrom and builders which are part of the foundation of the redesigned collection library introduced in scala 2.8.0
All the above answers are correct and here's my take:
scala> val reverseString = (str: String) => str.foldLeft("")((accumulator, nextChar) => nextChar + accumulator)
reverseString: String => java.lang.String = <function1>
scala> reverseString.apply("qwerty")
res0: java.lang.String = ytrewq
def rev(s: String): String = {
val str = s.toList
def f(s: List[Char], acc: List[Char]): List[Char] = s match {
case Nil => acc
case x :: xs => f(xs, x :: acc)
}
f(str, Nil).mkString
}
Here is my version of reversing a string.
scala> val sentence = "apple"
sentence: String = apple
scala> sentence.map(x => x.toString).reduce((x, y) => (y + x))
res9: String = elppa