I have the following code:
object ContraCats {
val showString = Show[String]
def main(args: Array[String]): Unit = {
val m = showString.contramap[Symbol](_.name).show('dave)
val a = showString.contramap[Symbol](_.name)('dave)
}
}
As you can see, it is possible to write as currying version and the other as method call. Why it is possible?
The contramap returns a Show instance.
Show has both the show and the apply methods.
The apply method is special in Scala, since this two are equivalent:
someValue.apply(someArg)
someValue(someArg)
So in your example what's happening is that you're calling the apply method on the Show instance returned by contramap, i.e.
val m = showString.contramap[Symbol](_.name).show('dave)
val a = showString.contramap[Symbol](_.name).apply('dave)
Update
While the explanation above would make sense, I realized cats's Show doesn't have an apply method, so your code shouldn't compile (I tried on a REPL and it doesn't)
Related
I'm using other teams api(let's name it otherTeamAPI) to call data, so in my function, my code looks like this:
def getData(host:String, port:Int, date: String): Map[String, String] = {
val data = new otherTeamAPI(host,port)
val latestData = data.getLatestData(date)
}
Could someone teach me how to use Mockito to do the same thing to get data in unit test? I'm not sure whether to use something like below to new an api:
val otherTeamAPI = Mock[otherTeamAPI]
otherTeamAPI.getLatestData(date)
How to get data everytime i trigger my function getData? Do i need to do somthing new a mock otherTeamAPI?
Your code, written as is, is not testable. You have to be able to pass your method an instance of the OtherTeamAPI so that your production code uses a real instance but test code can use a fake one (a "mock").
How you pass this instance depends on the structure of the rest of your code: either as a parameter of this method getData or as an attribute of the class that contains it.
The first one would look like this:
def getData(api: OtherTeamApi, date: String): Map[String, String] = {
val latestData = api.getLatestData(date)
// ...
}
And then in your test, you can do something like:
val fakeApi = mock[OtherTeamAPI]
when(fakeApi.getLatestData(anyString())).the return(...)
val result = getData(fakeApi, ...)
// Then assert on result
This is a high level answer. You'll need to learn more about Mockito to find out what you want to do.
I'm looking to call the ATR function from this scala wrapper for ta-lib. But I can't figure out how to use wrapper correctly.
package io.github.patceev.talib
import com.tictactec.ta.lib.{Core, MInteger, RetCode}
import scala.concurrent.Future
object Volatility {
def ATR(
highs: Vector[Double],
lows: Vector[Double],
closes: Vector[Double],
period: Int = 14
)(implicit core: Core): Future[Vector[Double]] = {
val arrSize = highs.length - period + 1
if (arrSize < 0) {
Future.successful(Vector.empty[Double])
} else {
val begin = new MInteger()
val length = new MInteger()
val result = Array.ofDim[Double](arrSize)
core.atr(
0, highs.length - 1, highs.toArray, lows.toArray, closes.toArray,
period, begin, length, result
) match {
case RetCode.Success =>
Future.successful(result.toVector)
case error =>
Future.failed(new Exception(error.toString))
}
}
}
}
Would someone be able to explain how to use function and print out the result to the console.
Many thanks in advance.
Regarding syntax, Scala is one of many languages where you call functions and methods passing arguments in parentheses (mostly, but let's keep it simple for now):
def myFunction(a: Int): Int = a + 1
myFunction(1) // myFunction is called and returns 2
On top of this, Scala allows to specify multiple parameters lists, as in the following example:
def myCurriedFunction(a: Int)(b: Int): Int = a + b
myCurriedFunction(2)(3) // myCurriedFunction returns 5
You can also partially apply myCurriedFunction, but again, let's keep it simple for the time being. The main idea is that you can have multiple lists of arguments passed to a function.
Built on top of this, Scala allows to define a list of implicit parameters, which the compiler will automatically retrieve for you based on some scoping rules. Implicit parameters are used, for example, by Futures:
// this defines how and where callbacks are run
// the compiler will automatically "inject" them for you where needed
implicit val ec: ExecutionContext = concurrent.ExecutionContext.global
Future(4).map(_ + 1) // this will eventually result in a Future(5)
Note that both Future and map have a second parameter list that allows to specify an implicit execution context. By having one in scope, the compiler will "inject" it for you at the call site, without having to write it explicitly. You could have still done it and the result would have been
Future(4)(ec).map(_ + 1)(ec)
That said, I don't know the specifics of the library you are using, but the idea is that you have to instantiate a value of type Core and either bind it to an implicit val or pass it explicitly.
The resulting code will be something like the following
val highs: Vector[Double] = ???
val lows: Vector[Double] = ???
val closes: Vector[Double] = ???
implicit val core: Core = ??? // instantiate core
val resultsFuture = Volatility.ATR(highs, lows, closes) // core is passed implicitly
for (results <- resultsFuture; result <- results) {
println(result)
}
Note that depending on your situation you may have to also use an implicit ExecutionContext to run this code (because you are extracting the Vector[Double] from a Future). Choosing the right execution context is another kind of issue but to play around you may want to use the global execution context.
Extra
Regarding some of the points I've left open, here are some pointers that hopefully will turn out to be useful:
Operators
Multiple Parameter Lists (Currying)
Implicit Parameters
Scala Futures
I had a piece of code that looks like this:
val foo = df.map(parser.parse) // def parse(str: String): ParsedData = { ... }
However, I found out that passes a lambda into Scala that captures this, I guess Scala treated code above into:
val foo = df.map(s => /* this. */parser.parse(s))
where my intention to pass lightweight capture. In Java, I'd do parser::parse, but that isn't available in Scala.
That does the trick:
val tmp = parser // split val read from capture; must be in method body
val foo = df.map(tmp.parse)
but makes code a little bit more unpleasant. There is an answer by #tiago-henrique-engel that could be used like:
val tmp = parser.parse _
val foo = df.map(tmp)
but it still requires a temporary val.
So, is there a way to pass lightweight capture to map without storing it first into some val to keep the code clean?
I have the two following objects (in scala and using spark):
1. The main object
object Omain {
def main(args: Array[String]) {
odbscan
}
}
2. The object odbscan
object odbscan {
val conf = new SparkConf().setAppName("Clustering").setMaster("local")
conf.set("spark.driver.maxResultSize", "3g")
val sc = new SparkContext(conf)
val param_user_minimal_rating_count = 2
/***Connexion***/
val sqlcontext = new org.apache.spark.sql.SQLContext(sc)
val sql = "SELECT id, data FROM user_profile"
val options = connectMysql.getOptionsMap(sql)
val uSQL = sqlcontext.load("jdbc", options)
val users = uSQL.rdd.map { x =>
val v = x.toString().substring(1, x.toString().size - 1).split(",")
var ap: Map[Int, Double] = Map()
if (v.size > 1)
ap = v(1).split(";").map { y => (y.split(":")(0).toInt, y.split(":")(1).toDouble) }.toMap
(v(0).toInt, ap)
}.filter(_._2.size >= param_user_minimal_rating_count)
println(users.collect().mkString("\n"))
}
When I execute this code I obtain an infinite loop, until I change:
filter(_._2.size >= param_user_minimal_rating_count)
to
filter(_._2.size >= 1)
or any other numerical value, in this case the code work, and I have my result displayed
What I think is happening here is that Spark serializes functions to send them over the wire. And that because your function (the one you're passing to map) calls the accessor param_user_minimal_rating_count of object odbscan, the entire object odbscan will need to get serialized and sent along with it. Deserializing and then using that deserialized object will cause the code in its body to get executed again which causes an infinite loop of serializing-->sending-->deserializing-->executing-->serializing-->...
Probably the easiest thing to do here is changing that val to final val param_user_minimal_rating_count = 2 so the compiler will inline the value. But note that this will only be a solution for literal constants. For more information see constant value definitions and constant expressions.
An other and better solution would be to refactor your code so that no instance variables are used in lambda expressions. Referencing vals that are defined in an object or class will get the whole object serialized. So try to only refer to vals that are local (to a method). And most importantly don't execute your business logic from within a constructor/the body of an object or class.
Your problem is somewhere else.
The only difference between the 2 snippets is the definition of val Eps = 5 outside of the map which does not change at all the control flow of your code.
Please post more context so we can help.
What I'm trying to do (this is a simplified example, but contains all I need)
trait MyTrait[T] {
val name = Somefunction(simpleName)
def simpleName(implicit m:Manifest[T]) = m.erasure.getSimpleName
}
But I get a "No Manifest available for T" compiler error on the val initialisation at simpleName.
doing
val name = Somefunction(implicitly[Manifest[T]].erasure.getSimpleName)
does the same
Somefunction returns a object that is expensive to create, so I only want to create it once.
The only way I got this to work is by using a function that checks if the object has already been created and if so then just return it else create it first and then return it.
EDIT -- added example of how I can get it to work
example
trait MyTrait[T] {
var n:MyClass = null
def name(implicit m:Manifest[T]) = {
if(n == null) n = Somefunction(implicitly[Manifest[T]].erasure.getSimpleName)
n
}
}
You cannot declare the type parameter of a trait as having a Manifest context-bound because it is equivalent to requiring a constructor parameter (which a trait cannot have). I understand that allowing this is planned for some future version of scala.
Furthermore, a val cannot have parameters, so it is simply not possible to instantiate a val dependent on an instance of Manifest[T] that I can see. But you have said you have got this to work: how?