Immutable Lists in Scala - list

I am just trying to figure out how immutable things like a List are working, and how I can add things to it?
I am very sorry for asking such dumb questions, but why is here my list always empty when printing it out?
var end = false
val list = List()
while (!end) {
val input = scala.io.StdIn.readLine("input:")
if (input == "stop" ) end = true
else input :: list
}
println(list)
}
Sorry for my inconvenience and this rather stupid question!

I am just trying to figure out how immutable things like a List are working, and how I can add things to it?
You can't. That's what immutable means, after all. If Latin is not your cup of tea, the English translation of immutable is unchangeable. It should be clear now, why you can't change something that is unchangeable.
I am very sorry for asking such dumb questions, but why is here my list always empty when printing it out?
You create an empty list, and you never change it (because it cannot be changed anyway). So, of course it is empty.
What can you can do, however, is create a new list which is almost exactly like the old list, except with a new item prepended to the front. That's what you are doing here:
input :: list
However, you don't assign this new list anywhere, you don't return it, you completely ignore it.
If you want to actually use your list in any way, you need to remember it somehow. The most obvious solution would be to assign it to a variable:
var end = false
var list: List[String] = List() // note: `var` instead of `val`
while (!end) {
val input = scala.io.StdIn.readLine("input:")
if (input == "stop" ) end = true
else list = input :: list // note: assign to `list`
}
println(list)
However, that's not very idiomatic. After all, we have now taken an immutable list and assigned it to a mutable variable … IOW, we have just moved the mutability around.
Instead, we could use a recursive solution:
def buildListFromInput(list: List[String] = List()): List[String] = {
val input = scala.io.StdIn.readLine("input:")
if (input == "stop") list else buildListFromInput(input :: list)
}
println(buildListFromInput())
This solution is not only recursive, the recursive call is also in tail position (IOW, the method is tail-recursive), which means that it will be just as efficient as a while loop (in fact, it will be compiled into a while loop, or more precisely, into a GOTO). The Scala Language Specification guarantees that all implementations of Scala must eliminate direct tail-recursion.

The reason
println(list)
is only printing out an empty list is because the bit
input :: list
isn't actually mutating the list itself. It is simply, in this case, very temporarily, creating a list containing the input at the front.
Try
println(input :: list)
or
val newList = input :: list
println(newList)
and you'll see what I mean.

Try rewriting the code in more functional way. Every operation on Immutable data structures return new instance with change. So :: operator creates new List with input on front. You might want to try rewrite this code as tail recursive function as follows.
#tailrec
def scanInput(continue: Boolean,acc: List[String]): List[String] = {
val input = scala.io.StdIn.readLine("input:")
if(!continue) acc
else scanInput(input != "stop", input :: acc)
}
Above code has no mutating state and it suits more Scala functional style.

In scala List is immutable.
Then how can I add items to the list?
When you add an item to list a new List instance is crated with a item as its head and its tail now contains the previous list.
If you have list of "1,2,3" called intList internally it is represented as
List(3, List(2, List(1, Nil) ) )
If you add an element 4 to this intList
List(4, intList )
Lets call this newList
Note intList still contains List(3, List(2, List(1, Nil) ) ).
If you want the intList to refer the newList You will have to do
intList = intList.add(4)
How can I fix my code
Change list from val to var. Then you can assign resulting List to list variable
list = input :: list
Source: Online course on Scala called Functional Programming Principles in Scala

Thank you for all your help, I appreciate your help so much from all of you!
I should have taken a closer look at recursion since it seems to be really important like in Scala!
But trough your help I am getting an better idea of how it works!
I just tried to figure out how your solutions are working and created my own:
val list = List()
def scanInput(acc: List[String]): List[String] = {
val input = scala.io.StdIn.readLine("input:")
input match {
case "stop" => acc
case _ => scanInput(input :: acc)
}
}
println(scanInput(list))

Related

split list by delimiter in Kotlin

I have a below list
val list = listOf("o=one", "t=two", "t=two", "f=four", "o=one", "t=two", "s=seven", "o=one")
I wanna split it into list of the list contains [["o=one", "t=two", "t=two", "f=four"],["o=one", "t=two", "s=seven"],["o=one"]]
Actually I want to group list by "o=" delimiter and the list will always have at least one "0=" value. How could I achieve this in Kotlin without creating mutable var keyword because of my code should be in the functional style?
I have tried with group() and groupBy{} methods but couldn't get the expected result.
This might not cover all edge cases, and there might be better ways of doing it, but given that your requirements are not fully clear and extremely contrived, this should get you started either way. From here on out you can polish it yourself.
// Identifies indices of all "o=" elements in the list.
val splitAt = list
.withIndex()
.filter { it.value.startsWith( "o=" ) }
.map { it.index }
// Create sublists.
val split = splitAt
.windowed( 2, step = 1, partialWindows = true )
.map {
list.subList(
it[0],
if (it.count() == 1) it[0] + 1 else it[1]
)
}

How can I get the elements of list using ListBuffer

I am facing a very weird problem while getting elements of a list
Below is the piece of code where I am passing arguments as "bc" and "mn"
val list1 = List("abc", "def", "mnp")
val list2 = List(args(0), args(1))
val header1=list1.filter(x => list2.exists(y => x.contains(y)))
println(header1)
Output-List("abc","mnp")
I am trying to do it in a different way (by passing the same arguments)but getting an empty List
val list1 = List("abc", "def", "mnp")
//val list2 = List(args(0), args(1))
val ipList1= new ListBuffer[Any]
for(i <- 0 to 1){
ipList1 +=args(i)
}
val list2=ipList1.toList
println(list2)
val header1=list1.filter(x => list2.exists(y => x.contains(y)))
println(header1)
Output-List(bc, mn)
List()-->This is the empty List I am getting
Can Someone please tell where I am doing it wrong and How to make it right?
The problem is that x.contains(y) does not mean what you think it means. String has a contains method that checks whether another String is a substring of this String. But in your code y doesn't have type String, but type Any. So the contains method of String isn't called. It's the contains method of WrappedString which treats the String x as though it's a Seq[Char]. That method doesn't check whether any substring is equal to y but whether any character is equal to y.
The solution, obviously, is to use a ListBuffer[String].
The problem is that you are using a ListBuffer[Any] thus the elements lost their type information from String to Any and apparently that changes the semantics of the code.
You may either do this:
val ipList1 = new ListBuffer[String]
for (i <- 0 to 1) {
ipList1 += args(i).toString
}
val list2 = ipList1.toList
Or even better just:
val list2 = args.slice(0, 2).toList

How to search a list for elements of a tuple?

For my assignment, I have to take a list of tuples of people at a wedding who can't sit next to each other. Then compare it with a list of people at a table. If any two people in the same tuple are in the table list, then it should be false. Otherwise true. This is my first time coding in F# so the syntax is killing me here.
let isValidTable (cantSit:(string*string) list) (people: string list) =
let truth = true;
let rec matchPeople cantSit person1 person2=
match cantSit with
| [] -> None
| head :: tail ->
let (person1,person2) = head
if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
let result2 = false
else
matchPeople tail fst snd;;
let result = true;;
matchPeople cantSit fst snd;;
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")];;
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList;;
printf("\n%O") validOrNah;;
The problem for me is that I keep getting errors like "matchPeople constructor not defined", or "let is unfinished". Any help would be appreciated thank you!
Before: I had
if(first person is in list and second person is in list)
then Some false
else recursive statement;
This code compiled without errors but only printed null. I know variables are immutable in F#, which is making this tough.
There are many problems in your code, all caused by your unfamiliarity with F#. I'll go through it line by line and try to explain what you haven't yet understood.
let isValidTable (cantSit:(string*string) list) (people: string list) =
This is fine.
let truth = true;
There's no need for this assignment at all, since you never use the name truth anywhere else in your code. And if you did need to use it, you could just replace it with the constant true and it would read better. Let's remove this line entirely.
BTW, there's no need for semicolons at the end of lines in F#, unlike in C-like languages. The double semicolon is only used in the F# Interactive interpreter, to tell the interpreter "I'm done entering this expression". This allows you to split an expression across multiple lines, without the interpreter needing to guess when you're done (because many partial expressions in F# can look complete, so explicit expression termination is needed). I won't mention this every time a semicolon comes up, but you can remove all semicolons (and double semicolons) at the end of your lines. The only place a semicolon is needed in F# is between items in a list, such as in x or in weddingList.
On to the next line.
let rec matchPeople cantSit person1 person2=
This looks fine, but in fact, you don't need the person1 and person2 parameters at all. My guess is that you have them in the parameter list because you think you need to declare variables before you create them, but that's not how F# works at all. When you write let (person1, person2) = head later in the function, the variables person1 and person2 are created right there, and there's no need to have them as function parameters. So you can remove them, and your function definition will become let rec matchPeople cantSit =
match cantSit with
This is fine.
| [] -> None
This is a minor mistake. Elsewhere you look like you want to return a Boolean value, but here you return an option instead. In F#, all branches of match and/or if...else must return the same type. Your isValidTable function clearly is intended to return a Boolean, and so is matchPeople, so this should be a Boolean value as well. The question is, should this line return false or true? To answer that question, think about what an empty cantSit list means in the semantics of your problem domain. It would mean that there is nobody who can't sit with each other, so the seating list is valid no matter who's at the table. Or, of course, it could also mean that you've reached the end of the cantSit list by multiple recursive calls, in which case the value you return here will be the value you return finally from the last recursive call. And again, returning true is what you want, because if you had found an invalid sitting pair earlier, you would have returned false immediately and not made another recursive call. So if you get to the point where the cantSit list is empty, then you're ready to return true.
| head :: tail ->
This is fine.
let (person1,person2) = head
This is not just fine, it's quite good.
if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
This is fine, but could be simplified. There's a List.contains function that does what you want here. Any call of the type List.exists (fun item -> item = value) itemList) can be simplified to List.contains item itemList. So this would become if (List.contains person1 people) && (List.contains person2 people) then, which is much easier to read and understand quickly.
let result2 = false
This is incorrect; a let assignment in F# has no value, and since it's the last expression in the if block, that means the if block would not have a value if its condition turns out to be true. This is why you're getting the "unfinished" errors: in F#, a let assignment may never be the last expression of a code block. It must always be followed by an expression that has a value. What you're actually trying to do here is pretty clear: you want to return false if both people are in the list. You can do that by just writing false in this line; I'll explain a little more here.
In F#, if...else is an expression that returns a value, not a statement like it is in most other languages. So you can write something like this:
let n = 5
let s = if n % 2 = 0 then "Even" else "Odd"
printfn "%s" s // Prints "Odd"
Here, your if...else is the last line of one case of the match expression, so its value will be the value of the match expression. And the match expression is the last expression of the matchPeople function, so its value will be the return value of the function. So in the case where you find a matching pair that can't sit together (the true branch of this if...else expression), then you just have to have a line saying false, and that will be the return value of the function if it hits that branch.
Moving on to your next line.
else
This is fine, obviously.
matchPeople tail fst snd;;
This is fine once you remove the fst and snd (since we changed our function signature so that matchPeople now takes just one argument), and remove the semicolons as mentioned previously.
let result = true;;
Same comment as for the earlier let result2 = false line: a let assignment may never be the last line of a code block in F#. Here, what you want to do is let the result of the recursive matchPeople call be the final result of your "outer" level of recursion. You can do that by simply deleting this let result = true line, so that the matchPeople call is the last line of the else block. That means that its result will be the result of the else block, and since the if...else expression is the last expression of this case of match, the recursive call will be the last expression of the match statement. And since the match statement is the last expression of the matchPeople function, its result will also be the result of the overall function (if the code reaches the else branch). That means that this recursive call is in tail position, which is an important concept later: a call is in tail position if its result will be the result of the overall function. A call in tail position is usually known as a "tail call" for short. I won't go into depth about tail calls here, except to say that a tail call can be optimized by the compiler so that it will never cause a stack overflow error, no matter how many times you go through the recursive call. For now, we'll put tail calls aside and go on to look at the rest of your code:
matchPeople cantSit fst snd;;
As with the other call, just remove the fst and snd parameters (and the double semicolon) and this will be fine.
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")];;
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList;;
printf("\n%O") validOrNah;;
All of this is fine once you remove the unnecessary double semicolons. I'd probably write printfn "%O" validOrNah on the last line, but that's personal preference: I like to print a newline at the end of my output, rather than the beginning (printfn prints a newline after whatever you ask it to print, while printf without a trailing n in the function name does not print a trailing newline). But what you have written here is fine.
Making all those changes, here's what your code turns into:
let isValidTable (cantSit:(string*string) list) (people: string list) =
let rec matchPeople cantSit =
match cantSit with
| [] -> true
| head :: tail ->
let (person1,person2) = head
if (List.contains person1 people) && (List.contains person2 people) then
false
else
matchPeople tail
matchPeople cantSit
let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")]
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList
printfn "%O" validOrNah
I made no changes to your logic since it's correct (well done!), so once you make these syntax fixes that I suggested, this should run and print the correct results.

How do I select lists inside a list that have a specific length in Haskell?

In Haskell I have a list that looks like this:
[[["PersonA"],["AddressA"]],[["PersonB"],["AddressB"]],[["PersonC"]]]
and I need the lists within my list that have length=2, i.e. the people that I know the address of. In this case, I would want:
[["PersonA"],["Address"]]
and
[["PersonB"],["Address"]]
and I would not want PersonC because I don't have his address.
I was thinking about something like:
myList = [[["PersonA"],["123456789"]],[["PersonC"],["987654321"]],[["PersonE"]]]
main :: IO ()
main = do
map (\x -> if length x == 2 print x else print "") myList
(print is just an example, I will need to work with them later)
But this returns a
Couldn't match expected type ‘IO ()’ with actual type ‘[IO ()]’
error on line 5.
Any idea how to do that?
Thanks
Your problem is that print is an IO action, and to sequence these you'd need to use mapM_ instead of map to also get back the IO () that main expects. Alternatively, wrap the list of IO actions that map produced in a sequence_ call.
But I don't think this is the right approach anyway. To select from a list, you should use filter not map:
myList = [[["PersonA"],["123456789"]],[["PersonC"],["987654321"]],[["PersonE"]]]
myLen2List = filter (\x -> length x == 2) myList
main :: IO ()
main = print myLen2List
That said, #Daniel Wagner is totally right in the comments. Don't use lists as your custom data type.
data Person = Person { name :: String, address :: Maybe String } deriving (Eq, Show)
myList = [ Person "PersonA" (Just "123456789"),
Person "PersonC" (Just "987654321"),
Person "PersonE" Nothing ]
myAddressList = filter (isJust . address) myList
main = print myAddressList

Pattern matching list prefixes in Scala

I have questions regarding pattern matching of list prefixes (i.e. the first couple of elements of a list).
This compiles, but it does not work as expected:
val l = List(1,2,3)
val test = { m: List[Int] =>
m match {
case l :: tail => println("tail: "+tail.mkString(","))
case _ => println("no match")
}
}
test(List(1,2,3,4,5))
Output is tail: 2,3,4,5. I'd expect it to say either tail: 4,5, or to fail to match, or to fail at compile time. What makes this work as it does?
My second question is: How can I match a list prefix using a list? I know that this works as I expect:
case 1 :: 2 :: 3 :: tail => println("tail: "+tail.mkString(","))
I have, however, my prefixes as lists, and cannot hard-code them. Is pattern matching even the right thing here?
I know I could do something like
if (m startsWith l) {
val tail = m drop l.size
}
But a long list of these seems rather inelegant, especially in Scala.
Regarding the output of your first code snippet, the l inside of the match is actually a new value that shadows the outer scoped l and captures 1 during execution.
The problem you are encountering is that :: is the unapply for List to break it into exactly a single head value and the tail, deconstructing the linked list.
While there is a ::: operation to go along with ::: to concatenate two lists, it does not have a corresponding unapply which would let you use it in a pattern match in the way you desire.
I don't think this is possible. Closest syntax i could propose based on this workaround:
import collection.SeqLike
implicit class PrefixMatcher[T](prefix: Seq[T]) {
object then {
def unapply[S <: SeqLike[T,S]](seq: S): Option[S] =
if (seq startsWith prefix) Some(seq drop prefix.length) else None
}
}
Then you could use it as
val test: List[Int] => Unit = {
case l.then(tail) => println("tail: " + tail.mkString(","))
case _ => println("no match")
}
Addresing the first part of your question: As #Arne mentions, case l is not being matched against your list, but captures a new list. For the former you'd need to enclose it on backticks, but even then I don't see how you can achieve what you want, the closes I can think of is:
case `l` :+ x => println(s"tail is $s") //but this just works when the tail is just one element long.
For the final part of your question, maybe pattern matching is not the right thing to do here, how about:
val prefixes = List (List (1,2,3), List(4,5,6)...)
def findTail(li:List[Int]) = prefixes.collectFirst{ case p if li.startsWith(p) => li.drop(p.size) } //Option[List[Int]]
This will find the tail for the first prefix that matches the testList or None if there was no match.You can easily generalize it to work with more than just Ints.