Process the same input file concurrently Let's say we have a text file that contains 2 different types of lines. For the sake of example, one group starts with "i:" (for Integer) and the other group starts with "s:" (for String), something like the following file: s:New york s:Apple i:387548 s:Amsterdam i:4556 i:39874 s:Orange i:56787 s:Banana i:4657567 s:Turkey i:45679456 s:Iran i:4356456 i:23423 i:456 s:Ukraine i:453645 i:5456 We want to process these input lines separately but concurrently. And the process can be anything, for this example, we just print them to the console. But what matters is that we open the file only for READ so 2 different processes (or routines) can read the file at the same time. The Cats Effect answer to open files (or in general any resources) in a safe and efficient way, is Resource class. So we need a function to take the path to the file and give us a Resource of some type that allows us to read the file line by line. One o...
Let's practice some functional problem-solving!
Consider the classic problem of finding the index of a sub-string in a larger string. So we want to write a function that if we pass it the following strings it returns 0.
"hello world", "hello"
If we pass it the following strings it returns 6
"hello world", "world"
If we pass it the following strings it returns None, because "apple" can not be found inside "hello world.
"hello world", "apple"
So our function signature should look like this:
def findFirstSubString(str: String, subStr: String): Option[Int] = ???If we want to implement it in an imperative way, and yes Scala allows imperative programming, we can implement the function as follows, but we don't want imperative programming, do we?
def findFirstSubString_bad(str: String, subStr: String): Option[Int] = {
var j = 0;
var temp = ""
for (i <- 0 to str.length - 1) {
if (str.charAt(i) == subStr.charAt(j) && j < subStr.length) {
temp = temp + str.charAt(i)
j += 1
} else {
temp = ""
j = 0;
}
if (temp == subStr) return Some(i - (subStr.length - 1))
}
None
}In functional programming, we usually implement loops using recursion. So we do not need a for-loop.
This would be one recursive solution for the problem:
- A helper function to be called recursively (tail-recursively to be precise) that:
- Takes 3 parameters, 2 Strings, and one Int
- If the first String is smaller than the second String returns None, otherwise
- If the First String starts with the second String, return the Int parameter, otherwise
- Call itself using the first String without its first character, the original second String, and the Int param + 1
- Call the helper function using the two parameters of the original function and 0
def findFirstSubString(str: String, subStr: String): Option[Int] = {
def loop(remainder: String, lookingFor: String, pos: Int): Option[Int] = {
if (remainder.length < lookingFor.length) None
else if (remainder.substring(0, lookingFor.length) == lookingFor) Some(pos)
else loop(remainder.substring(1), lookingFor, pos + 1)
}
loop(str, subStr, 0)
}We can test our function like :
def main(args: Array[String]): Unit = {
println(findFirstSubString("hello world", "world")) // Some(6)
println(findFirstSubString("hello world", "WORLD")) // None
println(findFirstSubString("hello world", "hello")) // Some(0)
}
Comments
Post a Comment