skyde
skyde

Reputation: 2956

How to get methods list in scala

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?

Upvotes: 36

Views: 29002

Answers (6)

170730350
170730350

Reputation: 622

You can use the scala REPL prompt. To find list the member methods of a string object, for instance, type "". and then press the TAB key (that's an empty string - or even a non-empty one, if you like, followed by a dot and then press TAB). The REPL will list for you all member methods.

This applies to other variable types as well.

Upvotes: 12

OscarRyz
OscarRyz

Reputation: 199264

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

Upvotes: 3

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297265

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")

Upvotes: 51

OscarRyz
OscarRyz

Reputation: 199264

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)

Upvotes: 4

sblundy
sblundy

Reputation: 61424

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))

Upvotes: 5

pdbartlett
pdbartlett

Reputation: 1519

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.

Upvotes: 1

Related Questions