7

In Scala, it's possible to check if an item is a member of a Set using "Contains":

object Main extends App {
    val the_set = Set(1, 2, 3, 4)
    if( the_set contains 3 ) println("The set contains 3!")
}

However, I'd like to do a similar comparison but with the item coming first and the set coming at the end (a minor stylistic point, I know). I have some background in Python, so I'm hoping for something along the lines of Python's in operator:

the_set = set([1, 2, 3, 4])
if 3 in the_set: print "The set contains 3!"

Is there any way to do this in Scala? In case you're curious, the reason why I want to do this is to write a concise if statement that compares a value against a long Set that I build. At the same time, I want the item to come first so that the code is easier to read and understand.

Thanks!

bnsmith
  • 1,667
  • 19
  • 30
  • `the_set contains 3` seems pretty concise already. I don't see how `3 in the_set` is any easier to read. – Gangstead Oct 03 '14 at 20:56
  • @Gangstead `in` looks nicer for large inlined Sets (but yeah, the easy solution is to resort to variable definition). – om-nom-nom Oct 03 '14 at 21:04
  • @Gangstead: I agree that variable definition would work. I was just hoping for something a bit nicer for stylistic reasons. (Yes, I'm shallow) – bnsmith Oct 04 '14 at 01:34

2 Answers2

12

Here is one example how to do this:

scala> implicit class InOperation[T](v: T) extends AnyVal { def in(s: Set[T]) = { s contains v } }
defined class InOperation

scala> val x = Set(1,2,3)
x: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> 2 in x
res0: Boolean = true

It uses implicit class to add in method (that takes Set[T]) to arbitrary type T and checks whether object is in the set.

Eugene Loy
  • 12,224
  • 8
  • 53
  • 79
  • Unfortunately it's rendered ambiguous in ScalaTest FlatSpec, fixable by constraining T, or maybe something cleverer. – som-snytt Oct 03 '14 at 20:56
  • 5
    use [Value Classes](http://docs.scala-lang.org/overviews/core/value-classes.html#extension-methods) to remove the runtime overhead. – roterl Oct 04 '14 at 01:24
  • Excellent answer! I've actually used implicit classes before to make some other minor changes to various bits of Scala. Still, I have this feeling that something like the 'in' operator should be built-in as part of the standard library. Do you think that they would accept a patch? – bnsmith Oct 04 '14 at 01:31
  • @bnsmith might be, but I do not think so. Something like this is a nice thing to have in your DSL and Scala allows you to implement it when you need, but Scala's standard library has established way of doing this and I am not quite sure polluting library with another way of doing this is a good idea (plus, I remember standard lib maintainers ranting about need to reduce amount of almost identical methods on collections on some conference). This is arguable, though. – Eugene Loy Oct 04 '14 at 09:20
  • 4
    @bnsmith Both `2 in x` and `x contains 2` are readable so this is a personal style. Scala goes with the later, as it fit better with other functions. It also, IMHO, become more readable when it combined with other functions e.g.: `if (List(1,2,3) map (_ * 2) filter (_ > 2) contains 4)` – roterl Oct 04 '14 at 09:54
  • @roterl: There are a lot of situations where 'contains' is more readable, but it depends on exactly what code you're writing. There are also situations where I think that an 'in' operator would enhance readability, and I'd like to be able to choose one or the other in different situations. I would like to see this feature in the standard library ([and I'm not the only one](http://stackoverflow.com/questions/5927608/in-scala-is-there-a-neat-and-simple-way-to-compare-one-value-with-multiple-valu#comment6831304_5927677)). It's just a question of whether the maintainers of Scala would agree. – bnsmith Oct 05 '14 at 15:19
0

The Scala Set has the method contains. So, you can use it like that:

val x = Set(1,2,3)
x.contains(1) // True

You also can use syntax sugar and call it like that:

x(1) // True
  • 1
    That's not syntax sugar, that's the `apply()` method. The [ScalaDocs page](https://www.scala-lang.org/files/archive/api/current/scala/collection/Set.html#apply(elem:A):Boolean) states, "This method is equivalent to contains." And the OP knows all about the `contains()` method, as clearly mentioned at the top of this 5-year old question. – jwvh Sep 17 '19 at 07:55