James Iry
Posts: 85
Nickname: jiry
Registered: Nov, 2007
|
|
Re: What Do You Consider "Readable" Code?
|
Posted: Mar 19, 2009 7:39 PM
|
|
> I'll make my point like this - let's go a step further. > Why call another method, create a list etc? Let's > introduce a list comprehension too:
But note that a list comprehension is a special purpose tool - it only works with lists or, perhaps in some languages, collections. Closures and pattern matching, in contrast, are general purpose tools - they work with all manner of things.
It's worth mentioning that there is a generalization of a list comprehension called a monad comprehension and that Scala's "for" and C#'s LINQ are based on the idea. I think monad comprehensions rise to the level of being worthwhile more than list comprehensions do. Other languages may choose differently.
> List<Person> minors = [p || Person p <- people, p.age() < > 18];
In this case, your comprehension is more verbose than the straight method call which you saw in GScript. In Scala its
val minors = people filter (_.age < 18)
In a hypothetical closures based Java API it would be
import static Collections.filter; List<Person> minors = filter(people, {p => p.age() < 18})
> My question is when do we stop? I like concise code too
Language design is about trade-offs. You have to ask if benefit of something outweighs the cost of additional complexity. Scripting languages tend to include a lot of additional complexity in order to get syntactically nice lists and maps and such. Scala aims instead for relatively little specialized syntax (tuples are the only data structure that get special syntax) and lots of library support. In Scala when you see Map("one" -> 1, "two" -> 2) there's nothing in the syntax that's specialized for maps. If you wanted to use the same arrow notation for your own treemap, you would be free to develop something that was usable as TreeMap("one" -> 1, "two" -> 2).
> reason I asked why aren't libraries enough? From your > responses its clear that libraries aren't always enough or > ideal. But we have to draw a line somewhere.
Libraries can get you awfully far once the language has a few key features. Lambdas are a minimum.
> ** GScript code reads better because of "where" method. It > feels more generic than partition, select, find ...
I do want to emphasize that "partition" is an ordinary method on an ordinary class. Nothing special about it. But to answer your comment "partition" does something different from "where" - it splits a collection into two based on a predicate. The equivalent of GScript's "where" in Scala's library is "filter." Still, Scala is flexible enough to let you add a "where" method if you preferred it. Here's an actual session with the REPL where I add it. I've bolded what I typed, everything else is computer's response.
scala> implicit def iterableWithWhere[T](iterable : Iterable[T]) = new { | def where(p : T => Boolean) = iterable filter p | } iterableWithWhere: [T](Iterable[T])java.lang.Object{def where((T) => Boolean): Iterable[T]}
scala> case class Person(name : String, age : Int) defined class Person
scala> val people = List(Person("Bob", 28), Person("George", 17), Person("Sarah", 12)) people: List[Person] = List(Person(Bob,28), Person(George,17), Person(Sarah,12))
scala> val minors = people where (_.age < 18) minors: Iterable[Person] = List(Person(George,17), Person(Sarah,12))
This might look like "monkeypatching" but the scope of the additional method is statically defined and the compiler will warn you about ambiguities.
|
|