Как получить список методов в Scala - PullRequest
27 голосов
/ 22 мая 2010

В таких языках, как python и ruby, чтобы спросить язык, какие методы, связанные с индексами, поддерживает его строковый класс (имена методов содержат слово «index»), вы можете сделать

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

а в яве

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;  

Как бы вы сделали то же самое в Scala?

Ответы [ 6 ]

44 голосов
/ 22 мая 2010

Любопытно, что никто не пробовал более прямой перевод:

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

Итак, некоторые случайные мысли.

  • Разница между "методами" и обручами выше поразительна, но никто никогда не говорил, что отражение - это сила Java.

  • Я скрываю кое-что о sorted выше: на самом деле он принимает неявный параметр типа Ordering. Если бы я хотел отсортировать сами методы вместо их имен, я должен был бы предоставить это.

  • A grep на самом деле является комбинацией filter и matches. Это немного усложняется из-за решения Java сопоставлять целые строки, даже если ^ и $ не указаны. Я думаю, что имеет смысл иметь метод grep для Regex, который принимает Traversable в качестве параметров, но ...

Итак, вот что мы можем с этим поделать:

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

А теперь это возможно:

"".methods.sorted grep ("index", "i")
10 голосов
/ 19 мая 2015

Вы можете использовать приглашение scala REPL. Чтобы найти список методов-членов строкового объекта, например, введите "". и затем нажмите клавишу TAB (это пустая строка - или даже непустая строка, если хотите, затем точка и затем нажмите TAB) REPL перечислит для вас все методы-члены.

Это относится и к другим типам переменных.

5 голосов
/ 22 мая 2010

Более или менее так же:

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

Но все в одной строке.

Чтобы сделать его более читабельным,

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))
3 голосов
/ 22 мая 2010

Теперь, подождите минуту.

Я допускаю, что Java многословна по сравнению, например, с Ruby.

Но этот кусок кода не должен был быть таким многословным.

Вот эквивалент:

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

Который имеет почти такое же количество символов, как помечено как правильное, версия Scala

2 голосов
/ 22 мая 2010

Насколько я понял:

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

Странно, у массива Scala нет метода сортировки.

edit

Это закончилось бы как.

"".getClass.getMethods.map(_.getName).toList.sort(_<_).filter(_.indexOf("index")>=0)
1 голос
/ 22 мая 2010

Простое использование Java-кода поможет вам в этом, поскольку классы Scala все еще являются классами JVM.Вы также можете довольно легко перенести код в Scala для развлечения / практики / простоты использования в REPL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...