3

Edit
ok, great feedback here, got me pointed in the right direction. Use case for invoking anonymous closure is in Scalatra routing layer. I have a bunch of routes that are grouped together under various types, in this example, requests common to teams:

class Router {
  type TeamType <: _Controller with _Team

  get("""(schedules|rosters|teamresults|teamstats)/\d{8}""".r) {
    val clazz :: date = captures

    val obj = (clazz match {
      case "schedules" => new RosterController
      case "rosters" => new ScheduleController
    }).asInstanceOf[TeamType]

    obj.show(date)
  }
}

By wrapping the match expression in a a self-invoked anonymous closure, we avoid tacking on "FooController.asInstanceOf[TeamType]" to each matched case, and instead do the type cast on returned instance, maintaining immutability in the process (i.e. could not "val obj = clazz match {...}" followed by type cast as obj has already been val'd)

I believe that this is as short-form as one can get when creating object instances based on string class name. Of course, saying that, there is likely an FP approach that does the job with even greater concision...

Anyway cool stuff, was missing anonymous closures from Groovy, and now I discover Scala has that covered as well ;-)

Original
Not sure how to pull this off in Scala. In Groovy you can both define and invoke an anonymous closure like so:

{String s-> println(s) }("hello")

What is the equivalent in Scala? Also, rather than returning Unit, how would one specify a return type?

Thanks

virtualeyes
  • 11,147
  • 6
  • 56
  • 91
  • It's exceedingly rare the case where a use of `asInstanceOf` is valid, and this doesn't look like one. If type ascription doesn't work here, then the statement is probably incorrect. – Daniel C. Sobral Jan 29 '12 at 20:43
  • Why would it not work? The closure returns an object and asInstanceOf casts to the desired type. I have yet to test, but compiler shows correct type with expected auto-complete methods available. – virtualeyes Jan 29 '12 at 21:03
  • 1
    You got it backwards: `asInstanceOf` *never* results in compile time error -- you are explicitly telling the compiler to trust you even if it thinks you are wrong. If the code is correct, then type ascription suffice. The exception is things like reification, de-serialization and marker traits, plus a few situations where the semantics can guarantee something the types alone don't. – Daniel C. Sobral Jan 30 '12 at 01:58
  • ahh, ok, did not know that, +1. In this case, while not at all type safe, the route itself is not processed unless the regex matches; therefore I know I'm getting a Seq[String] of length 2 to create clazz & date vals. Like xml, possibility of fat fingering the strings is there, but otherwise I can live with it, like the self-invoking object factory ;-) – virtualeyes Jan 30 '12 at 08:37

2 Answers2

8
((s : String) => println(s))("hello")

As for the return type, just let Scala infer it.

scala> ((x : Int) => x < 4)(3)
res0: Boolean = true
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • thanks, parens in place of curlies does the trick. re: return type, the closure will actually contain the result of a match block, which is an object instance whose type I will know; thus the question of how to specify the return type on the closure itself (so I don't have to do, "case x => new Foo with CommonSuperType") – virtualeyes Jan 29 '12 at 12:01
  • @virtualeyes: sorry, I wouldn't know the syntax for an explicit return type on a closure. It's actually quite a while ago that I last did anything in Scala :) – Fred Foo Jan 29 '12 at 12:06
  • 1
    @virtualeyes, the braces would work too, but you would have to call `apply` explicitly. `{ (s: String) => println(s) } apply "hello"`. – missingfaktor Jan 29 '12 at 12:10
  • 2
    @virtualeyes, this is how you specify both argument types and return types: `({ s => println(s) } : String => Unit) apply "hello"`. – missingfaktor Jan 29 '12 at 12:12
  • 2
    You can get an explicit return type by either stating the return type on the last value, e.g. `((s: String) => println(s): Any)("hello")` or by stating the type of the whole function, e.g. `((s => println(s)): (String => Any))("hello")` – Rex Kerr Jan 29 '12 at 12:14
  • +1 @missingfaktor, that will do the trick indeed, solves another issue I was having with generic return type on match block – virtualeyes Jan 29 '12 at 12:16
  • nice +1 @Rex, now to finish it off, how would I specify a generic type? i.e. something like (String => [T <: FooSuperType]) – virtualeyes Jan 29 '12 at 12:27
  • @virtualeyes, you cannot. Function objects cannot have generic type parameters. You'll have to define methods instead. – missingfaktor Jan 29 '12 at 12:41
  • k, am doing so already in my other question where I wrap a match expression in a method with generic return type. Motivation for this question was to wrap the match expression in an anonymous closure with the generic type specified. Basically do the match in single self contained operation vs splitting off into separate method – virtualeyes Jan 29 '12 at 12:47
  • @missingfaktor, actually, while we cannot define a generic type param on Function objects, one can define a type alias that represents the generic type, and thereby do what I want "(String => TypeAlias)". Going to update my answer as this brings together the goal of my 2 SO questions today – virtualeyes Jan 29 '12 at 18:12
1

To add to @larsmans's answer, you can have the Scala compiler infer argument types too. The Scala type inference flows from left to right, so you have to arrange the terms accordingly. We can do this by definiting a pipe-forward operator, |>, such that:

x |> f = f(x)

It's available in Scalaz. If you don't want to use Scalaz, it's not hard to define it yourself.

Usage example:

scala> "hello" |> { s => println(s) }
hello

scala> "hello" |> println
hello

scala> 3 |> { y => y < 4 }
res23: Boolean = true

scala> 3 |> { _ < 4 }
res24: Boolean = true
Community
  • 1
  • 1
missingfaktor
  • 90,905
  • 62
  • 285
  • 365