The output type still needs to be improved, is there any better suggestion for this example?

for example in Clojure:

user=> (map #(* % 2) (concat [1.1 3] [5 7])) (2.2 6 10 14) 

but in Scala:

 scala> List(1.1,3) ::: List(5, 7) map (_ * 2) <console>:6: error: value * is not a member of AnyVal List(1.1,3) ::: List(5, 7) map (_ * 2) ^ 

Here: get a list of types List, oops then failed. Could any coding more intuitively resemble Clojure above?

+4
source share
5 answers

Here are the separate lists:

 scala> List(1.1,3) res1: List[Double] = List(1.1, 3.0) scala> List(5, 7) res2: List[Int] = List(5, 7) 

The computed minimum upper bound (LUB) of Double and Int needed to capture the type of the new list, which includes the elements of both argument lists passed to ::: , is AnyVal . AnyVal includes a Boolean , for example, so there are no numerical operations.

+4
source

As Randall said, the common supertype of Double and Int is AnyVal, which is what is output in this case. The only way to get your example to work is to add a type parameter to the second list:

 scala> List[Double](1.1,3) ::: List(5, 7) map (_ * 2) :6: error: value * is not a member of AnyVal List[Double](1.1,3) ::: List(5, 7) map (_ * 2) scala> List(1.1,3) ::: List[Double](5, 7) map (_ * 2) res: List[Double] = List(2.2, 6.0, 10.0, 14.0) 

I assume that in the latter case, an implicit conversion from Int to Double is applied. However, I'm not sure why this does not apply when adding a type parameter to the first list.

+2
source

The first list is of type List[Double] due to the extension of the letter type. Scala sees literals and notes that although they are of different types, they can be combined by expanding some of them. If there was no type extension, then the most common AnyVal superclass will be accepted.

 List(1.1 /* Double literal */), 3 /* Int literal */) 

The second list is explicitly List[Int] , although an explicit call to Double will result in a type extension for literals.

 List(5 /* Int literal */, 7 /* Int literal */) 

Now, it’s important to note that type expansion is what happens at compile time. Compiled code will not contain Int 3, only Double 3.0. However, when the list was created, a type extension is not possible, since the stored objects are essentially different.

So, as soon as you separate the two lists, the resulting type will be the superclass Double and Int . Namely, AnyVal . However, as a result of the Java interaction, AnyVal cannot contain useful methods (such as numerical operators).

I am wondering what makes Clojure inside. Does integers convert to double parts when concatenated? Or does it store everything as an Object (e.g., Scala), but has smarter math operators?

+1
source

I see two ways to make it work - brackets for the second part

 scala> List (1.1, 3) ::: (List (5, 7) map (_ * 2)) res6: List[AnyVal] = List(1.1, 3, 10, 14) 

or explicit Duplicates everywhere:

 scala> List (1.1, 3.) ::: List (5., 7.) map (_ * 2) res9: List[Double] = List(2.2, 6.0, 10.0, 14.0) 

which, of course, is semantically different.

0
source

Why not just

 (List(1.1,3) ::: List(5, 7)).asInstanceOf[List[Double]] map (_ * 2) 

?

0
source

Source: https://habr.com/ru/post/1310740/


All Articles