Singleton is a first-class object, is it?

In the Scala book it is stated

A singleton object is more than a holder of static methods, however. It is a first-class object. You can think of a singleton object’s name, therefore, as a “name tag” attached to the object.

I fail to see how it can be the case, one cannot assign a singleton to value, nor send it to a method. Or is it actually possible?

Of course you can.

An object is just that, an object.
Just like 1 or "foo" or 1 :: 2 :: 3 :: Nil, or (x: Int) => x + 1 all are objects.

1 Like

These questions are easily explored interactively in the Scala REPL:

scala 2.13.8> object O
object O

scala 2.13.8> val x = O
val x: O.type = O$@26d24d7a

scala 2.13.8> def foo(x: Any) = x.toString
def foo(x: Any): String

scala 2.13.8> foo(O)
val res0: String = O$@26d24d7a

scala 2.13.8> def bar(x: O.type) = x.toString
def bar(x: O.type): String

scala 2.13.8> bar(O)
val res1: String = O$@26d24d7a
2 Likes

Ok, this clears things up for me. Thank you for both answers!

1 Like

You can see this sample (though in ruby):

> module Mymod
>   def mysize
>     size
>   end
> end
=> :mysize

> word = "Jennifer"
=> "Jennifer"

> word.extend Mymod
=> "Jennifer"

> word.mysize
=> 8

Only the object “word” has this method “mysize”, other string doesn’t have. So it’s called singleton.

1 Like

in Scala 3 one can define an extension method on a singleton type:

extension (s: "Jennifer")
  def mySize = s.size

and in Scala 2:

implicit class MySize(s: "Jennifer") {
  def mySize = s.size
}

But it’s not really the same as your Ruby example, because the Scala versions are resolved at compile-time, whereas the Ruby one is resolved at runtime (right? I don’t really know Ruby). So one can:

scala 2.13.8> "Jennifer".mySize
val res6: Int = 8

scala 2.13.8> val word: "Jennifer" = "Jennifer"
val word: "Jennifer" = Jennifer

scala 2.13.8> "Jennifer".mySize
val res7: Int = 8

But one cannot:

scala 2.13.8> val word = "Jennifer"
val word: String = Jennifer

scala 2.13.8> word.mySize
                   ^
              error: value mySize is not a member of String

Here word is only known to have type String at compile-time, so the extension method isn’t found.

3 Likes

Seth you are right. I think for types stuff the script language would be checking at run time. This is the reason why Spark has Dataset structures for Java/Scala but not for Python/R.