Ответ 1
Этот вопрос заставлял меня копаться в исходном коде Clojure. Я просто потратил несколько часов на то, чтобы напечатать заявления в источнике, чтобы понять это.
Оказывается, два выражения карты оцениваются с помощью разных кодовых путей
(type {:a 1})
заставляет вызывать и запускать байт-код Java. Испускаемый код использует clojure.lang.RT.map()
для построения карты, которая возвращает PersistentArrayMap для небольших карт:
static public IPersistentMap map(Object... init){
if(init == null)
return PersistentArrayMap.EMPTY;
else if(init.length <= PersistentArrayMap.HASHTABLE_THRESHOLD)
return PersistentArrayMap.createWithCheck(init);
return PersistentHashMap.createWithCheck(init);
}
При оценке (def x {:a 1})
по крайней мере из REPL там не выдается байт-код. Постоянная карта анализируется как PersistentHashMap в clojure.lang.Compiler$MapExpr.parse()
, которая возвращает ее в файл ConstantExpr
:
else if(constant)
{
IPersistentMap m = PersistentHashMap.EMPTY;
for(int i=0;i<keyvals.length();i+= 2)
{
m = m.assoc(((LiteralExpr)keyvals.nth(i)).val(), ((LiteralExpr)keyvals.nth(i+1)).val());
}
//System.err.println("Constant: " + m);
return new ConstantExpr(m);
}
Выражение def
при оценке связывает значение созданного выше ConstantExpr
, которое, как сказано, является PersistentHashMap.
Итак, почему это реализовано таким образом?
Я не знаю. Это может быть простой надзор или оптимизация PersistentArrayMap, возможно, не стоит того.