challenge メソッド数の多い組み込みクラスを列挙

言語処理系に組み込みの全クラスについて、それぞれに定義されているメソッド数が多い順に上位10番目までのクラス名とメソッド数を出力するコードを書いてください。全クラス数も示してください。

なお、「組み込み」「クラス」「メソッド」などについては、必要であれば、その言語にふさわしい対象や機能に適宜読み替えてください。(たとえば、組み込み→標準添付、クラス→型・モジュール・パッケージ…、メソッド→関数・プロシージャ…といった具合に)

ああ…、ごめんなさい。大事な但し書きを忘れました。orz

可能であれば、継承したメソッド数は含まずに、そのクラスで定義(再定義も含む)されたメソッド数のみをカウントしてください。

言語処理系ごとに、普段目にするクラス群において、最大、どのくらいのメソッドを定義したクラスが存在するのか(心情的に許容されるのか)を知りたかったのですが、継承されたメソッドを含めてしまうと、階層が深くなるほどメソッド数が多くなる当たり前の傾向を見るだけになってしまうので…

おなじ理由で、メタクラスを持たない言語では、static メソッドについてもカウントから除いてください。もし数える場合でも別物としてカウントしてください(SomeClass -> 15, SomeClass static -> 5 というように)。

おそらく、わざわざ static メソッドだけ個別にカウントせずとも、省いてしまっても結果には影響しないだろうと思われます(static メソッド数が上位10番に入るほど多く定義されているクラスは存在しないと予想されるので)。

Posted feedbacks - Nested

Flatten Hidden

「言語処理系に組み込みの全クラス」が、.NET Frameworkのどこまでに該当するかが分からなかったので、そのプロジェクトで参照されている全クラスを対象としました。

以下の実行結果は、普通にWindowsApplicationのプロジェクトを作ると参照されているものだけが対象になっています。参照するアセンブリを増やせば、結果が変わってくると思います。

以下、実行結果:

System.Convert: 314
System.Reflection.Emit.TypeBuilder: 170
System.Runtime.InteropServices.Marshal: 156
System.Type: 146
System.Reflection.Emit.EnumBuilder: 135
System.Net.Sockets.Socket: 135
System.Reflection.Emit.GenericTypeParameterBuilder: 134
System.RuntimeType: 131
System.ReflectionOnlyType: 131
System.Reflection.TypeDelegator: 129
System.Reflection.Emit.SymbolType: 129
System.Reflection.Emit.TypeBuilderInstantiation: 129
全クラス数: 4295
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Doukaku270 {
    class Program {
        static void Main(string[] args) {
            int classCount = 0;
            SortedDictionary<int, List<Type>> result = new SortedDictionary<int, List<Type>>();
            foreach (AssemblyName name in typeof(Program).Assembly.GetReferencedAssemblies()) {
                Assembly asm = Assembly.Load(name);
                if (asm != null) {
                    foreach (Type type in asm.GetTypes()) {
                        int methodCount = type.GetMethods().Length;
                        if (!result.ContainsKey(methodCount)) {
                            result[methodCount] = new List<Type>();
                        }
                        result[methodCount].Add(type);
                        classCount++;
                    }
                }
            }

            List<int> keyList = new List<int>(result.Keys);
            keyList.Reverse();
            int count = 0;
            foreach (int key in keyList.GetRange(0, 10)) {
                foreach (Type type in result[key]) {
                    Console.WriteLine("{0}: {1}", type.FullName, key);
                    count++;
                }
                if (count >= 10)
                    break;
            }
            Console.WriteLine("全クラス数: {0}", classCount);
        }
    }
}
java.homeのrt.jar (最も基本的なライブラリ) に含まれる java か javax で始まるパッケージに属するクラスを対象としました。
メソッド数はそのクラスが持つpublicメソッドの数で、継承されたものを含みます。

結果は以下の通り
javax.swing.JMenuItem                           : 407
javax.swing.JPasswordField                      : 407
javax.swing.text.html.FrameView$FrameEditorPane : 408
javax.swing.JEditorPane                         : 408
javax.swing.JCheckBoxMenuItem                   : 409
javax.swing.JFormattedTextField                 : 412
javax.swing.JTextPane                           : 422
javax.swing.JMenu                               : 433
javax.swing.JTree                               : 437
javax.swing.JTable                              : 456
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package doukaku;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.*;

public class HugeClasses {
    public static void main(String[] args) throws Exception {
        final File rt = new File(System.getProperty("java.home"), "lib/rt.jar");

        if (!rt.exists()) {
            System.err.println("rt.jarが見つかりません。");
            return;
        }

        final int topN = 10;
        NavigableSet<ClassHolder> sortSet = new TreeSet<ClassHolder>();

        for (JarEntry entry : Collections.list(new JarFile(rt).entries())) {
            String name = entry.getName();
            if ((name.startsWith("java/") || name.startsWith("javax/"))
                    && name.endsWith(".class")) {

                String className = name.substring(0, name.length() - 6)
                        .replace('/', '.');
                Class<?> clazz = Class.forName(className);
                sortSet.add(new ClassHolder(clazz));
                if (sortSet.size() > topN) sortSet.pollFirst();
            }
        }

        for (ClassHolder classHolder : sortSet) {
            System.out.printf("%-60s: %d%n", classHolder.className,
                    classHolder.methodCount);
        }
    }

    private static class ClassHolder implements Comparable<ClassHolder> {
        private static final AtomicInteger idCounter = new AtomicInteger(0);
        private String className;
        private int methodCount;
        private int id;

        ClassHolder(Class<?> clazz) {
            id = idCounter.getAndIncrement();
            className = clazz.getName();
            methodCount = clazz.getMethods().length;
        }

        @Override
        public int compareTo(ClassHolder o) {
            return methodCount != o.methodCount ?
                    methodCount - o.methodCount
                    : id - o.id;
        }
    }
}
私もhoriuchiさんと同じく、プロジェクトの参照しているアセンブリのみ対象として実施しました。
ワンライナー狙って見ましたが、やりすぎ感があったので、途中コードもコメントで残しておきました。
horiuchiさんとの差異については以下の部分かな?とか。

■コード
BindingFlagを使ってprivateも参照してる
# このフラグで合ってるはずですが・・・

■環境
Visual Studio 2010beta
.NET Framework 4.0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//全クラス数 : 3634
//System.Linq.Expressions.Expression : 387
//System.Convert : 313
//System.Linq.ParallelEnumerable : 210
//System.Runtime.InteropServices.Marshal : 203
//System.Linq.Enumerable : 203
//Microsoft.Win32.Win32Native : 199
//System.Linq.Expressions.Strings : 180
//System.Linq.Expressions.Error : 146
//System.Linq.Queryable : 124
//System.Console : 117

using System;
using System.Linq;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        //var classTypes = typeof(Program).Assembly.GetReferencedAssemblies().Select(assemblyName => Assembly.Load(assemblyName).GetTypes()).SelectMany(classType => classType);
        //var classCountDict = classTypes.ToDictionary(classType => classType, classType => classType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Count());
        //var result = classCountDict.OrderByDescending(pair => pair.Value).Take(10);
        var classCountDict = typeof(Program).Assembly.GetReferencedAssemblies().Select(assemblyName => Assembly.Load(assemblyName).GetTypes()).SelectMany(classType => classType).ToDictionary(classType => classType, classType => classType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Count());
        Console.WriteLine("全クラス数 : {0}", classCountDict.Keys.Count());
        foreach (var obj in classCountDict.OrderByDescending(pair => pair.Value).Take(10))
        {
            Console.WriteLine("{0} : {1}", obj.Key, obj.Value);
        }
        Console.ReadLine();
    }
}

Squeak Smalltalk で。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
| clsCount result |
clsCount := 0.
result := Dictionary new.
SystemNavigation default allBehaviorsDo: [:class |
    clsCount := clsCount + 1.
    result at: class put: class selectors size].
^{#全クラス数 -> clsCount. (result associations sort: [:a :b | a value > b value]) first: 10}


"=> {#全クラス数 -> 4384. {
    Morph -> 1165. 
    Player -> 620. 
    PasteUpMorph -> 469. 
    Preferences class -> 450. 
    Object -> 436. 
    ParagraphEditor -> 284. 
    SyntaxMorph -> 250. 
    Behavior -> 243. 
    ScriptLoader -> 236. 
    String -> 233
}} "

何もuseしない場合のpackageとそこに定義されてるsubをSTASHから拾ってきて数えてます。

手元の環境(v5.10.0 built for MSWin32-x86-multi-thread) では

main::Win32 --- 21
main::version --- 16
Tie::Hash::NamedCapture --- 9
main::mro --- 9
main::utf8 --- 8
main::Internals --- 6
main::re --- 4
main::UNIVERSAL --- 4
PerlIO::Layer --- 2
main::DynaLoader --- 1

という結果になりました

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
my %cnt;
my $top = '*main::';
count_subs($top,\%cnt);
--$cnt{$top}; # sub count_subs の分を差し引く
my $i=0;
$\="\n";
print for map { "@{[substr($_->[0],1,-2)]} --- $_->[1]" }
grep { ++$i <= 10 }
sort {$b->[1] <=> $a->[1]}
map { [$_, $cnt{$_}] } keys %cnt;

my %counted;
sub count_subs
{
  my ($mod, $cnt) = @_;
  return if exists $cnt->{$mod};
  $cnt->{$mod} = 0;
  return if !defined %{$mod};
  while (my ($k,$v) = each %{$mod}) {
    if ( substr($k, -2) eq '::' ) {
      count_subs($v, \%cnt);
    }
    elsif (defined &{$v} && !exists $counted{$v}) {
      ++$cnt->{$mod};
      $counted{$v}=undef;
    }
  }
}
もっといい方法がありそうな気がします。

$ gosh doukaku270.scm
<top>      : 36
<class>    : 17
<generic>  :  7
<list>     :  7
<integer>  :  7
<method>   :  5
<symbol>   :  5
<string>   :  5
<regmatch> :  4
<object>   :  4
$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(use srfi-1)

(define *builtin-identifiers*
  (let1 module (find-module 'gauche)
    (filter-map
      (cut global-variable-ref module <> #f)
      (remove (cut eq? '~$ <>)
              (hash-table-map (module-table module)
                              (lambda (sym _) sym))))))

(define *builtin-classes*
  (filter (cut is-a? <> <class>) *builtin-identifiers*))

(define *builtin-generic-functions*
  (filter (cut is-a? <> <generic>) *builtin-identifiers*))

(define (direct-methods class)
  (filter-map (lambda (method)
                (let1 specs (slot-ref method 'specializers)
                  (and (member class specs)
                       method)))
              (append-map (cut slot-ref <> 'methods)
                          *builtin-generic-functions*)))

(define (main args)
  (for-each
    (lambda (x) (format #t "~10a : ~2d~%" (class-name (car x)) (cdr x)))
    (take (sort-by (map (lambda (class)
                          (cons class (length (direct-methods class))))
                        *builtin-classes*)
                   cdr
                   >)
          10))
  0)

パッケージごとに、関数定義をもつシンボルの個数を数えました。他のパッケージから継承したシンボルは含めていません。

CLISP 2.38 で動かしてみた結果:

SYSTEM          : 1394
COMMON-LISP     : 755
CS-COMMON-LISP  : 752
CLOS            : 647
EXT             : 503
POSIX           : 147
FFI             : 127
I18N            : 63
GRAY            : 31
EXPORTING       : 28
1
2
3
4
5
6
(loop for p in (list-all-packages) collect
  (list (package-name p)
        (loop for s being each present-symbol in p count (fboundp s)))
  into x
  finally (format t "~10{~{~15A : ~A~}~%~}~%"
                  (sort x #'> :key #'cadr)))
組み込みのクラスを「ブートストラップクラス」と解釈しました(ブートストラップクラスはシステムプロパティ sun.boot.class.path で示されます)。クラスパスで示される Jar ファイルからクラス名を取り出し、リフレクションでメソッド数を数えています。

Mac OS X 10.4.11 の java 1.5.0_19 で実行した結果は以下です。

com.sun.corba.se.impl.logging.ORBUtilSystemException -> 1248
com.sun.corba.se.impl.logging.OMGSystemException -> 524
com.sun.corba.se.impl.logging.POASystemException -> 284
java.awt.Component -> 277
org.w3c.dom.css.CSS2Properties -> 244
com.sun.rowset.CachedRowSetImpl -> 211
com.sun.rowset.internal.SyncResolverImpl -> 206
com.sun.tools.example.debug.expr.ExpressionParser -> 206
com.sun.org.apache.bcel.internal.generic.EmptyVisitor -> 180
com.sun.org.apache.bcel.internal.generic.Visitor -> 180

ちなみに、static メソッドのみを取り出した場合は以下です。

java.util.Arrays static -> 114
java.nio.Bits static -> 114
apple.laf.AquaImageFactory static -> 98
java.lang.Character static -> 80
sun.awt.FontConfiguration static -> 79
com.sun.security.sasl.digest.DigestMD5Base static -> 70
com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary static -> 69
java.net.URI static -> 66
apple.laf.AquaSliderUI static -> 65
com.sun.tools.corba.se.idl.ParseException static -> 63
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.io.*;
import java.lang.reflect.*;
import java.util.Map.Entry;
import java.util.jar.*;
import java.util.*;

public class Sample {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Map<String, Integer> classMap = new HashMap<String, Integer>();
        for (String jarName : System.getProperty("sun.boot.class.path").split(System.getProperty("path.separator"))) {
            File jar = new File(jarName);
            if (jar.isFile()) {
                JarFile jf = new JarFile(jar);
                for (Enumeration<JarEntry> i = jf.entries(); i.hasMoreElements();) {
                    String entry = i.nextElement().getName();
                    if (entry.endsWith(".class")) {
                        String className = entry.substring(0, entry.length() - 6).replaceAll("/", ".");
                        Class<?> cc = Class.forName(className, false, null);
                        int staticCount = 0, memberCount = 0;
                        for (Method m : cc.getDeclaredMethods()) {
                            if ((m.getModifiers() & Modifier.STATIC) != 0)
                                staticCount++;
                            else 
                                memberCount++;
                        }
                        classMap.put(className, memberCount);
                        classMap.put(className + " static", staticCount);
                    }
                }
            }
        }
        Map.Entry<String, Integer>[] a = classMap.entrySet().toArray(new Map.Entry[0]);
        Arrays.sort(a, new Comparator<Map.Entry<String, Integer>> () {
            public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
                return -o1.getValue().compareTo(o2.getValue());
            }    
        });
        for (int i = 0; i < 10; i++) {
            System.out.printf("%s -> %d%n", a[i].getKey(), a[i].getValue());        
        }
    }

}
Fan 1.0.44で。
Podはnamespaceのようなもの、Typeはクラスのようなものです。
継承したメソッドを判別する綺麗な方法はないようで、いったん文字列に変換して比較する、という回りくどい事をやってます。
出力行数は十分小さいと仮定してエラーチェック手抜きしてます。

実行結果
% fan Doukaku270.fan
web::WebOutStream, 95
compiler::Parser, 84
compiler::CodeAsm, 75
compiler::CheckErrors, 74
sys::Buf, 71
sys::List, 65
sys::Str, 65
compiler::CType, 62
testSys::DateTimeTest, 54
testSys::StrTest, 52
testSys::UriTest, 52
%
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Doukaku270
{
    static const Int numClassesToDisplay := 10

    Void main() {
        Int:Type[] counts := [:] // 連想配列: メソッド数 -> クラスのリスト

        // countsを埋める
        Pod.list.each |Pod pod| {
            pod.types.each |Type type| {
                numMethods := type.methods.findAll {
                    // 継承したものでなく、このクラスで実装されたものを選ぶ
                    it.toStr.startsWith("${type.toStr}.")
                }.size
                counts[numMethods] = counts.get(numMethods, [,]).add(type)
            }
        }

        numPrints := 0  // 出力済みの行数
        keys := counts.keys.sortr
        while (numPrints < numClassesToDisplay) {
            numMethods := keys.removeAt(0)
            counts[numMethods].each |Type type| {
                echo("${type.toStr}, $numMethods")
            }
            numPrints += counts[numMethods].size
        }
    }
}
 Rubyはこんな感じでした。

total:  135
String: 369
Array:  355
File:   349
IO:     340
Hash:   334
Class:  332
Module: 331
Fixnum: 329
Bignum: 327
File::Stat:     322
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
list = []
ObjectSpace.each_object(Class) do |klass|
  info = {
    :name => klass.name,
    :methods => {
      :instance_methods => {
        :public => klass.public_instance_methods,
        :protected => klass.protected_instance_methods,
        :private => klass.private_instance_methods
      },
      :class_methods => {
        :public => klass.class.public_instance_methods,
        :protected => klass.class.protected_instance_methods,
        :private => klass.class.private_instance_methods
      }
    }
  }
  info.instance_eval do |obj|
    def name
      self[:name]
    end
    def method_count
      [:instance_methods, :class_methods].inject(0) do |c, t|
        c + [:public, :protected, :private].inject(0) do |r, s|
          r + self[:methods][t][s].size
        end
      end
    end
  end
  list << info
end
puts "total:\t#{list.size}"
list.sort { |a,b| b.method_count <=> a.method_count }[0..9].each do |e|
  puts "#{e.name}:\t#{e.method_count}"
end
 scala-library.jarとscala-swing.jarについて調べてみました。Java側のリフレクションを使って調べているので,ソースコード上の値とはずれがあります。

total:  3173
scala.swing.Key:        206
scala.collection.jcl.Buffer$Projection: 166
scala.collection.jcl.ArrayList: 158
scala.collection.jcl.LinkedList:        158
scala.collection.jcl.Buffer$$anon$2:    155
scala.collection.jcl.SortedMap$$anon$1: 153
scala.collection.jcl.TreeMap:   153
scala.collection.jcl.SortedMap$$anon$2: 151
scala.collection.jcl.Buffer$Range:      150
scala.collection.jcl.TreeSet:   146
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import scala.collection.jcl.Conversions
import java.io.File
import java.util.Collections
import java.util.jar.{JarEntry,JarFile}

object MethodCount {
    def getClassInformations(l:List[String]):List[Pair[String,Int]] = {
        def getInfo(n:String):Pair[String,Int] =
            try { (n, Class.forName(n).getDeclaredMethods.size) } catch { case _ => (n, -1) }
        def isClass(n:String):Boolean = n.endsWith(".class") && !n.matches("\\$\\$anonfun\\$")
        def getClassName(n:String):String = n.substring(0, n.length - 6).replace('/', '.')
        def getJarEntries(f:File):List[JarEntry] =
            Conversions.convertList(Collections.list((new JarFile(f)).entries)).toList
        def getFiles(l:List[String]):List[File] =
            l.map(new File(System.getProperty("scala.home"), _)).filter(_.exists)
        getFiles(l).map(getJarEntries).flatten(identity(_)).map(_.getName).filter(isClass).map(getClassName).map(getInfo)
    }
    def main(args:Array[String]):Unit = {
        val l:List[Pair[String,Int]] = getClassInformations(List("lib/scala-library.jar", "lib/scala-swing.jar"))
        Console.printf("total:\t%d\n", l.size)
        l.sort(_._2 > _._2).take(10).foreach((i) => Console.printf("%s:\t%d\n", i._1, i._2))
    }
}

ghc 限定.Preludeからエクスポートされているclassは15個しかないので全部列挙 (10個に限定するなら,コード中のコメントアウトされている部分をuncommentする) 括弧内がメソッドの数

実行例: *Main> :main Floating (18) RealFloat (14) Enum (8) Ord (7) Num (7) Integral (7) RealFrac (5) Read (5) Monad (4) Show (3) Fractional (3) Eq (2) Bounded (2) Real (1) Functor (1) ... number of classes : 15

System Message: WARNING/2 (<string>, line 5); backlink

Inline emphasis start-string without end-string.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Data.List
import Data.Ord
import System.Process

data ClassInfo = CI { className :: String, numberOfMethods :: Int }

main = do { res <- readProcess "ghc" ["-e",":browse Prelude"] []
          ; let cis = classInfos [] $ lines res
          ; let n = length cis
          ; putStr $ unlines {- $ take 10 -}
          $ map showClassInfo $ sortBy (flip (comparing numberOfMethods)) cis
          ; putStr $ unlines ["...","number of classes : "++show n]
          }

showClassInfo :: ClassInfo -> String
showClassInfo (CI name n) = name ++ " (" ++ show n ++ ")"

classInfos :: [ClassInfo] -> [String] -> [ClassInfo]
classInfos a [] = a
classInfos a (l:ls)
 | head lw /= "class" = classInfos a ls
 | otherwise = classInfos (ci:a) ls''
   where 
     lw = words l
     ci = CI name (if null ls' then 1 else length ls')
     (ls',ls'') = break (not . ("  " `isPrefixOf`)) ls
     name = case break ("=>"==) lw of
       (_,[])  -> head $ tail lw
       (_,lw') -> head $ tail lw'
すみません。プレビューせずに、形式をまちがえてupしたので実行例がこわれてしまいました。orz  実行例だけupします

*Main> :main
Floating (18)
RealFloat (14)
Enum (8)
Ord (7)
Num (7)
Integral (7)
RealFrac (5)
Read (5)
Monad (4)
Show (3)
Fractional (3)
Eq (2)
Bounded (2)
Real (1)
Functor (1)
...
number of classes : 15

Squirrel3.0で。
「継承したメソッド数は含まずに」が出来なかったのでカッとなって横に伸ばした。
反省はしていない。

結果:
roottable  :  56
blob       :  13
file       :  10
stream     :   9
regexp     :   5

ええ、別に継承考慮しなくても結果変わらないんです。
あまりにさみしいので、グローバル関数のようなものをroottableとしてカウントしています。
自分自身が含まれてしまわないようにlocal tab = のような書き方になっています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
local tab =
{
    function count_function(cla)
    {
        local ret = 0;
        foreach(k,v in cla) if (type(v) == "function") ret++;
        return ret;
    }

    function main()
    {
        local result = [{ key="roottable", val=count_function(getroottable()) }];
        foreach(k,v in getroottable()) if (type(v)=="class") result.append({ key=k, val=count_function(v) });
        result.sort(@(a, b) b.val-a.val);
        for(local i=0; i<10 && i<result.len(); i++) print(format("%-10s : %3d\n", result[i].key, result[i].val));
    }
}
tab.main();

>ええ、別に継承考慮しなくても結果変わらないんです。 と思いましたが、fileとblobはstreamを継承してるっぽいですorz

結果

Only regular methods: unicode(39), str(37), set(16), dict(15), file(15), list(9), frozenset(7), complex(1), enumerate(1), reversed(1)

Including special methods: unicode(66), str(64), bool(53), int(53), long(53), set(49), float(46), complex(45), list(41), dict(39)

「標準ライブラリ」は数え切れないほどあって、サードパーティ製との境目が不明瞭になるので、「組み込み」を意味する__builtins__モジュールに限って調査しました。

また、Pythonでは、__XXX__形式の特殊メソッドを実装してオブジェクトの暗黙的な振る舞いを定義するので、それらを含まない場合と含む場合で分けて調査しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def bi_of(name):
    return getattr(__builtins__, name)

def special_name(a):
    return a[0:2] == "__" and a[-2:] == "__"

def bi_methods_of(name):
    o = bi_of(name)
    return filter(
        lambda a: not special_name(a) and callable(getattr(o, a)),
        dir(o))

def bi_all_methods_of(name):
    o = bi_of(name)
    return filter(
        lambda a: callable(getattr(o, a)),
        dir(o))

def class_method_ranking(counter_func, limit):
    return map(
        lambda name: "%s(%d)" % (name, len(counter_func(name))),
        sorted(
            filter(
                lambda name: type(bi_of(name)) == type,
                dir(__builtins__)),
            lambda a,b: cmp(
                len(counter_func(a)),
                len(counter_func(b))
                ) * -1
        )[0:limit]
    )

print "Only regular methods: %s" % ", ".join(
    class_method_ranking(bi_methods_of, 10))
print "Including special methods: %s" % ", ".join(
    class_method_ranking(bi_all_methods_of, 10))

Hello! :) is it work? <a href=http://test.com>test</a>

GDKの追加メソッドで調べてみました。具体的には、org.codehaus.groovy.runtime.*パッケージのDefaultGroovyMethods, DefaultGroovyStaticMethods, SwingGroovyMethodの3つのクラスで定義されているメソッドからです。

結果はこんな感じ。

1 : class java.lang.String=72

2 : class java.io.File=63

3 : class java.lang.Object=57

4 : interface java.util.Collection=44

5 : class java.lang.Number=33

6 : class [Ljava.lang.Object;=31

7 : interface java.util.Map=25

8 : interface java.util.List=25

9 : class java.io.InputStream=23

10 : class java.lang.Character=22

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import org.codehaus.groovy.runtime.*

counter=[:]

[DefaultGroovyMethods,
 DefaultGroovyStaticMethods,
 SwingGroovyMethods].each {
    it.methods.each {
        if (it.parameterTypes.size() != 0) {
            cls = it.parameterTypes[0]
            counter[cls]==null? counter[cls]=1 : counter[cls]++
        }
    }
}
counter.entrySet().sort { -it.value }[0..9].eachWithIndex { it, idx ->
    println "${idx+1} : $it"
}

Index

Feed

Other

Link

Pathtraq

loading...