Searching the Scala documentation for #::
Asked Answered
E

5

19

I am trying to find the documentation for the Scala operator method #::. I believe that it is defined in the Stream class because of an example I found that uses it.

My question is not particular to this method (although I would like to know where the docs are), but how to search the Scala docs in general. I tried entering #:: in the search box in the upper left of the documentation page (2.8.1), but found nothing.

Etesian answered 29/12, 2010 at 12:3 Comment(0)
P
18

I suggest using the Reference Index - it's designed specifically to look for any kind of symbol (class, traits, methods, vals, vars) regardless of it's hierarchical position - contrasting with the Scaladoc's left index which doesn't show inner classes, traits or objects.

Unfortunately it's only available in the nightly. You can see the whole thing at nightly Scaladoc. Notice the upper box in the left frame, above the index.

Hope it will be bundled with Scala 2.9.0.

Edit As of 2.9.0, the reference index started to be bundle with Scaladoc. No need to go to the nightly docs now.

Pheidippides answered 29/12, 2010 at 12:42 Comment(5)
@Pheidippides only suggestion I could make is that they start using the same feature (an alphabet to select from at the top of the sidebar) in the stable docs as well.Trabzon
@pedrofurla: a couple of possible improvements to vscaladoc: 1) show inner classes in the sidebar. 2) in each class, add a list of methods that can be called as though they were class members, based on implicit conversions. Be sure to show which class or conversion is required to get that method, and make sure it's capable enough to detect the ConsWrapper conversion which is a bit unusual becuase it's a by-name conversion.Cassidycassie
@pedrofurla: I thought vscaladoc was what you used these days to generate the standard library documentation. Whatever -- the standard library documentation should have these features.Cassidycassie
@Ken, check the links provided in my answer for no. 1. For no. 2, this is a pretty hard to achieve goal, nevertheless very useful.Pheidippides
@pedrofurla: I don't see Predef.<:< in the side bar.Cassidycassie
C
12

As others have already mentioned, #:: is defined on scala.collection.immutable.Stream.ConsWrapper. I just wanted to take a minute to elaborate on why that is.

In general, to call an operator on an object, that object needs to exist. However, the idea with a Stream is the tail of the stream is not evaluated until it needs to be. So consider the following stream:

def fibs(a:Int,b:Int):Stream[Int] = a #:: fibs(b,a+b)

Ordinarily, we would need to evaluate the recursive fibs call so that we could call the #:: operator on it. This would lead to runaway recursion. This is NOT what we want. What we want is for the reciever to be a by-name Stream. Hence the ConsWrapper:

The constructor for ConsWrapper is class ConsWrapper[T](tail: => Stream[T]) taking a by-name Stream, and it's created through an implicit conversion Stream.consWrapper[T](stream: => Stream[T]), which also takes a by-name Stream.

Hence, we have performed an implicit conversion on the result of a function that has not yet been called, and we have mimiced the effect of calling #:: with a by-name this reference.

Cassidycassie answered 29/12, 2010 at 16:30 Comment(0)
O
5

The problem here is that the scaladoc search does not allow you to look for an inner class/object (i.e. whose parent is not a package). The declaration of #:: is either Stream.#:: or Stream.ConsWrapper.#:::

object Stream { 
  //STUFF
  /** An extractor that allows to pattern match streams with `#::`.
   */
  object #:: {
    def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] = 
      if (xs.isEmpty) None
      else Some((xs.head, xs.tail))
  }
  class ConsWrapper[A](tl: => Stream[A]) {
    def #::(hd: A): Stream[A] = new Stream.Cons(hd, tl)
    def #:::(prefix: Stream[A]): Stream[A] = prefix append tl
  }
  //MORE STUFF
}

You could request this as an RFE to the scaladoc tool in trac.

In IntelliJ IDEA's scala plugin, you could have used symbol lookup (CTRL+ ALT+ SHIFT+ N) and typed #:: and this would have brought up both declarations of #:: immediately.

Once answered 29/12, 2010 at 12:21 Comment(4)
Except that Stream.#:: is wrong. The OP is asking about Stream.ConsWrapper.#::.Mcmorris
True - answer still valid, thoughOnce
Thanks. Actually, I'm not sure which one (Stream.#:: or Stream.ConsWrapper.#::) is executing. I'll need to study the code.Etesian
@Ralph: Stream.#:: is an object used for pattern matching. It's not what's being called. You're calling Stream.ConsWrapper.#::, as I have explained in my answer.Cassidycassie
V
2

That particular method is defined in a nested class inside of Stream, called scala.collection.immutable.Stream.ConsWrapper.

And no, I have absolutely no idea how one would go about finding it. I only stumbled across it by accident. And even though I knew where to find it now, when I wanted to post the link to the class here in my answer, I still couldn't find it on the first (and even second and third) try.

Vacillatory answered 29/12, 2010 at 12:28 Comment(0)
U
2

Well, normally, if we see

foo bar baz 

then bar is a method, defined for foo, so we first look in the class/object - definition of foo, then the inheritance/trait tree upwards (+ in implicit conversions to and from foo, in the current file, and in (directly) included files).

Except 'bar' ends in a colon, which is the case here. Then it is to be read in reverse order -

foo bar: baz 

is not

foo.bar: (baz)

, but

baz.bar: (foo) 

So we have to look up in the way described above, but not for foo, but for baz.

Underwater answered 30/12, 2010 at 2:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.