Implicit conversion of element to a list with single element

#1

Quite often (or at least in project I’ve been working), I have defined functions that take Lists as argument. In order to make it reusable where I have only one element to work with, I’ve ended up doing method(List(element)). Having a implicit of the following implicit def toList[T](a: T): List[T] = List(a) would then let me use the method as method(element). This would make the project base consistent across

Any thoughts why this may be not a good thing?

#2

I would suggest that it’s not a good idea since it will be very confusing for anyone else who works on your project until they find the implicit definition that allows this to compile.

I don’t want to be judgemental, but I think this is the kind of thing that gives the use of implicits in Scala a bad reputation.

3 Likes
#3

Why not define your methods using varargs?

def method(xs: T*)

Then, you can call it as method(elem).

2 Likes
#4

I think it depends on the project. Is this a pattern you use in other places? Do you tend to have scaladocs for all methods and will be including documentation? If no to both, tread carefully. Could be a bit too black magic. I know its things exactly like this that made me weary of implicits and makes me still try to avoid them.

1 Like
#5

Would this not end in xs being Seq[List[]]? I think what is wanted is xs to always be List[]

#6

If you want to call it with a list, you’ll have to append : _*. Otherwise, yes, it’ll be a Seq[List[_]].

#7

well passing a list would then require the spread opeartor _*

#8

Very true. Sometimes even the good parts of implicits confuse me off :stuck_out_tongue: but thanks

#9

Not sure this is a good idea … implicit conversions between completely interchangeable types (i.e. from Int to BigInt) makes sense. But A and List[A] … I don’t think that’s a design decision that should go into the core language libraries, but should be up to the developer instead. Using varags as @larsrh suggests achieves the same effect.

#10

Those are not “completely interchangeable”. Int to BigInt is fine, but the other direction isn’t.

1 Like
#11

Hello,

Implicit conversion from a commonly used type to another commonly used
type is discouraged because for the potential of unintended application.

Basically, some one tries to call a method, but gets the arguments wrong.
This would be caught as a trivial compile error, except that now the
implicit conversion steps in and makes the method call compile, but fail at
runtime.

This can happen with non-overloaded methods, but if methods are
overloaded, the potential for this to happen it far greater.

Or the other scenario: you actually wanted a particular implicit
conversion to apply, but there is a second implicit conversion in scope
that fits, too, and then it does not compile due to ambiguity.

Implicit conversions are usually fine if you only use them to or from a
type you have created yourself, and if methods that take this type are
clearly distinguishable from methods that don’t.

 Best, Oliver
#12

How about overloading method with a List[A] version and an A version?

Implicit conversions tend to be confusing, keep in mind that they will affect calls to libraries you didn’t write too, and make libCall(a) work only when your implicit is coincidentally in scope, and fail when the code is moved to another scope without your implicit.

#13

To avoid overloading and conversions to common types, they invented the magnet pattern in a bygone era. The magnet pattern has a steampunk aesthetic that may not work for a modern, streamlined API.

1 Like
#14

If your method works on a single element as well, it is easy to call it for a Collection with map.

foo (element)
list.map (foo)

Of course, if the method does not provide one output element per input element, like min, max, sum and the like, where it can still operate on a single element, for example for the above returning just that element - you may either recognize, that the function call is superflous, but it is trivial to call it with an ad hoc collection.

foo (List (element))

Does your case not fit into one of these two categories?

1 Like