Fork me on GitHub
#clojure
<
2018-05-21
>
tristefigure07:05:55

I was wondering what kind of wisdom lies at the heart of the following fact: control of whether a macro expansion should be spliced in the parent form or simply expanded belongs to the parent. If we could control the splicing of a macro-expansion from the macro itself, what kind of challenge would this pose ? Is there any Lisp from the past that has attempted this ? One edge case I can foresee is when the macro is already the top level form and there is no parent to splice into. Making the macro splice into a progn/do form could be a way to overcome this.

noisesmith16:05:55

if forms were allowed to transform their parents, you wouldn't understand a form without knowing exactly what gets put into it, so clojure (and most lisps similarly) only allow control from outside in

noisesmith16:05:10

it makes reading code much more sane

borkdude08:05:54

Why do I need the type hints here? using java.time

(def dtf (DateTimeFormatter/ofPattern "yyyy-MM-dd"))
(def now (LocalDateTime/now))
(def today
  (.format ^LocalDateTime now dtf))
(def tomorrow
  (-> ^LocalDateTime now
      (.plusDays 1)
      (.format dtf)))

borkdude08:05:49

Types are only inferred in let bindings?

jumar09:05:10

Do you? This code works for me without type hints

borkdude09:05:48

I get “call to method .format can’t be resolved”

jumar10:05:51

That's strange since it works perfectly ok for me. java 8, clojure 1.9. I'd assume that it could have some problems if the value you pass there (`now`) would be of more then one possible type that overloaded format method accepts but that's not the case I guess.

bill14:05:46

@U04V15CAJ is that an actual compile error—or is it the warning IntelliJ gives you when you try to ⌘-click through .format to get to the definition? I’ve seen the latter using Cursive, in cases where the code works fine at runtime. @U06BE1L6T’s point is apt.

borkdude14:05:51

Compile time

borkdude14:05:23

I’ll try and see if I can repro. I’m in the woods right now

borkdude08:05:22

@U06BE1L6T @U0E11941M From a fresh boot repl I get the same thing:

boot.user=> (import '[java.time LocalDateTime]
       #_=>            '[java.time.format DateTimeFormatter])
java.time.format.DateTimeFormatter
boot.user=> (set! *warn-on-reflection* true)
true
boot.user=> (def dtf (DateTimeFormatter/ofPattern "yyyy-MM-dd"))
#'boot.user/dtf
boot.user=> (def now (LocalDateTime/now))
#'boot.user/now
boot.user=> (def TODAY
       #_=>   (.format now dtf))
Reflection warning, null:2:3 - call to method format can't be resolved (target class is unknown).
#'boot.user/TODAY

jumar08:05:32

Ok, I didn't get it. I assumed you're getting an error (not warning) that method can't be resolved

borkdude08:05:54

no, I asked why I needed the type hint there 🙂

jumar08:05:21

That's what confused me - I thought that without type hint you get an error 😉

jumar08:05:03

I guess the situation with global defs is similar to function args (clojure cannot know the type of the argument in advance - it's just Object)

borkdude08:05:19

> They can be placed on function parameters, let-bound names, var names (when defined), and expressions https://clojure.org/reference/java_interop#typehints

borkdude09:05:16

so this works: (def ^LocalDateTime now (LocalDateTime/now))

borkdude09:05:29

but it feels a little bit weird… in let bindings you don’t have to do this

borkdude09:05:28

e.g.: (let [now (LocalDateTime/now)] (.format now dtf))

jumar09:05:13

cool - may be worth to update snippet with setting *warn-on-reflection* and printed warning.

dominicm08:05:56

Is there something like satisfies? for interfaces?

tristefigure09:05:10

yup (isa? Exception java.io.Serializable)

jumar09:05:33

I guess instance? is closer since with satisfies you actually check "instances" (e.g. instance of defrecord) not "classes".

(instance? java.util.Comparator (fn []))

👍 8
dominicm09:05:41

Oh neat, it's hierarchical. Cool, thanks!

punit-naik11:05:18

Is anyone aware of any library which can create a kubernetes cluster on aws? Like Kops in Go?

dominicm13:05:36

Why does (new java.io.OutputStream) result in java.lang.InstantiationError: java.io.OutputStream?

manutter5113:05:48

java.io.OutputStream is an abstract superclass, you need to create an instance of some specific subclass like java.io.FileOutputStream

dominicm13:05:53

I see. Hmph.

dominicm13:05:22

I guess my real question is, how do I get something writable that is convertible to an InputStream? I have a lazy seq I am converting to CSV.

dominicm13:05:34

I want to stream the result, so I need an InputStream.

manutter5113:05:42

I think a ByteArrayOutputStream might be useful here, because you can get the bytes with toByteArray() and pass them as a constructor arg to ByteArrayInputStream

Alex Miller (Clojure team)13:05:58

look at the Piped streams

dominicm13:05:57

Apparently I was in this mess originally because something was trying to convert my working solution with Channel/newWriter & Channel pipes into a ByteArray. Bypassed that and now it's all working.

dominicm13:05:16

something standards relevant xkcd