This works:
List(3, 1, 2).sorted apply 1
res1: Int = 2
And this works:
var x = List(3, 1, 2).sorted
x: List[Int] = List(1, 2, 3)
x(1)
res2: Int = 2
but this doesn't:
List(3, 1, 2).sorted (1)
error: type mismatch;
found : Int(1)
required: Ordering[?]
List(3, 1, 2).sorted (1)
^
And even parentheses don't clue the parser in to what I want:
(List(3, 1, 2).sorted)(1)
error: type mismatch;
found : Int(1)
required: Ordering[?]
(List(3, 1, 2).sorted)(1)
It seems like a natural expression. What am I doing wrong?
This works:
(Listed(3, 1, 2).sorted _)(1),
but I'm not sure whether it is much more convenient to use than:
Listed(3, 1, 2).sorted apply 1.
I'd go for the latter anyways.
I think you have to keep the apply. The reason is that sorted isn't "parameterless", it's defined as
def sorted [B >: A] (implicit ord: Ordering[B]) : List[A]
As this is an implicit parameter, the Ordering[Int] is normally provided automatically, but if you use parens, the compiler thinks you want to specify another Ordering[Int] (let's say backwards).
The required parameter can be provided this way:
List(3, 1, 2).sorted(implicitly[Ordering[Int]])(1)
Though using apply() looks shorter and less scary.
The shortest you could make it--not without a small performance penalty, however--is
class Allow_\[A](a: A) { def \ = a }
implicit def allowEveryone[A](a: A) = new Allow_\[A](a)
scala> List(1,3,2).sorted\(1)
res0: Int = 2
If you can accept another character, this might be nicer: <> looks like parens anyway, and can be read as "please fill in the implicit parameters like usual":
class Allow_<>[A](a: A) { def <> = a }
implicit def allowEveryone[A](a: A) = new Allow_<>[A](a)
scala> List(1,3,2).sorted<>(1)
res0: Int = 2
Related
I have a testing program in which we have in memory static arrays. I am using type aliases for brevity.
The following works in the REPL
type >[T] = Array[T]
val dat = >(>(1,2,3),>(2,3,4))
dat: Array[Array[Int]] = Array(Array(1, 2, 3), Array(2, 3, 4))
However changing the identifier to "A" from ">" does not work: the type is created but the same syntax for creating the array as used above fails:
scala> type A[T] = Array[T]
defined type alias A
scala> val dat = A(A(1,2,3),A(2,3,4))
<console>:7: error: not found: value A
val dat = A(A(1,2,3),A(2,3,4))
Also, NEITHER of the two above work within a Scala program AFAICT:
test("VectorProjection") {
type A[T] = Array[T]
// Next line shows RED for all the A's and also has compiler error: "not found: value A"
val dat = A(A(1., 2., 3.), A(1.5,2.,2.5), A(2.,3.8,5.6), A(2.5,3.0,3.5), A(3.1,3.7,4.3) )
val firsteigen = subtractProject(dat(0), dat(4))
}
Looking for:
1) For the REPL: An explanation of why the symbol ">" works but not
the identifier would be helpful.
2) For a real scala program/class:
An explanation of if it were possible to use any syntax similar to
the above
UPDATE Per suggestion by James Iry the following approach does work :
def A[T : ClassTag](ts: T*) = Array(ts:_*)
Here it is in action:
test("VectorProjection") {
def A[T : ClassTag](ts: T*) = Array(ts:_*)
val dat = A(
A(1., 2., 3.),
A(1.5,2.,2.5),
A(3.,6.,9.) )
val firstEigen = subtractProject(dat(0), dat(5))
println(s"firstEigen: ${firstEigen.mkString(",")}")
}
Another UPDATE Another answer hits closer to this OP:
Use type and val together:
type A = Array[Double]
val A = Array
Here it is in action:
test("VectorProjection") {
type A = Array[Double]
val A = Array
val dat = A(
A(1., 2., 3.),
A(1.5,2.,2.5),
A(3.,6.,9.) )
val firstEigen = subtractProject(dat(0), dat(5))
println(s"firstEigen: ${firstEigen.mkString(",")}")
}
I'm not able to replicate your success with '>'
scala> type >[T]=Array[T]
defined type alias $greater
scala> >(1,2,3)
<console>:8: error: not found: value >
>(1,2,3)
^
At least, not until I define it
scala> import scala.reflect._
import scala.reflect._
scala> def >[T : ClassTag](ts: T*) = Array(ts:_*)
$greater: [T](ts: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
scala> >(1,2,3)
res1: Array[Int] = Array(1, 2, 3)
Same thing works for A
scala> type A[T]=Array[T]
defined type alias A
scala> A(1,2,3)
<console>:11: error: not found: value A
A(1,2,3)
^
scala> def A[T : ClassTag](ts: T*) = Array(ts:_*)
A: [T](ts: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
scala> A(1,2,3)
res2: Array[Int] = Array(1, 2, 3)
For an explanation: type X = Y just creates a synonym for the type X. It doesn't bring in synonyms for everything else that might be associated with the type like companion objects, constructor methods, etc.
If you create a value alias it will work:
type A[T] = Array[T]
val A = Array
val dat = A(A(1,2,3),A(2,3,4)) //dat: Array[Array[Int]] = Array(Array(1, 2, 3), Array(2, 3, 4))
Line 2 creates a value alias, so you can create values with A type alias. It will in turn be able to call A.apply(1,2,3).
Use this to show what the repl knows:
scala> $intp.definedTerms
res0: List[$intp.global.TermName] = List($intp)
scala> $intp.definedTypes
res1: List[$intp.global.TypeName] = List($greater)
E.g., you might have:
scala> object X
defined object X
scala> trait X
defined trait X
warning: previously defined object X is not a companion to trait X.
Companions must be defined together; you may wish to use :paste mode for this.
scala> type X = String
defined type alias X
But it doesn't warn on aliasing.
A while back this was asked and answered on the Scala mailing list:
Kevin:
Given some nested structure: List[List[...List[T]]]
what's the best (preferably type-safe) way to flatten it to a List[T]
Jesper:
A combination of implicits and default arguments works:
case class Flat[T, U](fn : T => List[U])
implicit def recFlattenFn[T, U](implicit f : Flat[T, U] = Flat((l : T)
=> List(l))) =
Flat((l : List[T]) => l.flatMap(f.fn))
def recFlatten[T, U](l : List[T])(implicit f : Flat[List[T], U]) = f.fn(l)
Examples:
scala> recFlatten(List(1, 2, 3))
res0: List[Int] = List(1, 2, 3)
scala> recFlatten(List(List(1, 2, 3), List(4, 5)))
res1: List[Int] = List(1, 2, 3, 4, 5)
scala> recFlatten(List(List(List(1, 2, 3), List(4, 5)), List(List(6, 7))))
res2: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
I have been looking at this code for a while. I cannot figure out how it works. There seems to be some recursion involved... Can anybody shed some light? Are there other examples of this pattern and does it have a name?
Oh wow, this is an old one! I'll start by cleaning up the code a bit and pulling it into line with current idiomatic conventions:
case class Flat[T, U](fn: T => List[U])
implicit def recFlattenFn[T, U](
implicit f: Flat[T, U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)
def recFlatten[T, U](xs: List[T3])(implicit f: Flat[List[T], U]) = f fn xs
Then, without further ado, break down the code. First, we have our Flat class:
case class Flat[T, U](fn: T => List[U])
This is nothing more than a named wrapper for the function T => List[U], a function that will build a List[U] when given an instance of type T. Note that T here could also be a List[U], or a U, or a List[List[List[U]]], etc. Normally, such a function could be directly specified as the type of a parameter. But we're going to be using this one in implicits, so the named wrapper avoids any risk of an implicit conflict.
Then, working backwards from recFlatten:
def recFlatten[T, U](xs: List[T])(implicit f: Flat[List[T], U]) = f fn xs
This method will take xs (a List[T]) and convert it to a U. To achieve this, it locates an implicit instance of Flat[T,U] and invokes the enclosed function, fn
Then, the real magic:
implicit def recFlattenFn[T, U](
implicit f: Flat[T, U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)
This satisfies the implicit parameter required by recFlatten, it also takes another implicit paramater. Most crucially:
recFlattenFn can act as its own implicit parameter
it returns a Flat[List[X], X], so recFlattenFn will only be implicitly resolved as a Flat[T,U] if T is a List
the implicit f can fallback to a default value if implicit resolution fails (i.e. T is NOT a List)
Perhaps this is best understood in the context of one of the examples:
recFlatten(List(List(1, 2, 3), List(4, 5)))
The type T is inferred as List[List[Int]]
implicit lookup is attempted for a `Flat[List[List[Int]], U]
this is matched by a recursively defined recFlattenFn
Broadly speaking:
recFlattenFn[List[List[Int]], U] ( f =
recFlattenFn[List[Int], U] ( f =
Flat[Int,U]((xs: T) => List(xs)) //default value
)
)
Note that recFlattenFn will only match an implicit search for a Flat[List[X], X] and the type params [Int,_] fail this match because Int is not a List. This is what triggers the fallback to the default value.
Type inference also works backwards up that structure, resolving the U param at each level of recursion:
recFlattenFn[List[List[Int]], Int] ( f =
recFlattenFn[List[Int], Int] ( f =
Flat[Int,Int]((xs: T) => List(xs)) //default value
)
)
Which is just a nesting of Flat instances, each one (except the innermost) performing a flatMap operation to unroll one level of the nested List structure. The innermost Flat simply wraps all the individual elements back up in a single List.
Q.E.D.
May be a good solution is to try to look at how the types are infered. To avoid ambiguity, let us rename the generics:
case class Flat[T, U](fn : T => List[U])
implicit def recFlattenFn[T2, U2](implicit f : Flat[T2, U2] =
Flat((l : T2) => List(l))) =
Flat((l : List[T2]) => l.flatMap(f.fn))
def recFlatten[T3, U3](l : List[T3])(implicit f : Flat[List[T3], U3]) = f.fn(l)
In the first case, res0, the type of T3 is Int you cannot infer yet the type of U3, but you know that you will need a Flat[List[Int, U3]] object that will be provided implicitly. There is only one "implicit candidate": the result of the recFlattenFn function and its type is Flat[List[T2], List[U2]]. Thus T2 = Int and U2 = U3 (that we still need to infer).
Now, if we weant to be able to use recFlatten we must provide it a parameter f. Here is the trick. You can either use an implicit of type Flat[Int, U2] or the default value of type Int => List[Int]. Let us look about the available implicits. As explained before recFlattenFn can provide a Flat[List[T2], U2] (for a new T2 and U2) object. It does not fit the expected signature of fat this point. Thus, no implicit are a good candidate here and we must use the default argument. As the type of the default argument is Int => List[Int], U2and U3 are Int and there we go.
Hope that this long prose will help. I leave you with the resolution of res1 and res2.
I'm having trouble mapping a function that takes an optional parameter. I get the same type error as I would if the parameter were not optional. Here's a simple illustration:
scala> def multiple(m: Int, n: Int = 2) = m * n
multiple: (m: Int,n: Int)Int
scala> multiple(5)
res0: Int = 10
scala> multiple(5, 7)
res1: Int = 35
scala> (1 to 10).map(multiple)
<console>:7: error: type mismatch;
found : (Int, Int) => Int
required: (Int) => ?
(1 to 10).map(multiple)
Here's one way to make it work, but it requires repeating the default argument, which is a maintenance nightmare:
scala> (1 to 5).map { n => multiple(n, 2) }
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
Is there a better way to do it? More generally, why does a function with an optional parameter seem to have the same type as it would if the parameter was not optional? What is the actual type of multiple?
This seems to work:
(1 to 10).map(multiple(_))
//res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
When used in a situation expecting a function, Scala will "lift" a method to a FunctionN[T1,...,R].
In this situation, because multiple takes 2 parameters, it is lifted effectively as:
(1 to 10).map(new Function2[Int,Int,Int]{ def apply(v1: Int, v2: Int) = multiple(v1, v2) })
Even though the original method has a default argument, FunctionN objects do not. The type error should now be clear here. When multiple(_) is used, this is a call to multiple with a single argument with the second defaulted and so is treated like:
(1 to 10).map(new Function1[Int,Int]{ def apply(v1: Int) = multiple(v1) })
This type checks ok as others have shown.
Note that (multiple _ ) is not the same as multiple(_). The former represents multiple with all arguments wild carded and so is a Function2, whereas the latter is applying multiple to a single wild card argument, causing the other argument to be defaulted at that point, and so is a Function1.
Defaults are implemented at compile time by introducing a new method which returns the default value. Where the defaulted method is called, if arguments are missing, the compiler will add the necessary calls to the extra methods for the default parameters before adding the call to the method itself. This means that the method itself is compiled to code which itself has no knowledge of default parameters. To see this, compile the following sample class:
class Defaults {
def m(a: Int, b: Int = 3) = a * b
def a = m(1)
def b = m(1, 2)
}
then run: javap -c Defaults
For being able to write
scala> (1 to 10).map(multiple)
you can pass a partially applied function
def multiple(m: Int, n: Int) = m * n
val mul2 = multiple(_: Int, 2)
(1 to 10) map mul2
Here's one way to make it work, but it
requires repeating the default
argument, which is a maintenance
nightmare:
Btw this works too:
scala> (1 to 5).map { n => multiple(n) }
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
So you don't need to repeat the default argument either ;) [Scala 2.9.0.RC1]
import java.util.Random
class Kostka {
val rand = new Random(System.currentTimeMillis())
val value: List[Int] = List(rand.nextInt(6+1))
}
object MyRandom {
def Fill[A](n: Int): List[A] = {
if (n<=0) Nil
else {
var lst = List[A]
for (i <- 1 to n){
lst ++= (new Kostka).value
}
return lst
}
}
}
object Gra {
def main(args: Array[String]): Unit = {
println("Podaj liczbe kosci\n")
val kosci: List[Kostka] = MyRandom.Fill[Kostka](10)
// Policzenie wyniku
println("Strzelaj ile razem wypadło\n")
// przyjecie wyniku
// dopisac ile wypadlo czyli wynik
println("Wypadlo: ")
println(kosci.toString)
}
}
And error:
a.scala:10: error: missing arguments for method apply in object List;
follow this method with `_' if you want to treat it as a partially applied function
var lst = List[A]
^
one error found
When I have:
var lst = List[A]()
i got that error:
a.scala:12: error: type mismatch;
found : List[Any]
required: List[A]
lst ++= (new Kostka).value
^
one error found
in your declaration of lst you forgot the parens : lst = List[A]()
In fact, List[A](a,b,c) is a synthatic sugar for List[A].apply(a,b,c), that's why the compiler complained about apply's arguments.
Edit: you can use a ListBuffer instead of your List (in the Fill method, and by the way, the name should be fill(cf http://davetron5000.github.com/scala-style/)) . When you finish the work to do on the buffer, you can call toList, which computes on constant time ;) .
See Aymen's answer for general guidelines. After your update you have the following effect.
Kostka.value has type List[Int]. lst has type List[A]. The result of the append (++) is the least common supertype of List[Int] and List[A] which is List[Any]. But List[Any] is not a subtype of List[A]. That's why you get the type mismatch.
Your Fill method should not be generic in the first place, unless you make Kostka generic, too.
Furthermore, the use of new Kostka combined with the PRNG initialization looks strange as well.
Finally, in Scala 2.8 there is a fill method on the collection companions:
scala> val r = new java.util.Random
r: java.util.Random = java.util.Random#14a616
scala> List.fill(10) {r.nextInt(6+1)}
res4: List[Int] = List(3, 6, 4, 1, 2, 4, 0, 4, 6, 4)
and, unless your dice are 7-sided, you might go for
scala> List.fill(10) {r.nextInt(6) + 1}
res5: List[Int] = List(2, 5, 2, 1, 1, 4, 4, 2, 6, 3)
instead.
compiling this code in scala 2.7.6:
def flatten1(l: List[Any]): List[Any] = l.flatten
i get the error:
no implicit argument matching parameter type (Any) = > Iterable[Any] was found
why?
If you are expecting to be able to "flatten" List(1, 2, List(3,4), 5) into List(1, 2, 3, 4, 5), then you need something like:
implicit def any2iterable[A](a: A) : Iterable[A] = Some(a)
Along with:
val list: List[Iterable[Int]] = List(1, 2, List(3,4), 5) // providing type of list
// causes implicit
// conversion to be invoked
println(list.flatten( itr => itr )) // List(1, 2, 3, 4, 5)
EDIT: the following was in my original answer until the OP clarified his question in a comment on Mitch's answer
What are you expecting to happen when you flatten a List[Int]? Are you expecting the function to sum the Ints in the List? If so, you should be looking at the new aggegation functions in 2.8.x:
val list = List(1, 2, 3)
println( list.sum ) //6
The documentation:
Concatenate the elements of this list. The elements of this list should be a Iterables. Note: The compiler might not be able to infer the type parameter.
Pay close attention to that second sentence. Any cannot be converted to Iterable[Any]. You could have a list of Ints, and that list cannot be flattened since Int is not iterable. And think about it, if you have List[Int], what are you flattening? You need List[B <: Iterable[Any]], because then you would have two dimensions, which can be flattened to one.