Fork me on GitHub
#clojure
<
2017-01-09
>
gfredericks00:01:08

even shifting the mantissa is underspecified since it has that implicit leading 1

gfredericks00:01:45

normally for floats * 2 and / 2 result in an exponent change, not a mantissa change

sophiago00:01:57

ah yeah, wrong terminology

sophiago00:01:26

err wait, actually i do want to shift the mantissa...but this is clearly not the way to do it

gfredericks00:01:26

in which direction? and what happens to the invisible 1 bit?

sophiago00:01:17

and yeah the leading 10 is retained

gfredericks00:01:10

so you're essentially adding a 0 just to its right?

gfredericks00:01:41

it's like halving just part of the number

sophiago00:01:25

yes! i think that's exactly what i've been looking for

sophiago00:01:41

float wasn't the right type to use in the first place i think

joshjones00:01:19

fwiw @sophiago float is rarely the right type to use, ever. better to use double, or BigDecimal, particularly when dealing with high precision and currency

sophiago00:01:11

@joshjones i know. i'm just not much of a java person so was having trouble finding the corresponding methods for double

dadair00:01:09

Anyone done clojure scripting for ImageJ?

sophiago01:01:40

@gfredericks i noticed you use type hints in that code. i've been wondering lately since i'm working on all these heavy numerics about the impact of reflection on performance, both for math and functions in general. i've never even tried turning warnings on for the latter. do you have any thoughts on this or could you link me to some reading?

gfredericks01:01:07

@sophiago reflection adds some nontrivial amount of time to every call. It's somewhere between a micro and a milli, I can't even remember because I just avoid it in any code that might conceivably be sensitive just so I don't have to worry about it.

sophiago01:01:41

ah, that's pretty tiny then

sophiago01:01:14

oh wait, i misread that

sophiago01:01:31

thought you wrote micro and nano (i have a pounding headache). that actually would matter for me. i should probably start checking for it as some point as well as using the primitive-math library

sophiago01:01:17

considering i read protocols add something like ~18ns overhead per call and i'm already considered about that in the context of a numeric tower

sophiago01:01:06

the docs are a bit unclear on how to add type hints for variadic functions where the arguments are of different types. is it just like [^int x ^double y]? and for return values you just add a vector in parens before the argument vector?

williewillus01:01:35

each arity goes into a new form, started by a return type hint. (defn foo (^ret [args] body) (^ret [args] body) ... )

sophiago01:01:48

sorry, i'm having trouble understanding that

sophiago01:01:13

you're saying you can't combine types?

sophiago01:01:35

(while hinting them, obviously)

williewillus01:01:39

you can, sorry. that was a bit unclear. It would look something like:

williewillus01:01:42

(defn foo
  (^long [x ^String y] x) ; takes something and a String, returns long
  (^String [x] (str x))) ; takes something, returns String

sophiago01:01:19

ah cool. thanks!

sophiago01:01:23

one more question...can you only give type hints for primitives? or records as well?

sophiago01:01:32

i'm also a bit unclear about the difference between using hints and actual static typing, as in typed-clojure

williewillus01:01:43

iirc, hints basically result in a cast in the bytecode, which can give you ClassCastException. core.typed allows you actual checking which means making sure what you return is what you say you're returning

qqq01:01:24

https://github.com/noprompt/garden <-- how do I use garden to write something which would match up with

<div id="app">...</div>
in particular, I don't see how garden allows me to write div.#app

sophiago02:01:37

@williewillus that makes sense. so there's still a performance hit in terms of casting, just less so than with inference and hopefully less typecasting in general. unfortunately, core.typed doesn't seem to be coming back from the grave. i'm not sure how many people would use it, but afaik it seems like the real major performance difference between clojure and scala when it comes to things like numerics

williewillus02:01:41

core.typed is in the grave? o.o

sophiago02:01:24

oh, wait. i must have been looking at a fork of it

sophiago02:01:26

lol, yeah i saw this and missed the note at the top: https://github.com/frenchy64/typed-clojure

ambrosebs02:01:40

core.typed is being resurrected 🙂

sophiago02:01:00

i'm really impressed/intrigued with how you were able to crowdfund working full-time on an open source project

ambrosebs02:01:11

why thankyou

ambrosebs02:01:21

took a lot of courage

sophiago02:01:55

yeah, crowdfunding anything always involves some degree of vulnerability i can imagine

sophiago02:01:20

i'm interested in whether this is a direction more developers could go

ambrosebs02:01:43

I did some more this summer, it took me a month of coaxing to gather myself

ambrosebs02:01:55

before I even started

ambrosebs02:01:43

easy to feel like old news, but people are out there who want to help

sophiago02:01:35

well, projects like yours contribute great value. it just seems they're increasingly not fitting into traditional profit motives/structures. i know engineers at places like google talking about how if there was a universal basic income they would be happier doing open source work that was more interesting than their day jobs (part of a larger conversation about the demand for software engineers now being a bubble that likely won't continue, similar to automation in most other fields)

adamkowalski02:01:04

Hey how come

(with-open [w (java.io.BufferedOutputStream. (java.io.FileOutputStream. "streams/demo"))]
  (.write w 1))

adamkowalski02:01:15

Works but

(with-open [w (java.io.BufferedOutputStream. (java.io.FileOutputStream. "streams/demo"))]
  (a/go (.write w 1)))

ambrosebs02:01:40

@sophiago thanks for the compliment

adamkowalski02:01:42

(:require [clojure.core.async :as a] [taoensso.nippy :as nippy]

ambrosebs02:01:10

I've dreamed of crowdfunding enough to hire a few devs. That would be awesome

ambrosebs02:01:17

gets a bit lonely

ambrosebs02:01:35

right now, grad school is striking a nice balance because everyone at work knows what I do and has similar areas.

sophiago02:01:00

that's ironic because what got my wheels spinning wrt to this was thinking the project i'm working on is the kind of thing one could apply to a grant for, except i don't have the academic background to do that

sophiago02:01:06

so if it proves to have enough useful applications i wonder if crowdfunding my work on it would be viable, especially if i could offer SLAs as incentives

sophiago02:01:07

(it's a library/dsl for solving partial differential equations and i decided to lean more towards the dsl side so i can have domain experts test it)

ambrosebs02:01:48

nice. I spent two years developing typed clojure and had a few conf talks before crowdfunding (to say a bit about my journey)

ambrosebs02:01:30

it was more an insurance policy to save myself from failure, but it worked out

ambrosebs02:01:53

people seem to respect going full time on OS in a different way than just leaving a few tips

ambrosebs02:01:23

I haven't really spent much effort on summarizing my experience, so this is a bit of brain dump

sophiago02:01:46

no, thanks, i appreciate it

sophiago02:01:07

you definitely need a working project before doing something like that. but more where my thinking is coming from is being in a hard spot financially yet spending most of the time that allots time working on something that does contribute quite a bit of value, which i think is more respectable (even if i think that should be besides the point) and sustainable (which does matter) than the plethora of crowdfunding campaigns among broke people i know that are totally aimless

ambrosebs02:01:58

yea. For about 5 hours this summer I had a GoFundMe to raise $10,000 to "support my phd". Went like a lead balloon. But it led me to propose a narrow and compelling project related to core.typed, which went much better.

joshjones02:01:54

@adamkowalski The async/go block returns immediately. By the time the .write is performed, however, the with-open block has already completed, and as the doc says for with-open: "Evaluates body in a try expression with names bound to the values of the inits, and a finally clause that calls (.close name) on each name in reverse order." So, the file handle has been closed, before the write can occur.

joshjones02:01:44

@adamkowalski Do this to delay completion of with-open, and it works (only for demo purposes to see the concept, not an effective way to handle concurrency here):

(with-open [w (java.io.BufferedOutputStream. (java.io.FileOutputStream. "test.txt"))]
  (async/go
    (.write w 1))
  (Thread/sleep 500))

adamkowalski02:01:30

so what would the recommended way of handling this be then?

adamkowalski02:01:47

I essentially want something that constantly waits for a message from a channel

adamkowalski02:01:52

then just writes it to a file

isaac_cambron03:01:47

why not just do the with-open inside the go block?

isaac_cambron03:01:40

alternatively, you don't need to use with-open at all; you can just create the stream somewhere and .close it when you know you're done

isaac_cambron03:01:21

you might, for example, close it when the channel closes

isaac_cambron03:01:29

something like this:

(def write-channel-to-file [ch]
  (let [w (java.io.BufferedOutputStream. (java.io.FileOutputStream. "test.txt"))]
    (go-loop [thing (<! ch)]
      (if thing
        (do
          (.write w thing)
          (recur (<! ch)))
        (.close w)))))

isaac_cambron03:01:34

(untested, natch, and you should close on errors too)

adamkowalski03:01:01

yeah how do people generally deal with errors with channels?

adamkowalski03:01:24

right now I usually take in an error channel as an argument and toss em there

adamkowalski03:01:39

but I still have a really hard time debugging anything inside of go blocks

sova-soars-the-sora03:01:32

Question... I have a web app, I made an awesome uberjar over a year ago. It still works great, but the domain has changed, and I hardcoded the domain name in a certain email that the app sends to supply users with login links. Is there a way to run the lein repl via an uberjar (and modify running code?)

sophiago04:01:55

i tried asking this in the lein channel, but seems rather empty there: i'm maintaining an alternate version of a project that doesn't use a certain dependency and instead of creating a whole separate project i just added another file with a different ns to the current one figuring i could require it from the repl and it would override all the common functions. requiring it is working, but the functions don't seem to be available, including those that aren't duplicates. what am i doing wrong here?

williewillus04:01:15

did you refer the things you wanted?

sophiago04:01:48

no. do i have to just because i required it from the repl?

sophiago04:01:45

all the functions are duplicates of the ones in the core ns that i'd like to override

sophiago04:01:25

and really the only reason i don't want to create a separate project is because it'd be a mess on github. i'd rather a way to just swap out core files

sophiago05:01:46

ah, nm. i realized i can just switch namespaces in the repl, which is really what i wanted to do anyway 🙂

mpenet05:01:45

@isaac_cambron blocking io in a go block :(

isaac_cambron06:01:25

@mpenet hmm, right, I suppose he should use (thread (loop instead of (go-loop @adamkowalski It's tricky, and the answer in my experience depends on who exactly needs to know about the failure (downstream readers of your output channels? producers pushing to your input channels?). One thing though is to catch inside your loop and print the stack trace before it's lost in all that async macro gobbledigook

isaac_cambron06:01:13

I wrote some macros that codify how I use core.async and added my exception handling, logging, etc to it. I'd share them, but I don't think I got the error handling stuff quite right either.

beppu08:01:28

@isaac_cambron I'm curious about what you think you got wrong. I'm just getting in to core.async, and I'm curious about best practices for error handling in go blocks.

ejelome09:01:55

any clj/cljs ecommerce out there? seems to be one of the areas clj/cljs is lacking 😐

lmergen09:01:10

what do you mean by 'ecommerce' ? i know quite a few european webshops running on clj

donyorm09:01:15

So I'm working on 4clojure problem #60 (http://www.4clojure.com/problem/60), and I've found a solution working on my local machine, but it seems to time out on the server. Is there any specific part of my code I can edit to make it run more efficiently?

(fn this
    ([func start coll]
     (this func (cons start coll)))
    ([func coll]
     (letfn [(reduct [result vals]
               (let [val (func result (first vals))]
                 (if (and (not (instance? clojure.lang.IPending vals))
                          (= (count vals) 1))
                   (cons val [])
                   (lazy-seq (cons val (reduct val (rest vals)))))))]
       (cons (func (first coll)) (reduct (func (first coll)) (rest coll))))))

ejelome09:01:13

@lmergen, an open-source ecommerce, something like magento or django-oscar

beppu09:01:39

django-oscar looks impressive.

isaac_cambron09:01:43

@beppu basically I do a good job of a) formalizing who "owns" a channel, b) having good conventions about how to pass them around, and c) how to alert downstream consumers that there's been a problem. I do a terrible job of alerting upstream producers that maybe there isn't a point in producing anything anymore because the consumer kerploded. I still haven't found a satisfactory way to do that that generalizes so at this point it's shrug

ejelome10:01:17

@beppu indeed! as much as I like clojure, if there's non comparable from the choice, would go instead with oscar

beppu10:01:09

@isaac_cambron Suppose you gave the chan a size limit; if the consumer stopped consuming, the chan would eventually get filled up by the producer and then it'll block once the limit is reached, effectively stopping the producer. Is that not enough? Do you really need to explicitly communicate some kind of stop message to the upstream producer?

beppu10:01:20

@ejelome Having a big community like the django people seem to have is not to be underestimated. That raw man power can get a lot of work done.

beppu10:01:02

@isaac_cambron (I need to get more hands-on experience w/ core.async before I say any more.) I imagine debugging long pipelines can get tricky.

qqq11:01:56

my "lein ring uberwar" app, with ":aot :all", takes about 8 seconds to start up on google app engine; is this the "most optmized" I can do with "lein ring uberwar", or are there other options that will make startup time faster ?

tbaldridge13:01:26

@qqq, that seems pretty respectable for me. Remember that these highly virtualized systems tend to be pretty weak in compute power. How fast does the uberwar boot on your local box?

qqq13:01:43

@tbaldridge: good question. I don't even know how to use uberwars (expect for packing it to Google). How do I run an uber war locally? (Google points me at running uberjars, which iirc are different things.)

qqq13:01:20

I'm pretty sure these GAE instances I get are .5-1 GB ram + virtualized CPU, so yeah, not most powerful of systems.

martinklepsch13:01:56

I want to construct a namespace symbol programatically, e.g (x :a :b :c) => ‘a.b.c — what function am I not finding right now? 😄

martinklepsch13:01:02

ah wait, it’s probably as simple as (symbol “a.b.c”)

pesterhazy13:01:22

(symbol ns name)

donyorm13:01:19

So I'm trying to solve problem #60 on 4clojure (http://www.4clojure.com/problem/60#prob-title). I basically have to implement reductions. I have the following code, which works on machine but times out on 4clojure. What am I missing? Is there something I can optimize?

donyorm13:01:31

(fn reduct
    ([func start coll]
     (cons (func start)
           (lazy-seq (reduct func (first coll) (next coll)))))
    ([func coll]
     (reduct func (first coll) (next coll))))

joshjones14:01:43

@donyorm without spoiling your satisfaction from solving it, a hint: what is the base/terminating case for the recursion here? the last case is the one that is not working. (reduct * 2 [3 4 5])

donyorm14:01:52

@joshjones Really? For me it fails on the first case. Anyway, that code is wrong I didn't test it properly I guess. I have some other code that was timing out, I'm seeing if I can get that to work. Thanks for helping!

joshjones14:01:10

well yes, your answer is wrong on the first case too, but it’s not a timeout issue there 😉 have fun!

donyorm14:01:13

@joshjones Yeah that code wasn't really my best code. I had tried to trim down this code (which works) but made some errors. This code passes all the test cases in my code pretty promptly. Why would it time out on the server?

(fn this
    ([func start coll]
     (this func (cons start coll)))
    ([func coll]
     (letfn [(reduct [result vals]
               (lazy-seq (let [val (func result (first vals))]
                           (if (and (not (instance? clojure.lang.IPending vals))
                                    (= (count vals) 1))
                             (cons val [])
                             (cons val (reduct val (rest vals)))))))]
       (lazy-seq (cons (func (first coll)) (reduct (func (first coll)) (rest coll)))))))

joshjones14:01:53

I’m not sure — maybe it’s the clojure gods telling you that you don’t want to really submit that answer, with the IPending and all .. I’d suggest thinking about it very simply again. Your other answer was actually closer to the spirit of what to do. Look at https://clojure.org/reference/lazy under “The new way:” and give it another go, IMO

urbanslug14:01:56

What would be the right way to get this to return a value (-> [1 2 3] (partial (filter #(> 3 %))))

urbanslug14:01:28

Because (-> [1 2 3] (fn [b] (filter #(< 3 %) b))) says fn is an unsupported binding

joshjones14:01:55

is this what you’re trying to do @urbanslug ?

(->> [1 2 3]
    (filter #(> 3 %)))

joshjones14:01:42

you’re using the thread-first macro there and it doesn’t make much sense in that context

urbanslug14:01:10

I don’t get your answer

urbanslug14:01:21

It gives the correct result

urbanslug14:01:25

but I don’t see why

joshjones14:01:21

the above is equivalent to:

(filter #(> 3 %) [1 2 3])

joshjones14:01:52

your code was equivalent to:

(partial [1 2 3] (filter #(> 3 %)))    ; don’t try this at home

urbanslug14:01:06

Oh man I think I see it

urbanslug14:01:22

It takes partially applied functions

urbanslug14:01:17

Shouldn’t it work like this though:

urbanslug14:01:46

(-> [1 2 3]
  (filter #(> 3 %)))

urbanslug14:01:00

Because all the ->> does it make it a list if it wasn’t one?

urbanslug14:01:12

but it keeps saying it can’t create a seq

urbanslug14:01:18

It already is a seq

joshjones14:01:54

-> and ->> are macros. -> evaluates the current form and uses this result as the first argument to the next form. ->> evaluates the current form and uses this result as the last argument to the next form.

schmee14:01:26

user=> (macroexpand '(-> [1 2 3] (filter #(> 3 %))))
(filter [1 2 3] (fn* [p1__10246#] (> 3 p1__10246#)))

joshjones14:01:42

Your code above does: (filter [1 2 3] #(> 3 %)) and it should be (filter #(> 3 %) [1 2 3])

schmee14:01:57

macroexpand is a great tool for learning about this stuff 🙂

schmee14:01:20

user=> (macroexpand-1 '(->> [1 2 3] (filter #(> 3 %))))
(filter (fn* [p1__10254#] (> 3 p1__10254#)) [1 2 3])

sveri15:01:53

@qqq you have to put wars into an application container like jetty or tomcat for instance

sveri15:01:52

I would suggest to setup a similar system to GAE on your local machine, if that makes sense. At least that is what I usually do, mirror my dev environment as best as I can to the production environment.

donyorm15:01:23

Is conj supposed to take a single argument? Ex. (conj [1])

tbaldridge15:01:48

@donyorm yes, and it also takes no arguments

donyorm15:01:20

Why is 4clojure giving me clojure.lang.ArityException: Wrong number of args (1) passed to: core$conj then?

tbaldridge15:01:36

transducers want reducing functions in the format of conj: 0 arity = create something 1 arity = finish what you created 2 arity = add something to the something you created

tbaldridge15:01:39

interesting,

tbaldridge15:01:23

@donyorm it's because 4clojure is running clojure 1.4

tbaldridge15:01:48

and those other arities were added in 1.8

donyorm15:01:20

thanks, good to know!

donyorm15:01:35

Finally finished that problem, thanks @tbaldridge

symbit16:01:44

Trying to connect to a JMX interface: The newMXBeanProxy method takes a Class<T> interfaceClass Using (class the-interface) throws a RuntimeExc Not an interface: java.lang.Class

symbit16:01:19

In Java it would be TheInterface.class

williewillus16:01:54

(class foo) yields the concrete superclass of foo not any of its interfaces

symbit16:01:49

@williewillus ok thanks, that explains the RTExc above.

urbanslug16:01:26

Anyone know how I can write this so that it gives me [1 2 3 4 5 6] without changing ->> to ->

(->> [1 2 3]
     ((comp vec concat) [4 5 6]))

urbanslug16:01:46

I looked at as -> but it seems to work for ->

tbaldridge16:01:08

well you can replace the ->> completely with the as->

urbanslug16:01:25

naaah in my question I said without doing that

urbanslug16:01:34

It’s part of a much larger function

joshjones16:01:42

this probably belongs on #beginners fyi @urbanslug

pesterhazy16:01:02

probably an occasion not to use a threading macro

joshjones16:01:15

sounds like homework 😉

pesterhazy16:01:29

@joshjones I don't agree, it's a valid question

urbanslug16:01:32

Not homework just me nerding out on a function.

pesterhazy16:01:34

in my experience, it's best not to fight threading macros

joshjones16:01:51

don’t agree with what?

urbanslug16:01:51

Just trying to uh super compose a function

urbanslug16:01:10

I mean write it in as few lines as possible

tbaldridge16:01:13

using comp + threading macros is a bad idea, imo

urbanslug16:01:20

I already have it working with a let anyway

joshjones16:01:42

the question was, “how do I keep ->> and still make this work" … sounds like forcing it to me .. so I think we agree @pesterhazy

dpsutton16:01:57

> It’s part of a much larger function

dpsutton16:01:06

valid reason to ask about it

urbanslug16:01:32

Yeah I have a working

(let [fn-name #(..)] 
  (->>))

tbaldridge16:01:59

The question is valid either way. But so is the assertion of not fighting the macros.

urbanslug16:01:59

Anyway, I just like composition

jr16:01:22

I usually extract the composition into a def

(def into-array (comp vec concat))
(->> [1 2 3] into-array)

tolitius16:01:09

@urbanslug since the question is mostly practice and fun:

boot.user=> (->> [1 2 3] (interleave [4 5 6]) sort)
(1 2 3 4 5 6)

urbanslug16:01:34

hmmmm sort wouldn’t work in my case

urbanslug16:01:44

I care more about the order in which args are passed

urbanslug16:01:51

flip concat would work

tolitius16:01:52

@urbanslug is that for something "real"? 🙂

joshjones16:01:53

If you are using a threading macro to “chain” several transformations, that’s the intended purpose. But your cases so far have included only one transformation, which makes its use less than ideal. For learning, anything goes, but in practice you’d probably want to have at least a couple of transformations for it to make sense

urbanslug16:01:58

but we have no flip

urbanslug16:01:27

Whichever way I let it go

urbanslug16:01:45

@tolitius In my case the [1 2 3] is a vector of maps

tolitius16:01:25

boot.user=> (->> [1 2 3] (conj '(4 5 6)) flatten)
(1 2 3 4 5 6)

tolitius16:01:48

not sure why you can't use as-> though..

symbit16:01:21

@williewillus This seems to do the trick: (Class/forName "com.zaxxer.hikari.HikariPoolMXBean")

sandbags17:01:56

This baffles me, perhaps there is a good explanation. Why does almost every library I have ever found display their depedency info (for including in project.clj et al) as an image? I mean the first thing I want to do is copy & paste and... it's a damn image!?!

bostonaholic17:01:08

@sandbags yes. that pisses me off every time

sandbags17:01:34

what's particularly baffling is... isn't this actually more difficult than just having the text??

sandbags17:01:48

i mean, you have to actually generate & update the image

bostonaholic17:01:03

it’s developers being lazy and loading the image from a service which watches version of their library so they don’t have to update the README directly

bostonaholic17:01:10

it’s laziness

sandbags17:01:03

okay lazy, yes, but it makes sense

bostonaholic17:01:03

you don’t have to create the image. clojars allows you to copy/paste a ‘Version Badge'

bostonaholic17:01:20

add once to your README, and piss off you users for eternity

sandbags17:01:41

well at least i understand the rationale now

sandbags17:01:49

i can at least empathise with the desire to be lazy 🙂

bostonaholic17:01:06

the version badge is great. but it’s not a substitute for a textual representation in your installation instructions

sandbags17:01:47

i don't suppose there is an easy way to copy alt text from an <img>

bostonaholic17:01:48

I would suggest opening a PR to the lib with your reasoning

sandbags17:01:09

If it was one lib or even two perhaps

bostonaholic17:01:26

I believe in you

sandbags17:01:36

but i think trying to circumvent this kind of behaviour has a low probability of success

bostonaholic17:01:39

hell, I’ll commit to doing the same

sandbags17:01:52

what's required is something as easy or easier

sandbags17:01:13

that does the right thing

beppu17:01:19

It might be better to make clojars serve up an SVG image which can be copy/pasted.

bostonaholic17:01:53

@beppu now you’re thinking

bostonaholic17:01:17

I see clojars’ badge is an SVG

tcrawley17:01:20

clojars does serve up an SVG. The idea was to provide something that is copyable. Unfortunately, Github loads SVG in a way to make them non-copyable, for security reasons

beppu17:01:32

oh... hrm.

tcrawley17:01:44

but if someone can figure out a way around it, I'm all for it :)

bostonaholic17:01:47

of course they do

juhoteperi18:01:27

Only way around Github restrictions seems to be to just write the version number to readme. Several Boot projects use a task to update marked part of readme automatically.

juhoteperi18:01:52

(Or a bash script)

beppu18:01:48

Can someone explain what's so dangerous about embedding the SVG image that github had to resort to replacing SVGs with pixel images?

bostonaholic19:01:42

malware injection

carocad19:01:35

well if you do things right you can just link the svg-badge from Clojars to the clojars website where there is a copy-paste text of the latest version. It is just one click away 😉 . You can see it in action in one of my libs https://github.com/carocad/clemence

tbaldridge21:01:52

Had a client once say that part of their app needed to support arbitrary HTML input by users that would then be displayed when any other users looked at that DB record.

tbaldridge21:01:06

I think the correct response is "Do you want someone to hack your site?"

dpsutton21:01:51

"arbitrary good and tasteful HTML" was the updated spec?

tbaldridge21:01:08

lol, most likely

dottedmag21:01:36

There's undocumented #= reader form. Is it a bad idea retained for compatibility reasons, an implementation detail, or is it something else completely?

jr21:01:25

it's a "secret" implementation detail

jr21:01:29

read-time eval

dottedmag21:01:04

Yeah, and until recently it was a single reader form which caused side-effects. Weird, really.

radon21:01:24

I wouldn’t say it’s undocumented.

user=> (doc *read-eval*)
-------------------------
clojure.core/*read-eval*
  Defaults to true (or value specified by system property, see below)
  ***This setting implies that the full power of the reader is in play,
  including syntax that can cause code to execute. It should never be
  used with untrusted sources. See also: clojure.edn/read.***

  When set to logical false in the thread-local binding,
  the eval reader (#=) and record/type literal syntax are disabled in read/load.
  Example (will fail): (binding [*read-eval* false] (read-string "#=(* 2 21)"))

qqq21:01:03

(apply str (repeat " " n)) ;; is there a better way to write this?

williewillus21:01:28

not much shorter but (str/join (repeat n \space))? needs a clojure.string require though

tbaldridge21:01:09

It's bad enough that there's clojure.edn that disables it.

dottedmag22:01:29

How are functions like ints used? What kind of argument needs to be coerced into a typed array? I have tried to supply various objects to this function, and the only one which worked was (integer-array 1), which does not need to be coerced anyway.

qqq22:01:36

(defn foo []... calls bar); (defn bar [] ... calls foo) ;; how do I make this work}?

williewillus22:01:00

@qqq: use declare or an unbound def

qqq22:01:11

@williewillus : right, thanks!

dottedmag22:01:46

Is there a difference between (intern (symbol (str *ns*)) 'var 1) and (def var 1)?

Lambda/Sierra22:01:49

@dottedmag I believe def adds some extra metadata to the Var.

dottedmag22:01:37

Ah, of course, and intern gets the meta from second argument.

qqq22:01:29

I really wish there was a version of map that was: list -> list, vector -> vector the existing map causes all types of confusion when I use conj

Alex Miller (Clojure team)22:01:14

use into with a transducer

Alex Miller (Clojure team)22:01:37

(into [] (map foo) a-vector)

Alex Miller (Clojure team)22:01:06

you pick the output coll

nathanmarz23:01:24

@qqq (transform ALL map-fn any-seq-type) with specter preserves type

qqq23:01:26

@nathanmarz : I can't figure out if specter is a brilliant composition of orthogonal components or a set of useful hacks; is there some relation between specter and datalog? it seems like esentially there is a "query" step, and an "update" step

nathanmarz23:01:58

@qqq no relation to datalog

nathanmarz23:01:28

it's just function composition at its core

nathanmarz23:01:37

this is a simplified implementation of specter that shows the basics of how it works: https://github.com/nathanmarz/basic-specter/blob/master/src/basic_specter.clj

qqq23:01:34

@nathanmarz: very interesting; thanks; was just about to look at https://www.youtube.com/watch?v=VTCy_DkAJGk

qqq23:01:41

Specter fully works in cljs right?

nathanmarz23:01:07

keep in mind that talk is outdated and does not include anything about inline caching