Fork me on GitHub
#beginners
<
2018-06-11
>
johnj00:06:37

why does (range 1e8) takes more memory than (range 100000000) ?

sundarj00:06:17

the former is clojure.lang.Range, whereas the latter is clojure.lang.LongRange, guessing it's to do with that

sundarj00:06:31

1e8 is a Double, 100000000 is a Long

johnj00:06:40

yeah, both are 8bytes - I guess clojure.lang.LongRange does some optimization

johnj00:06:33

or has to do less work, like not converting from double

johnj00:06:07

actually, I have no idea what's happening

Radek00:06:32

Since @lockdown- already asked about the 1e8 number, I ran into this:

user=> (time (reduce + (range 0 1e7)))
"Elapsed time: 150.138881 msecs"
49999995000000
user=> (time (reduce + (range 0 10000000)))
"Elapsed time: 89.430199 msecs"
49999995000000
Why does it always take more time to reduce range 0 1e7 than 0 10000000?

dpsutton00:06:58

(time (reduce + 0 (range (long 1e7))))
"Elapsed time: 253.150869 msecs"
(time (reduce + 0 (range 1e7)))
"Elapsed time: 1013.786702 msecs"

dpsutton00:06:15

and the source:

([end]
   (if (instance? Long end)
     (clojure.lang.LongRange/create end)
     (clojure.lang.Range/create end)))

dpsutton00:06:07

should give some hints @radekdymacz

Philip Hale00:06:01

Any chance someone can tell me why this is throwing No matching method found: init for class javax.crypto.Cipher? I feel like I'm missing something obvious... 😳

(defn decrypt-aes-ecb
  [bytes key]
  (let [cipher      (Cipher/getInstance "AES/ECB/NoPadding")
        initialized (.init cipher Cipher/DECRYPT_MODE key)
        decrypted   (.doFinal initialized bytes)]
    decrypted))
EDIT: Working code, for the record
(defn decrypt-aes-ecb
  [byte-stream key-str]
  (let [key         (SecretKeySpec. (.getBytes key-str) "AES")
        cipher      (Cipher/getInstance "AES/ECB/NoPadding")
        _           (.init cipher (int Cipher/DECRYPT_MODE) key)
        decrypted   (.doFinal cipher (byte-array byte-stream))]
    decrypted))

dpsutton01:06:42

try a type hint on the args? sometimes this error message can be misleading because it's really saying no matching method init(Object, Object)

dpsutton01:06:03

so if there are overloads to init with two args its having trouble resolving whihc one

👍 4
Philip Hale01:06:28

oh interesting - thank you! that sounds promising

dpsutton01:06:03

private static BoundsCheck positiveStep(final Object end) {
    return new BoundsCheck() {
        public boolean exceededBounds(Object val){
            return Numbers.gte(val, end);
        }
    };
}
this is the slowdown. the range does slow math

dpsutton01:06:41

vs

private static BoundsCheck negativeStep(final long end) {
    return new BoundsCheck() {
        public boolean exceededBounds(long val){
            return (val <= end);
        }
    };
}

dpsutton01:06:50

@phil672 did that work for you?

Philip Hale06:06:55

Just to follow up in case you were wondering... It was a stupid mistake after all. Two things actually: 1. I was passing key as a String when it needed to be a java.security.Key. 2. (.init cipher) mutates the existing Cipher, doesn't return a copy. It's been a while since I've worked with code that mutates values like that!

Philip Hale01:06:19

@dpsutton I had to step away for a second sorry but I'll come back to this later and check -- thank you for the suggestion

Radek02:06:35

@dpsutton Okay, I found that these are sources for Range and LongRange respectively. So I don’t understand Java, but I can imagine that the slowdown is Numbers.gte(val, end) in Range? I believe the Numbers method might be more complicated

Radek02:06:36

I can see why that would be slower than val <= end

Radek02:06:42

Is that what you meant?

dpsutton02:06:23

yeah. so there it knows to compare longs to longs. the other route it has two objects and it has to figure out how to compare them and then which one is less than

Radek02:06:28

Yeah, that’s what I meant, that the object method could have (and obviously does have) some overhead

Radek02:06:46

Good to know. Great investigation work! Thanks 🙂

Radek02:06:38

I really have to get used to (source) 🙂

fabrao03:06:20

Hello all, why is this fail to start in Cider?

(defproject buma "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.9.0"]]
  :profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]]}})
the source is in src/buma/core.clj
(ns buma.core)

(defn -main []
  (println "Hello !!!"))

fabrao03:06:59

even in lein repl

fabrao03:06:16

in version 1.8.0 is working great.

seancorfield04:06:48

@fabrao What messages are you seeing when it fails? (you may have to look in one of the cider or nrepl buffers to see the error messages)

seancorfield04:06:27

If it works in 1.8 and fails in 1.9, the most likely issue is the syntax of your ns -- in your test code, since you've showed your source code.

fabrao04:06:00

@seancorfield I discover that lein-shorthand is failing starting it

fabrao04:06:28

from .lein\profiles.clj. Sorry about that

seancorfield04:06:30

@fabrao Yup, user-level plugins are often the cause of Leiningen problems. It may be that there are more recent versions of that plugin that work with Clojure 1.9

seancorfield04:06:22

@fabrao Why are you using lein-shorthand by the way?

fabrao04:06:42

@seancorfield to use alembic, for loading dependencies on the fly.

seancorfield04:06:32

Switch to Boot. Some of the older lein plugins can be very problematic in that area and cause beginners more pain than they're worth.

seancorfield04:06:57

Boot lets you load dependencies on the fly, built-in, and is well-maintained.

seancorfield04:06:28

Alembic hasn't been updated for four years.

seancorfield04:06:29

I think it's fair to say that most of the pallet stuff is unmaintained at this point...

slipset05:06:20

WRT loading deps on the fly, CIDER and clj-refactor offers M-x cljr-add-missing-dependency (or some such). Priceless when starting up a project.

eggsyntax12:06:18

cljr-hotload-dependency (in case anyone sees this & is looking for it)

slipset14:06:38

Cool! Didn’t know about that one, they’re actually two different things 🙂

slipset14:06:54

(cljr-hotload-dependency)

Download a dependency (if needed) and hotload it into the current repl session.

Defaults to the dependency vector at point, but prompts if none is found.

See: 

slipset14:06:22

(cljr-add-project-dependency FORCE)

Add a dependency to the project.clj file.

See: 

slipset14:06:55

cljr-add-project-dependency also hotloads it into the running process.

fabrao13:06:35

@seancorfield I´ve been postpone migration to boot because lein is too simple until now. But, recently, many projects is breaking about something like this. So I´ll give a try with something simple to see I can handle using boot in day by day.

seancorfield15:06:50

Or, as @U04V5VAUN suggested, use CIDER for adding dependencies rather that Leiningen plugins. If you're using Emacs.

weihua16:06:03

(str #inst "2018-06-11T16:06:38.000-00:00") => "Mon Jun 11 17:06:38 BST 2018" how can i get the string “2018-06-11T16:06:38.000-00:00” as it is from an inst date-time?

dpsutton16:06:24

which host platform? java or javascript?

dpsutton16:06:21

that should be a java.util.Date and you can interop as you need in java. if you are on java 8 i think you have access to the better Date api from java

dpsutton16:06:25

i'm looking for your best bet. i know i left you hanging there a bit 🙂

weihua16:06:56

thanks @dpsutton, i’m currently doing the conversion using clj-time, it’d be a similar code piece if i use java 8 api. i was wondering if there’s a simple straightforward way to just get that string 😄

dpsutton16:06:29

it seems java is just not very pleasant here

dpsutton16:06:28

here's a lib that uses java.time. I would read how they do it (which imports, etc) and then use that idea not the dependency

Karol Wójcik19:06:54

Hello! Need some help with defining macro:

(defmacro update-state [update-path body]
  `(swap! state update-in ~update-path (fn [curr-state] ~body)))
Want to create a simple macro for updating the state of the atom. The problem is that I do not know how to handle that (fn [curr-state] ~body) seems that it want to get curr-state from my ns while it should be local in function.

Karol Wójcik19:06:08

(swap!
  state
  update-in
  [:upload-frame :reswo-file-path]
  (fn [reswo.logic.state.global/curr-state]
    (.getSelectedFile file-chooser)))
I want it to expand to
(swap!
  state
  update-in
  [:upload-frame :reswo-file-path]
  (fn [curr-state]
    (.getSelectedFile file-chooser)))

noisesmith19:06:15

if you are trying to do an anaphoric macro, (fn [~'current-state] ...)

noisesmith19:06:26

but anaphoric macros are generally avoided

noisesmith19:06:45

or, since you are ignoring the current value, you could use assoc-in instead of update-in and skip the need to bind anything there

Karol Wójcik19:06:21

oo. You're brilliant. I've forgotten about assoc-in. Thank you @noisesmith!

noisesmith19:06:44

also, if the client were to provide a function instead of a function body they could easily decide what to do with the arg

dpsutton19:06:39

^ this could easily be a function rather than a macro

👍 8
Karol Wójcik19:06:55

Yes and this is what I did 🙂

👍 8
Karol Wójcik19:06:04

Thank you one more time guys 🙂

alex31415919:06:58

Hi everyone. Little issue here, I'm using clojure.tools.logging in a project. I've added a dependency, twitter-api "1.8.0". This seems to use slf4j as a logging channel. Now while everything works, when I start the REPL I see that warning: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation. Then, the real problem is none of my logging calls actually do anything. What to do please?

seancorfield20:06:46

@alexandre.almosni Logging on the JVM is a horrible mess. slf4j isn't really a logger -- it's really more of a wrapper for other logging systems, so you need a dependency on an actual logging implementation. This blog post suggests logback https://spin.atomicobject.com/2015/05/11/clojure-logging/ (but there are other implementations out there).

alex31415921:06:49

thanks Sean let me give this a shot

seancorfield20:06:17

(I make no claim that's the best solution, just the first relatively sane suggestion I found via Bing!)

taylor20:06:31

+1 to Logback

seancorfield20:06:34

Here's another article that touches on just how weird the whole JVM logging thing is... https://dzone.com/articles/how-configure-slf4j-different

Mario C.23:06:55

Quick question: When I run lein run outside of a project directory, everything works as expected. I get a REPL running. user=> (+ 2 2). But whenever I run lein repl inside a project directory I get this error

java.lang.ExceptionInInitializerError
        at clojure.main.<clinit>(main.java:20)
Caused by: java.io.FileNotFoundException: Could not locate ring/server/standalone__init.class or ring/server/standalone.clj on classpath., compiling:(some/path/server.clj:1:1)

Mario C.23:06:00

I haven't been able to find anything online and honestly have no idea whats going on

hiredman23:06:40

run lein clean

hiredman23:06:27

turn off aot compilation, stop using lein-ring (which unfortunately turns aot compilation on)

hiredman23:06:40

hard to say what is going is going on without your project.clj, but my guess is you have the lein-ring plugin setup to use vars in a namespace that doesn't exist, and what you are actually seeing is the implicit aot that happens before starting the repl because of lein-ring failing

Mario C.23:06:53

Is it possible to load in a namespace defined within a project?

Mario C.23:06:20

In a REPL that was started outside of a project directory?

noisesmith23:06:28

you can load individual namespaces, but require from inside that ns will fail unless it's already findable or loaded in the target project

Mario C.23:06:11

Yea I was thinking if those requires would cause issues.