I've found the time to experiment myself and report my findings below.

In CLJS, MapEntry seems to work fine, and is slightly faster than using a 
vector to represent it. Below are dumb micro benchmarks, executed in fresh 
repls void of any other dependencies:

```
> clj -Sdeps "{:deps {org.clojure/clojurescript {:mvn/version 
\"1.10.339\"}}}" -m cljs.main
ClojureScript 1.10.339
(simple-benchmark [rng (range 1000)]
                  (into {} (map (fn [n] [n n]) rng))
                  1000)
[rng (range 1000)], (into {} (map (fn [n] [n n]) rng)), 1000 runs, 923 msecs
nil
(simple-benchmark [rng (range 1000)]
                  (into {} (map (fn [n] (MapEntry. n n nil)) rng))
                  1000)
[rng (range 1000)], (into {} (map (fn [n] (MapEntry. n n nil)) rng)), 1000 
runs, 840 msecs
nil
```

In this example, using MapEntry yields a 9% improvements.

In the Clojure side, there are 2 important differences. #1 MapEntry is not 
part of clojure.core in clojure.lang, so using it requires a JVM-specific 
import. #2 The MapEntry constructor doesn't need the third "hash" parameter 
like CLJS, only the key and value. So using MapEntry in cljc code will 
require reader conditional in `ns` and in each call-site.

```
(import clojure.lang.MapEntry)
(criterium/bench (let [rng (range 1000)]
                   (into {} (map (fn [n] [n n]) rng))))
Evaluation count : 317760 in 60 samples of 5296 calls.
             Execution time mean : 189.335048 µs
    Execution time std-deviation : 613.930267 ns
   Execution time lower quantile : 188.569507 µs ( 2.5%)
   Execution time upper quantile : 191.256133 µs (97.5%)
                   Overhead used : 1.867366 ns

Found 6 outliers in 60 samples (10.0000 %)
low-severe 3 (5.0000 %)
low-mild 3 (5.0000 %)
 Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
=> nil

(criterium/bench (let [rng (range 1000)]
                   (into {} (map (fn [n] (MapEntry. n n)) rng))))
Evaluation count : 401880 in 60 samples of 6698 calls.
             Execution time mean : 149.182354 µs
    Execution time std-deviation : 255.340674 ns
   Execution time lower quantile : 148.692324 µs ( 2.5%)
   Execution time upper quantile : 149.779548 µs (97.5%)
                   Overhead used : 1.867366 ns

Found 3 outliers in 60 samples (5.0000 %)
low-severe 3 (5.0000 %)
 Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
=> nil
```

This other dumb benchmarks shows a 26% speed improvements.

In my case, since I'm coding in cljc file I'm not totally confortable with 
the reader conditional. Furthermore I don't understand yet all the 
implications, apart from making the code that produce the map entries less 
flexible (a sequence of vectors is less generic than a sequence of map 
entries).

I'd love to hear from you specialists.

PS: I couldn't get clojure cli to download criterium to run the benchmark, 
so I ended up using the REPL provided by in my current app setup (based on 
Clojure 1.9.0, Boot 2.8.2 and criterium 0.4.4, the latest stable versions). 
Here's the command I ran and the error:

```
> clj -Sdeps "{:deps {org.clojure/clojure {:mvn/version \"1.9.0\"} criterum 
{:mvn/version \"0.4.4\"}}}"
Error building classpath. Could not find artifact 
criterum:criterum:jar:0.4.4 in central (https://repo1.maven.org/maven2/)
org.eclipse.aether.resolution.ArtifactResolutionException: Could not find 
artifact criterum:criterum:jar:0.4.4 in central 
(https://repo1.maven.org/maven2/)
at 
org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:422)
at 
org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:224)
at 
org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:201)
at 
org.eclipse.aether.internal.impl.DefaultRepositorySystem.resolveArtifact(DefaultRepositorySystem.java:260)
at 
clojure.tools.deps.alpha.extensions.maven$get_artifact.invokeStatic(maven.clj:95)
at 
clojure.tools.deps.alpha.extensions.maven$get_artifact.invoke(maven.clj:91)
at 
clojure.tools.deps.alpha.extensions.maven$eval698$fn__700.invoke(maven.clj:112)
at clojure.lang.MultiFn.invoke(MultiFn.java:243)
at clojure.tools.deps.alpha$lib_paths$fn__1068.invoke(alpha.clj:203)
at clojure.core.protocols$iter_reduce.invokeStatic(protocols.clj:49)
at clojure.core.protocols$fn__7839.invokeStatic(protocols.clj:75)
at clojure.core.protocols$fn__7839.invoke(protocols.clj:75)
at clojure.core.protocols$fn__7781$G__7776__7794.invoke(protocols.clj:13)
at clojure.core$reduce.invokeStatic(core.clj:6748)
at clojure.core$reduce.invoke(core.clj:6730)
at clojure.tools.deps.alpha$lib_paths.invokeStatic(alpha.clj:199)
at clojure.tools.deps.alpha$lib_paths.invoke(alpha.clj:197)
at clojure.tools.deps.alpha$resolve_deps.invokeStatic(alpha.clj:229)
at clojure.tools.deps.alpha$resolve_deps.invoke(alpha.clj:210)
at 
clojure.tools.deps.alpha.script.make_classpath$create_classpath.invokeStatic(make_classpath.clj:59)
at 
clojure.tools.deps.alpha.script.make_classpath$create_classpath.invoke(make_classpath.clj:52)
at 
clojure.tools.deps.alpha.script.make_classpath$run.invokeStatic(make_classpath.clj:70)
at 
clojure.tools.deps.alpha.script.make_classpath$run.invoke(make_classpath.clj:64)
at 
clojure.tools.deps.alpha.script.make_classpath$_main.invokeStatic(make_classpath.clj:109)
at 
clojure.tools.deps.alpha.script.make_classpath$_main.doInvoke(make_classpath.clj:84)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.core$apply.invokeStatic(core.clj:657)
at clojure.main$main_opt.invokeStatic(main.clj:317)
at clojure.main$main_opt.invoke(main.clj:313)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not 
find artifact criterum:criterum:jar:0.4.4 in central 
(https://repo1.maven.org/maven2/)
at 
org.eclipse.aether.connector.basic.ArtifactTransportListener.transferFailed(ArtifactTransportListener.java:48)
at 
org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(BasicRepositoryConnector.java:365)
at 
org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run(RunnableErrorForwarder.java:75)
at 
org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute(BasicRepositoryConnector.java:583)
at 
org.eclipse.aether.connector.basic.BasicRepositoryConnector.get(BasicRepositoryConnector.java:259)
at 
org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(DefaultArtifactResolver.java:498)
at 
org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:399)
... 34 more
```

On Wednesday, October 17, 2018 at 11:35:25 PM UTC+2, Khalid Jebbari wrote:
>
> Is it possible to create a map entry directly with the MapEntry type? I 
> see in the source code of CLJS that the type expects 3 parameters, key val 
> and hash. I've glanced quickly at usages and it seems most usages revolves 
> to (MapEntry. k v nil). Is it ok to use in app? Is it too low-level? I'd 
> like to use it in situations where I populate a map from vectors, like 
> (silly example)
>
> (into {} (map-indexed (fn [idx v] (MapEntry. idx val nil) [1 2 3]))
>
> And what does it mean in cljc code ? Is this ok in Clojure too?
>
>

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

Reply via email to