This code belongs to a class that extends Directives . Thus, all Directives methods are in scope.
Pathmatcher
There is no / method in String , so an implicit conversion is used to convert String to PathMatcher0 ( PathMatcher[HNil] ) with method / .
The / method takes a PathMatcher and returns a PathMatcher .
Segment is PathMatcher1[String] ( PathMatcher[String :: HNil] ).
The PathMatcher[HNil] method / parameter with the PathMatcher[String :: HNil] returns a PathMatcher[String :: HNil] .
The method / from PathMatcher[String :: HNil] with the parameter PathMatcher[String :: HNil] returns a PathMatcher[String :: String :: HNil] . This is black magic from shapeless . See Heterogeneous Concatenation Lists; it's worth a read.
Directive
So, you call the path method with PathMatcher[String :: String :: HNil] as a parameter. It returns Directive[String :: String :: HNil] .
Then you call the apply method on Directive with Function2[?, ?, ?] ( (a, b) => .. ) as the parameter. There is a corresponding implicit conversion (see Black Magic) for each Directive[A :: B :: C ...] that creates an object using the apply((a: A, b: B, c: C ...) => Route) method apply((a: A, b: B, c: C ...) => Route) .
Syntactic
PathMatcher contains rules for parsing a path. It returns its result as an HList .
The "foo" matcher matches the string and ignores it (returns HNil ).
A / B connector combines 2 sets ( A and B ), separated by the string "/". It combines the results of A and B using HList concatenation.
Segment segment matcher matches the segment of the path and returns it as String :: HNil .
So, "foo" / Segment / Segment matches a path of three segments, ignores the first and returns the remaining segments as String :: String :: HNil .
Then black magic allows you to use Function2[String, String, Route] ( (String, String) => Route ) to process String :: String :: HNil . Without such magic, you would have to use this method: {case a :: b :: HNil => ...} .
Black magic
As @AlexIv noted:
There is an implicit pimpApply conversion for each Directive[A :: B :: C ...] that creates an object with the apply((a: A, b: B, c: C ...) => Route) method apply((a: A, b: B, c: C ...) => Route) .
It accepts ApplyConverter implicitly. An element of type In ApplyConverter is a suitable function (A, B, C ...) => Route for each Directive[A :: B :: C ...] .
It is not possible to create such implicit values ββwithout macros or templates. Therefore, sbt-boilerplate used to generate ApplyConverter . See ApplyConverterInstances.scala .