1

I have a simple code

private def convertFieldsNames (fieldsNames: Array[String]): Array[String] =
  fieldsNames.map(convertFieldName)

private def convertFieldName (fieldName: String): String = s"!!! $fieldName"

val res = convertFieldsNames(Array("123", "456"))
res.map(println)

it works fine, but when i add type conversions functions, which i'm gonna use in other functions

implicit def fromStringToEitherStringOrArray (str: String): Either[String, Array[String]] = Left(str)
implicit def fromArrayToEitherStringOrArray (arr: Array[String]): Either[String, Array[String]] = Right(arr)

i get an error in a line

fieldsNames.map(convertFieldName)

type mismatch;
 found   : String => String
 required: Array[String] => ?

i expected that these conversions will effect only if conversion to Either value is needed, so i cant get why this error bubbles up in a line where no Either type at all

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Dmitry Reutov
  • 2,995
  • 1
  • 5
  • 20

1 Answers1

5

Just too many implicit conversions. Try

private def convertFieldsNames (fieldsNames: Array[String]): Array[String] =
  (fieldsNames: ArrayOps[String]).map(convertFieldName)

Compiler chose wrong conversion Array[String] => Either[String, Array[String]] rather than Array[String] => ArrayOps[String] because .map can be not only Array#map but also Either#map. And type inference/type checking works so that when there is type mismatch error it's too late to come back and choose proper implicit conversion.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • 3
    Can also be solved by not adding this new implicit for two very common base types (Array and String). If you don't scope that carefully, it will break other things all over the place. Why not just have an explicit function call to convert it (or just call `Left` or `Right` directly)? – Thilo Oct 13 '19 at 07:57
  • Ok, i got, so any methods which belongs both to arrays and to Either types will be confused if not using ArrayOps, correct? – Dmitry Reutov Oct 13 '19 at 07:58
  • @Thilo, yes, i can do it, i just wanted to minimize code...And actuially i'm new to scala and just learn what can be done and what not...Another option is make sealed trait with case classes instead of Either...so i just surprised why is such behavour, but now i got - seems that map function is confusing about who called it – Dmitry Reutov Oct 13 '19 at 08:01
  • @DmitryReutov Conversion `implicit def fromArrayToEitherStringOrArray[T] (arr: Array[T]): Either[String, Array[T]] = Right(arr)` seems not to create confusion in this place. – Dmytro Mitin Oct 13 '19 at 08:15
  • @DmytroMitin but it does – Dmitry Reutov Oct 13 '19 at 08:16