Lisper trend to write one-liners with functions such as map, doseq etc. with big combination chains with many other functions. When doing this in a dynamic type language with no documentation, I guess that's why he calls it magic.
jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE).
iterator.flatMap(entry =>
flatten(ResourcesPlugin.getWorkspace.
getRoot.findMember(entry.getPath)))
But giving informative names to the subexpressions can make things clearer for the next programmer to come along: val sources = jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE)
def workspaceRoot = ResourcesPlugin.getWorkspace.getRoot
def filesOfEntry(entry: Set[File]) =
flatten(workspaceRoot.findMember(entry.getPath)
sources.iterator flatMap filesOfEntry
When to use named vals instead of subexpressions is a matter of style and judgment. From my limited and dated experience, the "one big expression" style is more common and more culturally accepted in Common Lisp than in other languages I've used. You could even call it the norm. In less expressive imperative OO languages, programmers are used to using a plethora of named variables, simply because they usually can't avoid it. In languages like Scala and Clojure, there's bound to be some culture clash when people who are used to more or fewer explicit names have to read each others' code. (function arg arg) ; is the default form
And every form is passed to eval, which calls apply, which calls eval... until you get to a fully expanded form and the final call to eval. (map #'my-func '(1 2 3 4)) ; might eval to
(lambda () (my-func 1) (my-func 2) ...) ; which when passed to apply might result in
(list 1 4 9 16) ; which eval's to itself, a list object... 'list being a primitive
I just describe a theoretical evaluator (#'map is probably not implemented this way in most lisps). You can implement eval/apply in terms of a register machine if that makes you happy. Just read SICP for a good, basic description of one.I appreciate what the Algol-derivative languages have done and what they're useful for; but there are a large class of programming problems where telling the compiler how to solve your problem for you is far more efficient than manipulating the machine with primitives. It all boils down to that eventually and lisp-like languages simply take you to higher levels of abstractions with consistent semantics.