I have a list of this object :
case class Alloc(
segId: String,
paxId: String,
cos: String,
fare: String,
type: String,
promo: Boolean,
cosLev: String)
, I currently have a list of 10, all attributes have a value except paxId, all object have "".
Now I would like to increment each paxId, I mean like having paxId=1 for the first Alloc, 2 for the second, ... and 10 for the tenth.
I have tried this :
val allocWithPaxIds: List[Allocation] = for (id <- 1 to 10) {
allocs.map(alloc=>Alloc.apply(alloc.segId, id, alloc.cos, alloc.fare, alloc.type, false, alloc.cosLev))
}
allocs containing the alloc without paxIds
I am beginner in scala and I am lost, hope you'll be able to help me.
Thanks in advance
You can use zipWithIndex and then use copy to modify just one field of each object
list.zipWithIndex.map{
case (v, idx) => v.copy(paxId = idx.toString)
}
So, just to clarify what's happening with your implementation.
First, you might need to understand how for comprehension works.
https://docs.scala-lang.org/tutorials/FAQ/yield.html
Scala’s “for comprehensions” are syntactic sugar for composition of
multiple operations with foreach, map, flatMap, filter or withFilter.
And the fact that your code doesn't yield anything will be translated into forEach method which has return type Unit that means you will never get list out of it.
I will try to modify your code step by step.
for (id <- 1 to 10) {
allocs.map(alloc => Alloc.apply(alloc.segId, id, alloc.cos, alloc.fare, alloc.type, false, alloc.cosLev))
}
You don't need to explicitly call apply. The apply method is just a syntactic sugar that if you implement it, you can just use it like a function. In this case, case class has done the job for you.
(more on this topic here: https://twitter.github.io/scala_school/basics2.html#apply)
for (id <- 1 to 10) {
allocs.map(alloc => Alloc(alloc.segId, id, alloc.cos, alloc.fare, alloc.type, false, alloc.cosLev))
}
And you don't need for-comprehension here, also since the things that will be updated are just id and promo so you can use copy provided by case class.
allocs.map(alloc => alloc.copy(id = id, promo = false))
of just
allocs.map(_.copy(id = id, promo = false))
You want to fill up the id from 1 to 10 so you can just zip them together which will return List[(Int, Alloc)] and map it using partial function to do pattern matching and destructure the tuple.
(more on partial function: https://twitter.github.io/scala_school/pattern-matching-and-functional-composition.html#PartialFunction)
allocs
.zip(1 to 10)
.map {
case (alloc, id) => alloc.copy(id = id.toString, promo = false)
}
And, yes, if you like you can use zipWithIndex as Mikel suggest.
The last thing I want to point out is, I see type as a property of Alloc which has type String.
This might not be related to the question but you can leverage the power of Scala type system more to ensure the correctness of your program. Since less possible value means more predictability. So you might consider using sum type (or union type) instead.
(more on sum type: http://tpolecat.github.io/presentations/algebraic_types.html#11)
Related
With a background from object-oriented programming I am not able to understand how to make immutable lists in Scala.
Example; I want to make a list of 10 random people:
object MyApplication extends App {
val numberOfPersons = 10 : Int
val listOfPersons = makeListOfPersons(numberOfPersons) : List[Person]
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
// TODO: return a immutable list of 10 persons
}
}
class Person {
/**
Generic content,
like age and name.
* */
}
What is the "correct" way of making an immutable list in Scala?
If you know what collection type you want, you may be able to use the tabulate method on that type:
List.tabulate(10)(makePerson)
In this case makePerson is a function that takes an Int and returns the Person object for that Int.
If you don't care about the collection type, you can call map on the range 1 to 10 like this:
(1 to 10).map(makePerson)
If you don't need to use the Int parameter, you can do this:
List.tabulate(10)(_ => makeRandomPerson())
In this particular case,
List.fill(numberOfPersons){ codeThatCreatesASinglePerson }
seems most appropriate.
In most other cases: Nil creates an empty list, x :: y prepends an element x to list y.
If you want to append to list, instead of prepending to it, then you can take a collection.mutable.ListBuffer, append to it all the elements that you want to have in the list, and then call toList when you're done... or just use the built-in factory methods that do exactly that.
As the default List in Scala is immutable, the right way to add an element is to return a new list with the new element plus the older elements.
As a matter of fact, List has two methods, among others:
+:
++
The first one takes an element, add it as the first element and the rest of the list as it's tail and then returns the resulting list.
The other one takes another "collection" as parameter and adds it to the first list at the start.
List has another methods for adding the new element as the last one.
In Scala, these operations are permitted but take into consideration that always a new instance will be retrieved with the requested modifications as all objects are immutable by default.
As for your code goes, you could try with something like this:
object MyApplication extends App {
val numberOfPersons: Int = 10
val listOfPersons: List[Person] = makeListOfPersons(numberOfPersons)
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
(1 to numberOfPersons).foldLeft(List.empty[Person]){ (accum, elem) =>
new Person() :: accum
}
}
}
(1 to numberOfPersons) creates a range, which could be seen as a List of ints, which will be traversed by foldLeft. This method will iterate through that list, and receives a seed, in this case an empty list of Person. Then, for every element in the int's list, a new Person is created and add to the list, returned as is the last expression and used the accumulator for the next iteration. Finally, a list of ten instances of Person is retrieved.
There are 5 ways to create List in scala:
Lisp style:
val list = 1::2::3::Nil
this style can also be thought of as a Haskell or functional programming (FP) style.
Java Style:
val list = List(1,2,3)
Scala List with range method
List.range(1, 10)
Create scala List with fill
List.fill(3)(5)
Scala List with tabulate
List.tabulate(5)(n => n * n)
element of the list are created according to the function we supply.
for more info please read this :
Preferred way to create a Scala list
I am trying to build a wrapper around data saved in a redis database.
What I want to do is access it as normal as possible as if I have a scala value of some type.
It works, except for comparing it to anything (with == or similar).
So I want to be able to compare it to objects of the inner type.
Best I'll give example code first. This is a rough abstraction of my wrapper:
case class RedisObjectValue[T](name: String, default: T) {
def :=(value: T): Boolean = {
redisMagic.set(name, value)
}
def get: T = {
redisMagic.get[T](name).getOrElse(default)
}
override def equals(o: Any) = o match {
case ov: RedisObjectValue[T] =>
if (this.hashCode() == ov.hashCode()) true // Same reference
else this.get == ov.get
case v =>
// If we don't compare to another RedisObjectValue, let the equals method of data type handle it
this.get.equals(v)
}
}
I have an implicit conversion set up in the companion object so that I can use the wrapper wherever I would use the base type.
object RedisObjectValue {
implicit def objectValueToValue[T](ov: RedisObjectValue[T]): T = {
ov.get
}
}
So, as I said, everything works.
Except the comparing stuff. For that, let's say I have a class Player two values, userId and name.
class Player {
val userId = RedisObjectValue("userId", 0)
val name = RedisObjectValue("player", "Unknown")
}
And now I have a list of players and want to filter to get all players with name "Unknown".
list.filter(_.name == "Unknown")
Which does not work. If I extend the filter filter call and write a function, it tells me in IntelliJ "Comparing unrelated types".
And yeah, I understand what it is telling me, but I want to solve that. I mean I can easily compare Long to Int and similar stuff, so there must be a way to make them comparable, right?
In the code above I have even written the equals function which uses the comparison to the inner type, but it seems like it is not used.
Of course, I can always call .get on the values, like players.filter(_.name.get == "Unknown"), but that's a bit dirty and I would love to avoid that.
EDIT: Found the real problem after some analysis
Old text still above for reading, I will explain the problem here now.
I have a snippet which shows what is not working: https://ideone.com/AmQrkH
The Problem: The RedisObjectValue is defined as Long. When I am comparing it now with
players.filter(_.userId == 2)
for example, it doesn't give any results, even if there are players with userId 2, or to be more exact: 2l.
For direct Long it's not a problem.
players.filter(_._id == 2)
is working.
So is there any fix for that, so that comparable instances of classes to T can also be compared to RedisObjectValue[T], and not just T itself?
Replace this.get.equals(v) with get == v. (Removing this is unrelated, just a good idea in general, the main thing is to use == instead of equals).
Consider this:
scala> 2 equals 2L
res79: Boolean = false
scala> 2 == 2L
res80: Boolean = true
I am a bit new to Scala, so apologies if this is something a bit trivial.
I have a list of items which I want to iterate through. I to execute a check on each of the items and if just one of them fails I want the whole function to return false. So you can see this as an AND condition. I want it to be evaluated lazily, i.e. the moment I encounter the first false return false.
I am used to the for - yield syntax which filters items generated through some generator (list of items, sequence etc.). In my case however I just want to break out and return false without executing the rest of the loop. In normal Java one would just do a return false; within the loop.
In an inefficient way (i.e. not stopping when I encounter the first false item), I could do it:
(for {
item <- items
if !satisfiesCondition(item)
} yield item).isEmpty
Which is essentially saying that if no items make it through the filter all of them satisfy the condition. But this seems a bit convoluted and inefficient (consider you have 1 million items and the first one already did not satisfy the condition).
What is the best and most elegant way to do this in Scala?
Stopping early at the first false for a condition is done using forall in Scala. (A related question)
Your solution rewritten:
items.forall(satisfiesCondition)
To demonstrate short-circuiting:
List(1,2,3,4,5,6).forall { x => println(x); x < 3 }
1
2
3
res1: Boolean = false
The opposite of forall is exists which stops as soon as a condition is met:
List(1,2,3,4,5,6).exists{ x => println(x); x > 3 }
1
2
3
4
res2: Boolean = true
Scala's for comprehensions are not general iterations. That means they cannot produce every possible result that one can produce out of an iteration, as, for example, the very thing you want to do.
There are three things that a Scala for comprehension can do, when you are returning a value (that is, using yield). In the most basic case, it can do this:
Given an object of type M[A], and a function A => B (that is, which returns an object of type B when given an object of type A), return an object of type M[B];
For example, given a sequence of characters, Seq[Char], get UTF-16 integer for that character:
val codes = for (char <- "A String") yield char.toInt
The expression char.toInt converts a Char into an Int, so the String -- which is implicitly converted into a Seq[Char] in Scala --, becomes a Seq[Int] (actually, an IndexedSeq[Int], through some Scala collection magic).
The second thing it can do is this:
Given objects of type M[A], M[B], M[C], etc, and a function of A, B, C, etc into D, return an object of type M[D];
You can think of this as a generalization of the previous transformation, though not everything that could support the previous transformation can necessarily support this transformation. For example, we could produce coordinates for all coordinates of a battleship game like this:
val coords = for {
column <- 'A' to 'L'
row <- 1 to 10
} yield s"$column$row"
In this case, we have objects of the types Seq[Char] and Seq[Int], and a function (Char, Int) => String, so we get back a Seq[String].
The third, and final, thing a for comprehension can do is this:
Given an object of type M[A], such that the type M[T] has a zero value for any type T, a function A => B, and a condition A => Boolean, return either the zero or an object of type M[B], depending on the condition;
This one is harder to understand, though it may look simple at first. Let's look at something that looks simple first, say, finding all vowels in a sequence of characters:
def vowels(s: String) = for {
letter <- s
if Set('a', 'e', 'i', 'o', 'u') contains letter.toLower
} yield letter.toLower
val aStringVowels = vowels("A String")
It looks simple: we have a condition, we have a function Char => Char, and we get a result, and there doesn't seem to be any need for a "zero" of any kind. In this case, the zero would be the empty sequence, but it hardly seems worth mentioning it.
To explain it better, I'll switch from Seq to Option. An Option[A] has two sub-types: Some[A] and None. The zero, evidently, is the None. It is used when you need to represent the possible absence of a value, or the value itself.
Now, let's say we have a web server where users who are logged in and are administrators get extra javascript on their web pages for administration tasks (like wordpress does). First, we need to get the user, if there's a user logged in, let's say this is done by this method:
def getUser(req: HttpRequest): Option[User]
If the user is not logged in, we get None, otherwise we get Some(user), where user is the data structure with information about the user that made the request. We can then model that operation like this:
def adminJs(req; HttpRequest): Option[String] = for {
user <- getUser(req)
if user.isAdmin
} yield adminScriptForUser(user)
Here it is easier to see the point of the zero. When the condition is false, adminScriptForUser(user) cannot be executed, so the for comprehension needs something to return instead, and that something is the "zero": None.
In technical terms, Scala's for comprehensions provides syntactic sugars for operations on monads, with an extra operation for monads with zero (see list comprehensions in the same article).
What you actually want to accomplish is called a catamorphism, usually represented as a fold method, which can be thought of as a function of M[A] => B. You can write it with fold, foldLeft or foldRight in a sequence, but none of them would actually short-circuit the iteration.
Short-circuiting arises naturally out of non-strict evaluation, which is the default in Haskell, in which most of these papers are written. Scala, as most other languages, is by default strict.
There are three solutions to your problem:
Use the special methods forall or exists, which target your precise use case, though they don't solve the generic problem;
Use a non-strict collection; there's Scala's Stream, but it has problems that prevents its effective use. The Scalaz library can help you there;
Use an early return, which is how Scala library solves this problem in the general case (in specific cases, it uses better optimizations).
As an example of the third option, you could write this:
def hasEven(xs: List[Int]): Boolean = {
for (x <- xs) if (x % 2 == 0) return true
false
}
Note as well that this is called a "for loop", not a "for comprehension", because it doesn't return a value (well, it returns Unit), since it doesn't have the yield keyword.
You can read more about real generic iteration in the article The Essence of The Iterator Pattern, which is a Scala experiment with the concepts described in the paper by the same name.
forall is definitely the best choice for the specific scenario but for illustration here's good old recursion:
#tailrec def hasEven(xs: List[Int]): Boolean = xs match {
case head :: tail if head % 2 == 0 => true
case Nil => false
case _ => hasEven(xs.tail)
}
I tend to use recursion a lot for loops w/short circuit use cases that don't involve collections.
UPDATE:
DO NOT USE THE CODE IN MY ANSWER BELOW!
Shortly after I posted the answer below (after misinterpreting the original poster's question), I have discovered a way superior generic answer (to the listing of requirements below) here: https://stackoverflow.com/a/60177908/501113
It appears you have several requirements:
Iterate through a (possibly large) list of items doing some (possibly expensive) work
The work done to an item could return an error
At the first item that returns an error, short circuit the iteration, throw away the work already done, and return the item's error
A for comprehension isn't designed for this (as is detailed in the other answers).
And I was unable to find another Scala collections pre-built iterator that provided the requirements above.
While the code below is based on a contrived example (transforming a String of digits into a BigInt), it is the general pattern I prefer to use; i.e. process a collection and transform it into something else.
def getDigits(shouldOnlyBeDigits: String): Either[IllegalArgumentException, BigInt] = {
#scala.annotation.tailrec
def recursive(
charactersRemaining: String = shouldOnlyBeDigits
, accumulator: List[Int] = Nil
): Either[IllegalArgumentException, List[Int]] =
if (charactersRemaining.isEmpty)
Right(accumulator) //All work completed without error
else {
val item = charactersRemaining.head
val isSuccess =
item.isDigit //Work the item
if (isSuccess)
//This item's work completed without error, so keep iterating
recursive(charactersRemaining.tail, (item - 48) :: accumulator)
else {
//This item hit an error, so short circuit
Left(new IllegalArgumentException(s"item [$item] is not a digit"))
}
}
recursive().map(digits => BigInt(digits.reverse.mkString))
}
When it is called as getDigits("1234") in a REPL (or Scala Worksheet), it returns:
val res0: Either[IllegalArgumentException,BigInt] = Right(1234)
And when called as getDigits("12A34") in a REPL (or Scala Worksheet), it returns:
val res1: Either[IllegalArgumentException,BigInt] = Left(java.lang.IllegalArgumentException: item [A] is not digit)
You can play with this in Scastie here:
https://scastie.scala-lang.org/7ddVynRITIOqUflQybfXUA
I'd like to have some basic knowledge of how deeply my function call is nested. Consider the following:
scala> def decorate(f: => Unit) : Unit = { println("I am decorated") ; f }
decorate: (f: => Unit)Unit
scala> decorate { println("foo") }
I am decorated
foo
scala> decorate { decorate { println("foo") } }
I am decorated
I am decorated
foo
For the last call, I'd like to be able to get the following:
I am decorated 2x
I am decorated 1x
foo
The idea is that the decorate function knows how deeply its nested. Ideas?
Update: As Nikita had thought, my example doesn't represent what I'm really after. The goal is not to produce the strings so much as to be able to pass some state through a series of calls to the same nested function. I think Régis Jean-Gilles is pointing me in the right direction.
You can use the dynamic scope pattern. More prosaically this means using a thread local variable (scala's DynamicVariable is done just for that) to store the current nesting level. See my answer to this other question for a partical example of this pattern: How to define a function that takes a function literal (with an implicit parameter) as an argument?
This is suitable only if you want to know the nesting level for a very specific method though. If you want a generic mecanism that works for any method then this won't work (as you'd need a distinct variable for each method). In this case the only alternative I can think of is to inspect the stack, but not only is it not very reliable, it is also extremely slow.
UPDATE: actually, there is a way to apply the dynamic scope pattern in a generic way (for any possible method). The important part is to be able to implicitly get a unique id for each method. from there, it is just a matter of using this id as a key to associate a DynamicVariable to the method:
import scala.util.DynamicVariable
object FunctionNestingHelper {
private type FunctionId = Class[_]
private def getFunctionId( f: Function1[_,_] ): FunctionId = {
f.getClass // That's it! Beware, implementation dependant.
}
private val currentNestings = new DynamicVariable( Map.empty[FunctionId, Int] )
def withFunctionNesting[T]( body: Int => T ): T = {
val id = getFunctionId( body )
val oldNestings = currentNestings.value
val oldNesting = oldNestings.getOrElse( id, 0 )
val newNesting = oldNesting + 1
currentNestings.withValue( oldNestings + ( id -> newNesting) ) {
body( newNesting )
}
}
}
Usage:
import FunctionNestingHelper._
def decorate(f: => Unit) = withFunctionNesting { nesting: Int =>
println("I am decorated " + nesting + "x") ; f
}
To get a unique id for the method, I actually get an id for a the closure passed to withFunctionNesting (which you must call in the method where you need to retrieve the current nesting). And that's where I err on the implementation dependant side: the id is just the class of the function instance. This does work as expected as of now (because every unary function literal is implemented as exactly one class implementing Function1 so the class acts as a unique id), but the reality is that it might well break (although unlikely) in a future version of scala. So use it at your own risk.
Finally, I suggest that you first evaluate seriously if Nikita Volkov's suggestion of going more functional would not be a better solution overall.
You could return a number from the function and count how many levels you are in on the way back up the stack. But there is no easy way to count on the way down like you have given example output for.
Since your question is tagged with "functional programming" following are functional solutions. Sure the program logic changes completely, but then your example code was imperative.
The basic principle of functional programming is that there is no state. What you're used to have as a shared state in imperative programming with all the headache involved (multithreading issues and etc.) - it is all achieved by passing immutable data as arguments in functional programming.
So, assuming the "state" data you wanted to pass was the current cycle number, here's how you'd implement a function using recursion:
def decorated ( a : String, cycle : Int ) : String
= if( cycle <= 0 ) a
else "I am decorated " + cycle + "x\n" + decorated(a, cycle - 1)
println(decorated("foo", 3))
Alternatively you could make your worker function non-recursive and "fold" it:
def decorated ( a : String, times : Int )
= "I am decorated " + times + "x\n" + a
println( (1 to 3).foldLeft("foo")(decorated) )
Both codes above will produce the following output:
I am decorated 3x
I am decorated 2x
I am decorated 1x
foo
I came across this sentence in Scala in explaining its functional behavior.
operation of a program should map input of values to output values rather than change data in place
Could somebody explain it with a good example?
Edit: Please explain or give example for the above sentence in its context, please do not make it complicate to get more confusion
The most obvious pattern that this is referring to is the difference between how you would write code which uses collections in Java when compared with Scala. If you were writing scala but in the idiom of Java, then you would be working with collections by mutating data in place. The idiomatic scala code to do the same would favour the mapping of input values to output values.
Let's have a look at a few things you might want to do to a collection:
Filtering
In Java, if I have a List<Trade> and I am only interested in those trades executed with Deutsche Bank, I might do something like:
for (Iterator<Trade> it = trades.iterator(); it.hasNext();) {
Trade t = it.next();
if (t.getCounterparty() != DEUTSCHE_BANK) it.remove(); // MUTATION
}
Following this loop, my trades collection only contains the relevant trades. But, I have achieved this using mutation - a careless programmer could easily have missed that trades was an input parameter, an instance variable, or is used elsewhere in the method. As such, it is quite possible their code is now broken. Furthermore, such code is extremely brittle for refactoring for this same reason; a programmer wishing to refactor a piece of code must be very careful to not let mutated collections escape the scope in which they are intended to be used and, vice-versa, that they don't accidentally use an un-mutated collection where they should have used a mutated one.
Compare with Scala:
val db = trades filter (_.counterparty == DeutscheBank) //MAPPING INPUT TO OUTPUT
This creates a new collection! It doesn't affect anyone who is looking at trades and is inherently safer.
Mapping
Suppose I have a List<Trade> and I want to get a Set<Stock> for the unique stocks which I have been trading. Again, the idiom in Java is to create a collection and mutate it.
Set<Stock> stocks = new HashSet<Stock>();
for (Trade t : trades) stocks.add(t.getStock()); //MUTATION
Using scala the correct thing to do is to map the input collection and then convert to a set:
val stocks = (trades map (_.stock)).toSet //MAPPING INPUT TO OUTPUT
Or, if we are concerned about performance:
(trades.view map (_.stock)).toSet
(trades.iterator map (_.stock)).toSet
What are the advantages here? Well:
My code can never observe a partially-constructed result
The application of a function A => B to a Coll[A] to get a Coll[B] is clearer.
Accumulating
Again, in Java the idiom has to be mutation. Suppose we are trying to sum the decimal quantities of the trades we have done:
BigDecimal sum = BigDecimal.ZERO
for (Trade t : trades) {
sum.add(t.getQuantity()); //MUTATION
}
Again, we must be very careful not to accidentally observe a partially-constructed result! In scala, we can do this in a single expression:
val sum = (0 /: trades)(_ + _.quantity) //MAPPING INTO TO OUTPUT
Or the various other forms:
(trades.foldLeft(0)(_ + _.quantity)
(trades.iterator map (_.quantity)).sum
(trades.view map (_.quantity)).sum
Oh, by the way, there is a bug in the Java implementation! Did you spot it?
I'd say it's the difference between:
var counter = 0
def updateCounter(toAdd: Int): Unit = {
counter += toAdd
}
updateCounter(8)
println(counter)
and:
val originalValue = 0
def addToValue(value: Int, toAdd: Int): Int = value + toAdd
val firstNewResult = addToValue(originalValue, 8)
println(firstNewResult)
This is a gross over simplification but fuller examples are things like using a foldLeft to build up a result rather than doing the hard work yourself: foldLeft example
What it means is that if you write pure functions like this you always get the same output from the same input, and there are no side effects, which makes it easier to reason about your programs and ensure that they are correct.
so for example the function:
def times2(x:Int) = x*2
is pure, while
def add5ToList(xs: MutableList[Int]) {
xs += 5
}
is impure because it edits data in place as a side effect. This is a problem because that same list could be in use elsewhere in the the program and now we can't guarantee the behaviour because it has changed.
A pure version would use immutable lists and return a new list
def add5ToList(xs: List[Int]) = {
5::xs
}
There are plenty examples with collections, which are easy to come by but might give the wrong impression. This concept works at all levels of the language (it doesn't at the VM level, however). One example is the case classes. Consider these two alternatives:
// Java-style
class Person(initialName: String, initialAge: Int) {
def this(initialName: String) = this(initialName, 0)
private var name = initialName
private var age = initialAge
def getName = name
def getAge = age
def setName(newName: String) { name = newName }
def setAge(newAge: Int) { age = newAge }
}
val employee = new Person("John")
employee.setAge(40) // we changed the object
// Scala-style
case class Person(name: String, age: Int) {
def this(name: String) = this(name, 0)
}
val employee = new Person("John")
val employeeWithAge = employee.copy(age = 40) // employee still exists!
This concept is applied on the construction of the immutable collection themselves: a List never changes. Instead, new List objects are created when necessary. Use of persistent data structures reduce the copying that would happen on a mutable data structure.