My instincts are telling me a seasoned Scala programmer will find my code less than optimal. As will no doubt be obvious, I'm a Java guy who has just started in with Scala. Is there a more 'functional' way to accomplish this that I'm missing?
/**
* takes a file object and returns a string representing the fully qualified
* class name represented by that file.
*
* @param file
* @return string representation of the fully qualified class name
*/
def makeFqClassName(file: File): String = {
// pull out the file name - we'll use this for our class name
val fNameNoExtS = FilenameUtils.removeExtension(file.getName)
// extract only the path
val fPathOnlyS =
file.getPath.substring(0, file.getPath.lastIndexOf(File.separator))
// create a list of the path name, minus the delimiter
val fPathDelimList: List[String] = fPathOnlyS.split("/").toList
// truncate the list to include on the class name info
val fqNameList: List[String] =
fPathDelimList.drop(fPathDelimList.lastIndexOf("solutions"))
// convert the list to a string representation of a class name and return
// to caller
fqNameList.mkString(".") + "." + fNameNoExtS
}
Expected input: .java file object where the file name and the class name enclosed in the file are the same.
Sp01.scala
Expected output: fully qualified class name:
solutions.working_with_lists.Sp01
Note that if we were working with one of the problems from another group, the class name would be something like:
solutions.arithmetic.Sp31
The reason for all this is that I'm new to Scala and working my way through the 99 Scala problems set. This method is part of a test runner that trolls through the project files, picks up solution files, then uses reflection to instantiate an instance of the solution class and executes its solver method. This way I can organize the project files in a way that makes sense - in a way that matches the manner in which the problem set is structured - as well as work on whatever problem I want to work on while simultaneously giving me the freedom to reorganize the package structure w/o having to refactor the runner code.
1 Answer 1
My current assumption is that the string returned by file.getPath
is going to look something like ..\solutions\some-parent-dir\some-scala-file.scala
If this is the case then you can try the following function:
def makeFqClassName(file: File): String = {
val fileName :: _ = file.getName.split('.').toList
val upDir :: upUpDir :: _ = file.getParent.split(File.separator(0)).toList.reverse
s"$upUpDir.$upDir.$fileName"
}
I've introduced a smidgen of strange syntax just to show you a possibility. As a way of explaining what is going on, consider that the following are functionally equivalent:
val foo :: _ = List(0, 1, 2, 3)
val goo = List(0, 1, 2, 3).head
From the POV of operations performed they're unequivalent.
foo
is defined from the result of a pattern match that discards the tail of the list. goo
as you know is the result of the invocation of the head
method. (I suppose it could be the case that the compiler is smart enough to translate a pattern match on a list that only takes the head of the list into an invocation of the head method, but lets just ignore that for now :^) And a final example:
val a :: b :: c :: d :: ez = ('a' to 'z').toList
Here a
, b
, c
, and d
are assigned the expected character values and ez
is a list consisting of the characters e
through z
.
If I've misunderstood what your asking for please let me know and I'll update this accordingly.
-
\$\begingroup\$ w000000000t! t/y for this, it was exactly what I was looking for. I'm going to play with this a bit today and see how it jives with the rest of the runner. cheers, mate! \$\endgroup\$snerd– snerd2015年03月02日 16:42:24 +00:00Commented Mar 2, 2015 at 16:42
"solutions"
a special case? \$\endgroup\$