tags:

views:

230

answers:

5

In language like python and ruby to ask the language what index-related methods its string class supports (which methods’ names contain the word “index”) you can do

“”.methods.sort.grep /index/i

And in java

List results = new ArrayList();  
Method[] methods = String.class.getMethods();  
for (int i = 0; i < methods.length; i++) {  
    Method m = methods[i];  
    if (m.getName().toLowerCase().indexOf(“index”) != -1) {  
        results.add(m.getName());  
    }  
}  
String[] names = (String[]) results.toArray();  
Arrays.sort(names);  
return names;  

How would you do the same thing in Scala?

+4  A: 

More or less the same way:

val names = classOf[String].getMethods.toSeq.
    filter(_.getName.toLowerCase().indexOf(“index”) != -1).
    map(_.getName).
    sort(((e1, e2) => (e1 compareTo e2) < 0))

But all on one line.

To make it more readable,

val names = for(val method <- classOf[String].getMethods.toSeq
    if(method.getName.toLowerCase().indexOf("index") != -1))
    yield { method.getName }
val sorted = names.sort(((e1, e2) => (e1 compareTo e2) < 0))
sblundy
A: 

Just using the Java code direct will get you most of the way there, as Scala classes are still JVM ones. You could port the code to Scala pretty easily as well, though, for fun/practice/ease of use in REPL.

pdbartlett
+1  A: 

This is as far as I got:

"".getClass.getMethods.map(_.getName).filter( _.indexOf("in")>=0)  

It's strange Scala array doesn't have sort method.

edit

It would end up like.

"".getClass.getMethods.map(_.getName).toList.sort(_<_).filter(_.indexOf("index")>=0)
OscarRyz
Yes, but list does
sblundy
classOf[String].getMethods.toList.map(_.getName).sort( _ < _ ).filter( _.matches("index(.*)"))This is what i got
skyde
http://paste.pocoo.org/show/216854/
missingfaktor
It says: *warning: there were deprecation warnings; re-run with -deprecation for details* and gives me an empty list
OscarRyz
`scala.Array` are implicitly converted to `scala.collection.mutable.WrappedArray` which has the methods `sortBy` and `sortWith`. See the scaladocs: http://goo.gl/5pJD
missingfaktor
@Rahul does it need an import or something ? http://paste.pocoo.org/show/216856/
OscarRyz
No. I suppose the `sortBy` and `sortWith` methods are new in Scala 2.8.
missingfaktor
maybe , I did it with 2.7.7
OscarRyz
In Scala 2.7.7, you had to do something like this to sort an array: http://pastebin.com/CnsAvU0C
missingfaktor
Oh yeap, I tried that, but I discarded because.. .why?.. I don't remember, Oh yes, because it sorted the array it self instead of returning it and that would imply to create a reference prior to sorting, isn't?
OscarRyz
Yes. Blame the library designers, not me. :P
missingfaktor
+9  A: 

Curious that no one tried a more direct translation:

""
.getClass.getMethods.map(_.getName) // methods
.sorted                             // sort
.filter(_ matches "(?i).*index.*")  // grep /index/i

So, some random thoughts.

  • The difference between "methods" and the hoops above is striking, but no one ever said reflection was Java's strength.

  • I'm hiding something about sorted above: it actually takes an implicit parameter of type Ordering. If I wanted to sort the methods themselves instead of their names, I'd have to provide it.

  • A grep is actually a combination of filter and matches. It's made a bit more complex because of Java's decision to match whole strings even when ^ and $ are not specified. I think it would some sense to have a grep method on Regex, which took Traversable as parameters, but...

So, here's what we could do about it:

implicit def toMethods(obj: AnyRef) = new { 
  def methods = obj.getClass.getMethods.map(_.getName)
}

implicit def toGrep[T <% Traversable[String]](coll: T) = new {
  def grep(pattern: String) = coll filter (pattern.r.findFirstIn(_) != None)
  def grep(pattern: String, flags: String) = {
    val regex = ("(?"+flags+")"+pattern).r
    coll filter (regex.findFirstIn(_) != None)
  }
}

And now this is possible:

"".methods.sorted grep ("index", "i")
Daniel
That's almost what the OP had except for the "sorted" Are yo using 2.8?
OscarRyz
@Oscar Yes, that's 2.8. On Scala 2.7 there is `sort`, but not on all collections.
Daniel
+1  A: 

Now, wait a minute.

I concede Java is verbose compared to Ruby for instance.

But that piece of code shouldn't have been so verbose in first place.

Here's the equivalent :

    Collection<String> mds = new TreeSet<String>();
    for( Method m : "".getClass().getMethods()) {
        if( m.getName().matches(".*index.*")){  mds.add( m.getName() ); }
    }

Which has almost the same number of characters as the marked as correct, Scala version

OscarRyz