I'm building a map of enumeration entries to simple data accessors in an object. Here's an example (from the interpretor) using Int as the key:
class Obj(a: Int, b: Int) {
def getA = a
def getB = b
}
val m : Map[Int, (Obj) => Int] = Map(
(2, (o: Obj) => o.getA)
);
val d = m(2)(new Obj(3,4))
This works fine, but having to write a function with the :Obj type explicitally in the parameter in each map value seems unnecessary:
(o: Obj) => o.getA
Is there a tighter syntax I'm missing?
In this case the type will be inferred, for instance:
scala> val m : Map[Int, (Obj) => Int] = Map(
| (2, _.getA)
| )
m: Map[Int,Obj => Int] = Map(2 -> <function1>)
scala> m(2)( new Obj(3,4) )
res0: Int = 3
Here I used the underscore to make the function definition as terse as possible, but you could also define the function as: o => o.getA. It can be useful if the argument is used more than once, for instance: o => o.getA + o.getB.
If you want to get rid of the type annotation on the left hand side (not always a good idea, but good for conciseness) you can, keeping your original right hand side, or slightly shorter:
val m = Map( (2, (_: Obj).getA) )
As an aside, in Scala it would be more idiomatic to define your class as
class Obj(val a: Int, val b: Int)
// or
case class Obj(a: Int, b: Int)
and refer to your fields as simply a and b, since the compiler provides you with getters.
Related
I need to render a sorted map by a user-defined type.
SortedMap[X, Seq[Y]]
Json library should render the map as ordered by the X.name
case class X(order: Int, name: String) extends Ordered[X]
Assume I have X(1, "James"), X(2, "Mel"), X(3, "Ashley").
The output map should be
"James" : Seq(Y)
"Mel" : Seq(Y)
"Ashley": Seq(Y)
The inMap is correctly sorted (as viewed by the debugger), but after the rendering, the sorting order(X.order) is lost. Probably due to the toSeq. Any ideas?
implicit val myWrites = new Writes[SortedMap[X, Seq[Y]]] {
def writes(inMap: SortedMap[X, Seq[Y]]): JsValue =
Json.obj(inMap.map {case (s, o) =>
val r: (String, JsValueWrapper) = s.name() -> Json.toJson(o)
r
}.toSeq:_*)
}
So...
I never meet the word "render" used as "convert to"
ordering by key original key in SortedSet is lost after mapping because you change the key type so the result is ordered by a new key type (here: String)
if you want to preserve the order of items in between mapping I would suggest using ListMap
though in your particular case you can do away with Seq of tuples, as at the end of the day, this is what you need to produce
implicit val myWrites: Writes[SortedMap[X, Seq[Y]]] = new Writes[SortedMap[X, Seq[Y]]] {
def writes(inMap: SortedMap[X, Seq[Y]]): JsValue =
Json.obj(inMap.toSeq.map { case (s, o) =>
s.name() -> Json.toJson(o)
}:_*)
}
This question already has answers here:
How can I define an anonymous generic Scala function?
(2 answers)
Closed 9 years ago.
As most of you probably know you can define functions in 2 ways in scala, there's the 'def' method and the lambda method...
making the 'def' kind generic is fairly straight forward
def someFunc[T](a: T) { // insert body here
what I'm having trouble with here is how to make the following generic:
val someFunc = (a: Int) => // insert body here
of course right now a is an integer, but what would I need to do to make it generic?
val someFunc[T] = (a: T) => doesn't work, neither does val someFunc = [T](a: T) =>
Is it even possible to make them generic, or should I just stick to the 'def' variant?
As Randall Schulz said, def does not create a function, but a method. However, it can return a function and this way you can create generic functions like the identity function in Predef. This would look like this:
def myId[A] = (a: A) => a
List(1,2,3) map myId
// List(1,2,3)
List("foo") map myId
// List("foo")
But be aware, that calling myId without any type information infers Nothing. In the above case it works, because the type inference uses the signature of map, which is map[B](f: A => B) , where A is the type of the list and B gets infered to the same as A, because that is the signature of myId.
I don't believe it's possible. You can look at this previous post for more details:
How can I define an anonymous generic Scala function?
The only way around it (as one of the answers mentions) is to extend something like FunctionX and use a generic at the class level and then use that in the override of the apply function.
I don't believe it's possible either, but I'm a pessimist.
http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/
Edit:
Tell me if this isn't what you're asking, but this is why the accepted answer isn't what I thought you were asking for, see the link:
scala> :pa
// Entering paste mode (ctrl-D to finish)
def myId[A] = (a: A) => a
List(1,2,3) map myId
// List(1,2,3)
List("foo") map myId
// List("foo")
// Exiting paste mode, now interpreting.
myId: [A]=> A => A
res0: List[String] = List(foo)
scala> val f1 = myId[Int]
f1: Int => Int = <function1>
scala> val f2 = myId[String]
f2: String => String = <function1>
scala> List(1,2,3) map f2
<console>:10: error: type mismatch;
found : String => String
required: Int => ?
List(1,2,3) map f2
^
scala> List("foo") map f1
<console>:10: error: type mismatch;
found : Int => Int
required: String => ?
List("foo") map f1
^
The function values are not polymorphic, i.e., generic.
The closest thing is polymorphic functions I believe:
https://github.com/milessabin/shapeless#polymorphic-function-values
Is there any way to do something like argument.<keyword>(function) in Scala?
For example:
[1,2,3].supply(myFunc) yielding 6 if myFunc were the summation function.
It just seems easier to chain functions if I were able to do this, instead of calculating something and 'wrapping it' into an argument for a function call.
You can define it yourself if you want. It's frequently called the "pipe operator":
class AnyWrapper[A](wrapped: A) {
def |>[B](f: A => B) = f(wrapped)
}
implicit def extendAny[A](wrapped: A): AnyWrapper[A] = new AnyWrapper(wrapped)
Then:
def plus1(i: Int) = i + 1
val fortyTwo = 41 |> plus1
Do you mean something like this:
val sum = { (a: Int, b: Int) => a + b }
List(1, 2, 3).reduceLeft(sum)
I'm implementing an actor-based app in scala and I'm trying to be able to pass functions between the actors for them to be processed only when some message is received by the actor.
import actors.Actor
import java.util.Random
import scala.Numeric._
import Implicits._
class Constant(val n:Number) extends Actor{
def act(){
loop{
receive{
case "value" => reply( {n} )
}
}
}
}
class Arithmetic[T: Numeric](A: ()=>T, B: ()=>T) extends Actor{
def act(){
receive{
case "sum" => reply ( A() + B() )
/* case "mul" => reply ( A * B )
*/
}
}
}
object Main extends App{
val c5 = new Constant(5)
c5.start
val a = new Arithmetic({c5 !! "value"}, {c5!!"value"} )
a.start
println(a!?"sum")
println(a!?"mul")
}
In the example code above I would expect the output to be both 5+5 and 5*5. The issue is that reply is not a typed function and as such I'm unable to have the operator (+,*) to operate over the result from A and B.
Can you provide any help on how to better design/implement such system?
Edit: Code updated to better reflect the problem. Error in:
error: could not find implicit value for evidence parameter of type Numeric[Any]
val a = new Arithmetic({c5 !! "value"}, {c5!!"value"} )
I need to be able to pass the function to be evaluated in the actor whenever I call it. This example uses static values but I'll bu using dynamic values in the future, so, passing the value won't solve the problem. Also, I would like to receive different var types (Int/Long/Double) and still be able to use the same code.
The error: Error in: error: could not find implicit value for evidence parameter of type Numeric[Any]. The definition of !!:
def !! (msg: Any): Future[Any]
So the T that Arithmetic is getting is Any. There truly isn't a Numeric[Any].
I'm pretty sure that is not your problem. First, A and B are functions, and functions don't have + or *. If you called A() and B(), then you might stand a chance... except for the fact that they are java.lang.Number, which also does not have + or * (or any other method you'd expect it to have).
Basically, there's no "Number" type that is a superclass or interface of all numbers for the simple reason that Java doesn't have it. There's a lot of questions touching this subject on Stack Overflow, including some of my own very first questions about Scala -- investigate scala.math.Numeric, which is the best approximation for the moment.
Method vs Function and lack of parenthesis
Methods and functions are different things -- see tons of related questions here, and the rule regarding dropping parenthesis is different as well. I'll let REPL speak for me:
scala> def f: () => Int = () => 5
f: () => Int
scala> def g(): Int = 5
g: ()Int
scala> f
res2: () => Int = <function0>
scala> f()
res3: Int = 5
scala> g
res4: Int = 5
scala> g()
res5: Int = 5
I'm new to Scala, and being able to pass functions to other functions is pretty neat-- but can I pass an arbitrary function reference to another function? The arity of said functional parameter will be fixed (that said, I'm also curious about whether you can pass a function with arbitrary arity as well). I keep getting tripped up on type errors. I've tried using Any but it doesn't seem to help.
E.g., I have the code below:
class CodeRunner(val user_defined: (Int) => Unit) {
def run(input: Int) = {
user_defined(input)
}
}
def arbitrary_code(input: Int) = { println("Running with input " + input) }
val d1 = new CodeRunner(arbitrary_code)
d1.run(4)
And I get:
Running with input 4
Now, let's say that I want to pass the following function instead:
def arbitrary_code(input: String) = { println("Running with input " + input) }
How can I change my CodeRunner class to handle both?
How can I change my CodeRunner class to handle both?
You can make the arbitrary type a parameter of the class:
class CodeRunner[T](val user_defined: (T) => Unit) {
def run(input: T) = {
user_defined(input)
}
}
def arbitrary_code(input: Int) = { println("Running with input " + input) }
val d1 = new CodeRunner(arbitrary_code)
d1.run(4)
def arbitrary_code2(input: String) = { println("Running with input " + input) }
val d2 = new CodeRunner(arbitrary_code2)
d2.run("hello")
Note that the type of d2 is CodeRunner[String] which is not assignable to d1 which is CodeRunner[Int].
Generic types allow you to define a class with a placeholder type that gets specified when an object gets instantiated. The compiler is happy because it can make sure that everything is type safe, and you're happy because you can instantiate the object and pass in arbitrary types for the value.
To use a generic type with your class, you could modify it like this:
class CodeRunner[T] (val user_defined: (T) => Unit) {
def run(input: T) = {
user_defined(input)
}
}
The [T] after "class CodeRunner" is the important part -- it defines that there is a generic type T (you could replace T with another capital letter, etc.) which will be used within the class definition.
So, if you define a method:
def arbitrary_code(input: String) = { println("Running with input " + input) }
and then pass it in:
val d1 = new CodeRunner(arbitrary_code)
... the compiler then says "aha, for this instance of CodeRunner the generic type T is a string". And if you invoke
d1.run("string")
the compiler will be happy, but won't let you pass in d1.run(4).
To pass an arbitrary function you can certainly use generics :
def run[T,U](f: T => U) = println(f)
For arbitrary arity, it's impossible because a function of type T => U is instance of Function1[U,T] and a function of type (T,U) => V is an instance of Function2[T,U,V]. (Also, I couldn't find any useful use case).
However, there is a smart concept called "currying". It consists in transforming a function that takes multiple arguments and return a value in a function that takes a single argument and returns another function.
Here's an example :
def nonCurriedAdd(x: Int, y: Int) = x + y
// nonCurriedAdd(4,6)
def curriedAdd(x: Int) = (y: Int) => x + y
// we can use some syntax sugar
def curriedAdd(x: Int)(y: Int) = x + y
// curriedAdd(4)(6)
So, you can now do `d1.run(curriedAdd).
You can also transform a non-curried function in a curried one by using the "curried" method :
d1.run(nonCurriedAdd.curried)
can I pass an arbitrary function reference to another function? The arity of said functional parameter will be fixed
As always, write down the type of the function you are developing, and all becomes clear.
Your word "arbitrary" suggests that the function arguments work at any type. That is, they are polymorphic functions (or generic functions, in some languages).
The following should translate fairly cleanly to Scala:
== The type of an "arbitrary" function of fixed arity
f :: a -> b -> c -> d
-- The type of a function that accepts such a
-- function as an argument, and does something with it:
g :: (a -> b -> c -> d) -> a -> b -> c -> d
-- And a function that implements something of that type
g f a b c = f a b c
You might be able to come up with a few other such higher-order functions, that take functions of fixed arity, but arbitrary (i.e. polymorphic) type, and operate on them.
Classic higher-order functions are e.g.
map :: (a -> b) -> [a] -> [b]
fold :: (a -> b -> b) -> b -> [a] -> b
And many, many others.
scala> object codeRunner {
| def run[InputType, OutputType](code: InputType => OutputType) = (input: InputType) => code(input)
| }
defined module codeRunner
scala> def someCode(x: Int) {
| println("This code uses " + x)
| }
someCode: (x: Int)Unit
scala> def otherCode(y: String) {
| println("This code uses " + y)
| }
otherCode: (y: String)Unit
scala> codeRunner.run(someCode)(10)
This code uses 10
scala> codeRunner.run(otherCode)("hello")
This code uses "hello"