Fork me on GitHub
#clojure
<
2016-12-28
>
qqq00:12:05

(cond p1 e1 p2 e2 p3 e3 .. ); is there a "cond let" where the let is over the p1/e1, then another one over p2/e2, then a third over the p3/e3 ?

qqq00:12:22

basically there is some sub expressions that I need to calcualte for both p1 and e1, for both p2 and e2, for both p3 and e3

qqq00:12:24

and I'd like to cache them

zane01:12:11

Not out of the box I don't think.

bfabry01:12:39

yeah I can't think of anything that does that, also worth pointing out cond only chooses a single branch

qqq01:12:14

but cond has to eval some of the predicates to pick the branch right?

qqq01:12:23

when it's eval ing the predicates, I'd like to 'cache' some of the intermediate computations

bfabry01:12:33

sounds like I'd just write it as

(let [r1 (if p1 e1)
      r2 (if p2 e2)
      r3 (if p3 e3)]
etc

bfabry01:12:19

cond evals predicates until one is true. oh you want the value of the predicate result, not the expression?

qqq01:12:54

no, I don't want to eval all the branches

qqq01:12:09

it's just "if the predicate is true, when evaling the expression, there's stuff that is cached"

bfabry01:12:32

but what stuff? the result of the expression or the result of the predicate?

qqq01:12:19

I'm implementing something more complicated than core.match

qqq01:12:39

so I'm (attempgint to) destructure the argument, then eval the predate, then, if it's true, eval the expressioni

qqq01:12:43

I would prefer to only destructure olnce

bfabry01:12:33

you could use plumatic's graph library http://plumatic.github.io/prismatics-graph-at-strange-loop/ to cache intermediate computations only if they're used

qqq01:12:57

I'm doling a terrible job explaining my problem. One moment please.

qqq01:12:39

(my-cond [:rectangle a b] (< a b) (* a b) [:rectangle a b] (> a b) (+ a b) [:circle r] true (* pi r r))

qqq01:12:51

so I have a thing where there's three parts, a "destructure", a condition, and an expression

qqq01:12:01

if the destructure matches, then eval the condition, and if the condition is true, eval the expression

qqq01:12:09

if either the destructure or the pred fails, go to next line

qqq01:12:29

now, the bindings from the destructure needs to be "over" both the pred and the expr for them to make any sense at all

qqq01:12:42

sorry about misusing the term "caching calculation"

bfabry01:12:56

ah yeah ok. no there's nothing like that in core. destructurings are assumed to succeed. perhaps core.match has something but I've never used it

dpsutton05:12:23

Question, does the ignore syntax reader form require well-formed s-expressions?

dpsutton05:12:34

ie, #_(form ...)

dpsutton05:12:13

from http://clojure.org/reference/reader > The form following #_ is completely skipped by the reader. This makes it sound like invalid forms are ok?

jimmy06:12:06

hi guys, I'm looking for a good clojure client for google datastore, is there any recommendation ?

seylerius10:12:35

Okay, what's the right way to handle complex and optional arguments in Clojure? I've got a function that takes a shift (as an integer ID), an optional count of that shift (defaulting to 1), and the possibility of the string of shifts being followed by one or more of another shift (which could be any shift ID, a seq of IDs, or a shift-shorthand keyword (`:other`, :out or :off). What's the clearest and most straightforward way to do this?

seylerius10:12:46

Is there a right way to handle this?

abhir00p10:12:42

Has anyone here tried querying json fields in postgres using honeysql

abhir00p10:12:24

Are they even supported?

seylerius10:12:46

My googling is as good as yours, here, and otherwise occupied, to boot.

ejelome10:12:40

@seylerius, I think you're looking for multi-arity and variadic functions

seylerius10:12:25

Yeah, trouble is I've got two possibilities for three arguments for this function.

puzzler10:12:35

@seylerius After the mandatory inputs, take a map as an input that can contain any extra optional arguments. Do your logic to interpret that map. If it's really complicated to analyze the map, you can define a spec for the map and that will help with figuring out which of several cases the map conforms to.

seylerius10:12:18

Hmm... Yeah, map destructuring might do the trick, especially with type hinting or specs.

seylerius10:12:01

Yeah, I think map destructuring is the trick. I can add defaults there, too.

seylerius10:12:21

Except map destructuring doesn't do conditional arguments. Damnit. I was hoping I wouldn't have to just kwargs

seylerius10:12:59

Oh well. I needed to learn about spec properly anyway.

joost-diepenmaat11:12:11

does anyone have experience running elastisch against up-to-date elasticsearch versions?

joost-diepenmaat11:12:06

current releases of elastisch only supports es 1.7 - what should I use to work with elasticsearch 5? build my own jar of elastisch master branch or use something else?

mping12:12:01

does anyone knows how to preallocate a hashmap with a given size? equivalent of new HashMap<String, Object>(1000000);

tbaldridge12:12:17

@mping There isn't a way, and given the nature of persistent hash maps there's little reason to do so. But what are you trying to accomplish?

lvh13:12:37

@qqq Your problem is exactly what core.match is good at 🙂

mping14:12:28

@tbaldridge I’m trying to optimize a clojure fn

mping14:12:47

and I’m out of ideas, I wanted to use a transient map

mping14:12:51

but didn’t get much better

tengstrand14:12:45

I have just published a new architecture that allows you to modularize a system into services and run it in the development environment as a single project without restarting the REPL: https://medium.com/@joakimtengstrand/the-micro-monolith-architecture-d135d9cafbe#.6bi8wpstd

mpenet15:12:40

@joost-diepenmaat imho the best option atm is to use the new rest client they provide

mpenet15:12:34

Its quite simple and fast. We started wrapping it for clj before xmas but didnt use/test it yet.

joshjones15:12:41

@joost-diepenmaat Yes, I’m using elastisch 3.0.0-beta1 on our production servers, connecting to elasticsearch 2.3 running on aws. Version 5.0, no, but 2.3.x is the most stable and established right now anyway.

joshjones15:12:00

Yeah, I use the rest API through elastisch, not the native transport — can’t use 5.0 anyway yet, and did not want to write a clojure API to wrap a java API, since one already exists (elastisch)

mpenet15:12:13

I dont think it's the same code tho.

mpenet15:12:47

Pre 5.x rest client vs 5.x rest

joshjones15:12:07

right, it’s different I’m sure

mpenet15:12:29

Also the new client is backward compatible up to 2.x if i recall

lvh16:12:55

There’s no way to enumerate resources, right? Especially not if they’re in jar files? (I know about the indirect route of listing jar files, and then listing files in them, and extracting the filenames that way)

gfredericks16:12:48

I think you probably can

mpenet16:12:52

There's ( ".")

mpenet16:12:25

not sure if it's possible to have multiple resource paths tho, which would make it brittle

lvh16:12:31

@gfredericks by listing things on classpath and then parsing the jar files, or some other thing

lvh16:12:07

@mpenet right; the json file I’m looking for is in some jar on my classpath

gfredericks16:12:18

@lvh is "listing things on classpath" different from "enumerating resources"?

gfredericks16:12:39

if you're hoping there's a way to differentiate "resources" from "source code" then I don't think that will work

lvh16:12:43

maybe? I already have clojure.java.classpath

lvh16:12:03

@gfredericks no; I don’t think I particularly care about that

lvh16:12:18

I can check that the paths have a particular shape; e.g. I know they’ll match a certain regex

gfredericks16:12:30

any of the namespace discovery tools should have solved this problem

lvh16:12:57

I’m hoping as much; I’ll go look at clojure.java.classpath

tbaldridge16:12:24

@mping got some source we can look at?

mping16:12:49

solution_two

dpsutton16:12:04

the documentation for the ignore next form, from states http://clojure.org/reference/reader > Ignore next form (#_) > The form following #_ is completely skipped by the reader. (This is a more complete removal than the comment macro which yields nil).

dpsutton16:12:08

is this true?

dpsutton16:12:32

should #_ (defn invalid syntax [[) throw an error or be ignored?

mping16:12:21

I guess it is syntax, cuz the parser should run before the reader

mping16:12:27

(untested though)

dpsutton16:12:09

we are getting different behavior in lein repl and CIDER

dpsutton16:12:19

so not sure if this should be syntactically valid form or not

dpsutton16:12:24

lein repl ignores all of that

dpsutton16:12:48

but i'm not sure if lein repl is ignoring it or if it is correctly passing stuff to nrepl and the guts of clojure and there the reader is ignoring it

dpsutton16:12:23

and this is coming up because someone is doing #_ (defn foo [x] ::ns/blah) and it is throwing a reader error

tbaldridge16:12:44

@dpsutton yes, it will be "ignored"

dpsutton16:12:55

so there should be no reader error

tbaldridge16:12:02

I say "ignored" since the invalid syntax of the defn is only invalid at compile time, not reader time

dpsutton16:12:13

what about invalid characters?

tbaldridge16:12:13

This however will cause an error #_(]

dpsutton16:12:22

but that's only because of invalid parens?

dpsutton16:12:35

what about #_($%&)

tbaldridge16:12:01

right. That will throw assuming the that symbol is valid

dpsutton16:12:20

working on the behavior in the picture

tbaldridge16:12:27

the code behind #_ is literally:

data = rdr.read()
  return nil

dpsutton16:12:51

so it does read it

dpsutton16:12:04

so anything that could bork the reader will bork in the #_ syntax

dpsutton16:12:23

lein repl swallows everything

pesterhazy16:12:39

https://github.com/yogthos/json-html is wonderful, but is there a version that allows you to collapse/expand elements?

dpsutton16:12:46

and I couldn't find in their code where they dictate this, but I was assuming they were just not sending it into nrepl

dpsutton16:12:29

so in clojure 1.8, where :: is not defined, #_ (defn foo [x] ::ns/symbol) should throw an error?

tbaldridge16:12:49

@dpsutton :: has been around for years way before 1.8

pesterhazy16:12:00

@yogthos I'm using reagent (and data-frisk), but for a different project

pesterhazy16:12:11

my use case is actually from clojure code

yogthos16:12:50

ah I see, you’d need some client-side scripting to add collapsing expanding

pesterhazy16:12:07

super simple other than that

yogthos16:12:42

might make sense to package some minimal js for doing that in json-html

pesterhazy16:12:45

I use edn->html all the time by the way, @yogthos, thanks so much for that

yogthos16:12:02

@pesterhazy you’re welcome 🙂

pesterhazy16:12:30

I suppose I could build something similar using data-fristk

dpsutton16:12:23

is it slashes aren't allowed in :: keywords in <= 1.8?

dpsutton16:12:44

ah its the lack of the namespace

dpsutton16:12:59

so, if a namespace ns does not exist, should the following code throw a reader error or not?

dpsutton16:12:09

#_ (defn foo [x] ::ns/symbol)

dpsutton16:12:11

I'm trying to figure out if we've got a serialization problem in CIDER's bencode or if the error is expected

tbaldridge16:12:50

@dpsutton right, where you are reading that code, "ns" would need to exist

tbaldridge16:12:36

but it's even worse. Whatever namespace is reading that keyword, would need to have a compiler alias for that namespace. That code I linked above shows that the reader calls into the compiler.

dpsutton16:12:38

even in an ignore next form?

tbaldridge16:12:04

yes. In short, ::ns/symbol shouldn't be used outside of the context of compiling.

dpsutton16:12:19

ok, so the issue raised at https://github.com/clojure-emacs/cider/issues/1890 is not an issue with CIDER?

tbaldridge16:12:48

But I'm not even suer why CIDER is doing anything with this at all. It should be moving strings around, not data, or if it does move data it should be moving fully qualified data.

dpsutton16:12:03

yeah its not

dpsutton16:12:13

all it does is encode it and ship it off the the nrepl stuff

dpsutton16:12:36

The problem is that cider prepends the length of strings with a colon

dpsutton16:12:45

so I was wondering if the double colon was throwing off the encoding/decoding

tbaldridge16:12:48

but why encode it at all, why not just ship raw strings over, that's the thing I don't get.

dpsutton16:12:54

that's what it does

dpsutton17:12:03

the bencode spec says to prepend with the number of bytes

dpsutton17:12:07

so its numbytes:string

dpsutton17:12:22

and that's why i was wondering if the double colon was throwing things off

dpsutton17:12:25

but that seems to not be the case

dpsutton17:12:49

and why i was hoping that an error was to be expected, since we didn't seem to be touching anything at all

qqq17:12:57

in clojure, am I free to use symbol/variable names that start with , like a, _b, or are they reserved?

sophiago17:12:50

@qqq pretty sure underscore isn't reserved

gfredericks17:12:39

you can even use __-_-____---

sophiago17:12:26

i'm currently using print-methods to define writer syntax for several records, but when i nest records it displays the inner ones as object code. is this just not possible to do this?

dpsutton17:12:13

can you post one of your print methods for a record that has a nested record?

nooga17:12:36

@tbaldridge are you planning to get back to pixie at some point?

dpsutton17:12:18

does str invoke the print-method multimethod?

sophiago17:12:03

oh, huh. no i didn't think of that

dpsutton17:12:29

should it (.write w (str (print-method (:numerator v)) ...)

dpsutton17:12:41

I'm not sure but that's where I would start

sophiago17:12:51

is that right? let me try it

sophiago17:12:19

if i do that i get: ArityException Wrong number of args (3) passed to: core/fn--7124/fn--7125 clojure.lang.AFn.throwArity (AFn.java:429)

dpsutton17:12:36

can you post the code that you changed it to?

sophiago17:12:56

oh wait, i see what you were getting at

dpsutton17:12:15

yeah, str to concatenate the (print-method) "/" (print-method)

dpsutton17:12:17

for rational

sophiago17:12:19

to wrap each argument in .write with it?

rauh17:12:38

You need to pass in w into (print-metod your-child-obj w)

dpsutton17:12:38

no, just wrap all of it in one str so it concatenates them all

dpsutton17:12:57

ah good call ^

sophiago17:12:51

@rauh you're saying to pass w after the keys?

dpsutton17:12:21

you are saying the same thing

dpsutton17:12:30

look at the signature when you are doing the defmethod on print-method

rauh17:12:33

@sophiago Look at the two arguments of print-method that you'll receive

rauh17:12:52

So you need to pass along the second argument

sophiago17:12:43

ah, ok. and right now i have it outside of str

rauh17:12:20

(.write w (print-method (:real v) w))
(.write w " + i")
(.write w (print-method (:imag v) w))

sophiago17:12:10

oh like that? i see

sophiago17:12:34

so after, but you'd use a separate call to .write for each piece?

rauh17:12:45

@sophiago You can yes, I'd say it's more idiomatic than first stringing together pieces and putting it into the writer. The writer already does the stringing together efficiently

sophiago17:12:39

ok, i think i'm almost there... the output for the same example now looks like this: 1null" + i"null1nullnull"/"null2null

sophiago17:12:04

err actually i was just getting the quotes because of an extraneous call to print-method when i'm just writing the strings

sophiago17:12:45

ah i got it. i do need to convert them to strings after calling print-method

sophiago17:12:07

so like: (.write w (str (print-method (:real v) w)))

rauh17:12:45

Oh wait, my bad, that was silly

rauh17:12:16

It should be:

(print-method (:real v) w)
(.write w " +i")
(print-method (:imag v) w)

rauh18:12:12

So the print-method writes into the writer, you don't need to deal with converting it to a string, the recursive call will do that for you

sophiago18:12:37

ah ok. thanks. this is nearly undocumented so i had to ask someone on here to begin with and seems got it slightly off

rauh18:12:08

@sophiago Yes that's true. A good idea can give you the usage of it in clojure's own code

sophiago18:12:10

ah, cool. thanks!

sophiago18:12:27

somewhat tangentially related...i've been trying to write specs for some protocol functions that use the same records and am having trouble creating generators for the arguments i pass to their constructors. i have to use s/with-gen and gen/fmap, similarly undocumented as of yet, so i just figured out the syntax last week. but i'm getting various errors, even when the arguments are primitives. i'll throw a paste up

joshjones18:12:37

Might want to take it to #clojure-spec , but I don’t think you understand s/gen .. this function retrieves the generator for a spec. You are doing (s/gen Rational), and Rational is not a spec.

joshjones18:12:51

at least, I don’t think it is.

joshjones18:12:43

type (s/gen number?) and you get the generator for the (coerced) spec given by the predicate number?. type (s/gen Rational) and you get an error telling you it cannot construct the generator. yes?

joshjones18:12:08

fmap says: give me a generator, generate some values, apply a function to those values, and make this output also a generator

sophiago18:12:09

that makes sense, but then what about the ones where i'm only generating primitive numbers?

joshjones18:12:45

such as the very first code in your example?

sophiago18:12:03

yes, exactly. what am i doing wrong with that one?

joshjones18:12:40

why are you getting the generator twice? (s/gen number?)

sophiago18:12:00

because the Rational takes two arguments

sophiago18:12:44

and then from there i should be able to make a generator from that definition for the others, right?

joshjones18:12:46

you’re passing three arguments to fmap

joshjones18:12:30

you mean to pass two arguments: a function that modifies two rational numbers, and then a generator. for a generator like this, gen/tuple may be helpful

sophiago18:12:32

well, no. for that one Rational is a record that takes two arguments and they're both just numbers. but i suppose same idea?

sophiago18:12:45

is that really how it works, though? you pass arguments as lists?

gfredericks18:12:30

(gen/fmap (fn [[...]] ...) (gen/tuple ...)) is pretty useful

gfredericks18:12:05

in the next test.check release it'll be easier to do that via (gen/let {...} ...)

joshjones18:12:55

sophiago, consider:

(defrecord Rational [x y])
(gen/generate
  (gen/fmap
    #(->Rational (first %) (second %))
    (gen/tuple (s/gen int?) (s/gen int?))))

sophiago18:12:41

ok, thanks. lemme give that a try

joshjones18:12:52

you’re not giving (s/gen number?) arguments to ->Rational, you’re giving them to fmap

sophiago18:12:04

right, that makes much more sense

joshjones18:12:45

so you want:

(s/def ::rational
  (s/with-gen #(instance? Rational %)
              (fn [] (gen/fmap #(->Rational (first %) (second %))
                               (gen/tuple
                                 (s/gen number?)
                                 (s/gen number?))))))
=> :user/rational
(gen/generate (s/gen ::rational))
=> #user.Rational{:x 1651113, :y 81.4404296875}

sophiago18:12:13

ah, right. was going to ask 🙂

sophiago18:12:37

and then i can go on to define other generators using ::rational right?

joshjones18:12:02

yes. (s/gen ::rational) gives you the generator for the spec defined by ::rational. (you can always test whether you have a Generator by doing a (type …) on it, or by calling clojure.test.check.generators/generator? on it). Given the generator, you can give that to fmap as you’re doing here to apply a function to it again, or you can add constraints to it with such-that, etc. (alex’s list of combinators for generators is: bind cat choose elements fmap list map not-empty one-of return set such-that tuple vector vector-distinct)

sophiago18:12:25

so lastly i'm just confused about how to go about speccing out the actual functions with these

joshjones18:12:06

what in particular are you confused about?

sophiago18:12:10

i was under the assumption i passed generators for the args and exercise doesn't really check the return values unless i provide it with a function to. so like this:

sophiago18:12:18

(s/fdef add
        :args (s/cat :a (s/gen ::rational)
                     :b (s/gen ::rational))
        :ret (s/gen ::rational))
(s/exercise-fn `add)

joshjones18:12:17

stest/instrument checks :args only. stest/check generates args, and checks your :ret and :fn.

sophiago18:12:12

hmm, i'm getting an error with that fdef trying to call (stest/check add)`

joshjones18:12:12

(defn mul
  [^Rational a ^Rational b]
  (->Rational
    (*’ (:x a) (:x b))
    (*' (:y a) (:y b))))

(s/fdef mul
        :args (s/cat :a ::rational :b ::rational)
        :ret ::rational)

(stest/summarize-results (stest/check `mul))
{:sym user/mul}
=> {:total 1, :check-passed 1}

geoffs18:12:46

also, If I recal correctly, you actually pass a spec for both :args and :ret. The args spec should have a generator associated with it, but you don't pass the generator itself.

joshjones18:12:26

in the above case, both the :args and :ret are specs

geoffs18:12:05

right, your example is good. I was speaking to @sophiago original example of the similar spec

geoffs18:12:11

just typed slower than you

sophiago18:12:01

ok, i think i got it. i wanted s/exercise-fn though. but now i'm getting divide by zero errors...which is good i suppose because i didn't even think about checking for that 😛

joshjones18:12:41

Well, exercise-fn should work great now too. Curious what you will use the result for. On the divide by zero error, congrats, spec is already doing its job! :thumbsup::skin-tone-2:

sophiago18:12:39

exactly! that's what i'm using the results for!

sophiago18:12:14

but curiously, i'm feeding it ints right now and they're only between -1 and 1. whereas if i use gen/sample i get a full range

joshjones18:12:29

well, stest/check will generate by default 1000 arguments and test your :ret and :fn also. can specify more or fewer than 1000. it is very exhuastive, and requires no manual inspection

sophiago18:12:35

oh, huh. i just saw a long stack trace and glossed over it

joshjones18:12:38

exercise-fn does not check :ret and :fn, so it’s only useful for actually running the function

joshjones18:12:14

(stest/abbrev-result (first (stest/check `mul)))

joshjones18:12:29

(to see the essence of your error ^^ )

sophiago19:12:38

well i figured actually eyeballing the output would help having already determined it was far too complex to write fns to match the args to return values

sophiago19:12:56

basically to check that my type coercion functions are working correctly

sophiago19:12:49

i figured exercise-fn would use gen-sample to produce the args...but it seems almost as if with ints it's going through them sequentially?

joshjones19:12:21

exercise more than 10 and you’ll start to see more variety. try 20-40

sophiago19:12:43

i need to fix that divide by zero error first then...

kenny19:12:15

Is there a built in parser for the result of calling str on an instant? For example,

(str #inst"2015-06-01T07:05:27.000-00:00")
=> "Mon Jun 01 00:05:27 PDT 2015”
I want to parse "Mon Jun 01 00:05:27 PDT 2015” back into an instant.

joshjones19:12:56

@sophiago you might consider adding a constructor function to prevent zero from ever being the denominator https://stuartsierra.com/2015/05/17/clojure-record-constructors

sophiago19:12:36

oh, interesting. but there's a way to just exclude one value of a type like that?

sophiago19:12:47

as far as i see it, it really only matters in terms of complicating my ability to spec it out... otherwise it's up to the user to know not to divide by zero. none of the functions would output that

sophiago19:12:16

other than that, the only last thing i was going to ask about this is creating lists of generators to have it randomly sample from. i assumed i could just do it like this, but am getting a compile time error:

sophiago19:12:26

(s/def ::sym (s/or ::rational
                   ::rational-rational
                   ::rational-complex-numer
                   ::rational-complex-denom
                   ::rational-complex
                   ::complex
                   ::complex-rational-real
                   ::complex-rational-imag
                   ::complex-rational))

geoffs19:12:03

I think s/or needs each option to be labeled with a keyword so that s/conform can tell you which spec it matched

geoffs19:12:11

So something like:

(s/def ::sym (s/or :rational ::rational
                   :rational-rational ::rational-rational
                   ...
))

sophiago19:12:18

right. that does seem to be what the compiler is telling me. i think having the double bar for specs was a bit confusing to read over in the guide. even just now i thought that wasn't necessary

sophiago19:12:52

or wait...what do we call the double colon? i went to a talk by rich in november on spec and he was referencing it a bunch

joshjones19:12:55

all specs must be namespace-qualified, and :: in the guide is to save space while still showing that

sophiago19:12:31

ah, so that explains the syntax. right

joshjones19:12:36

it’s resolves keywords to the current namespace so that are fully qualified, and also expands aliases. so

(alias 'cstc 'clojure.spec.test.check)
=> nil
::cstc/my-kw
=> :clojure.spec.test.check/my-kw

sophiago19:12:30

i just meant how he was verbally referring to it. i could just look up the talk on youtube

joshjones19:12:39

regarding a non-zero number generator, here’s one:

(def non-zero-number-gen
  (gen/such-that (complement zero?)
                 (s/gen number?)))

joshjones19:12:01

another option is instead of number? in the above, use this, which eliminates values you wouldn’t want such as +/-`Infinity` and NaN: (s/double-in :infinite? true :NaN? false)

sophiago19:12:26

well i'm using int

joshjones19:12:59

well, your spec uses number? so you should change that to int?

sophiago19:12:05

technically it'll take any type of numbers, but i just made it that way because clojure ints are really longs

sophiago19:12:21

i did change them all to int?

sophiago19:12:43

anyway, thanks. that's awesome

joshjones19:12:05

ok — well then you have an easy non-zero-number-gen above (just replace (s/gen number?) with (s/gen int?) and you’re good to go)

sophiago19:12:19

sorry, one more thing...i'm realizing gen/tuple will just output a list if you feed it more than two generators (so not really accurately named), but i get an error trying to add something like (third %) to a variadic type constructor

joshjones19:12:23

gen/tuple yields a generator which will output a single vector, with the contents being the generated values of the generators used to compose it

sophiago19:12:46

it's (nth % 2) not (nth %2)?

joshjones19:12:47

(first %) = (nth % 0)

joshjones19:12:21

i think you get it, but just to be clear:

(gen/generate
 (gen/tuple
  (gen/char-alpha)
  (gen/string-alphanumeric)
  (gen/boolean)
  (gen/char-alphanumeric)))
=> [\A "Ux4FZWxIQzRPRadK8t1shzYZA96i3" false \2]
(nth *1 3)
=> \2

sophiago19:12:54

yup. got it 🙂

sophiago19:12:22

your non-zero generator doesn't seem to be working, though... not sure why. the code seems correct

joshjones19:12:58

how are you using it? with-gen or by itself?

joshjones19:12:36

sorry, should be:

(def non-zero-number-gen
  (gen/such-that (complement zero?)
                 (s/gen int?)))

joshjones19:12:50

(I put a comp there on accident earlier, duh sorry)

sophiago19:12:16

ah yeah that makes more sense

sophiago20:12:01

lol. i'm on many cups of coffee myself 😛

sophiago20:12:03

hmm, still having trouble fmapping tuples 😕

sophiago20:12:20

my constructor is like this: (gen/fmap #(->Poly 'x '((5 (nth % 0)) (4 (nth % 1)) (3 (nth % 2)) (0 (nth % 3))))

sophiago20:12:58

so the second arg is a list of tuples where the first number i'd like to be a constant

sophiago20:12:36

and with my print-method i get: x:((5 (nth p1__10256# 0)) (4 (nth p1__10256# 1)) (3 (nth p1__10256# 2)) (0 (nth p1__10256# 3)))

sophiago20:12:30

the generator list appears to be working, which is pretty cool

joshjones20:12:12

i have no idea what you’re doing there — your parens do not match in what you pasted either (missing a ) )

sophiago20:12:58

well, it's just printing the actual (nth x) with some object code in between. i'd prefer all those to be actual instances produced by my generators

geoffs20:12:10

I see what you're getting at. Your proximate issue is that you have quoted that whole list, so the calls to nth aren't actually happening. Maybe use vectors instead of a quoted list of lists

sophiago20:12:23

good thinking

sophiago20:12:45

so that works, but it may screw up a bunch of my code. not totally sure

sophiago20:12:23

i wonder if explicitly calling list would do it as well

geoffs20:12:10

yeah, that could work. or using the syntax-quote and unquoting the nth expressions

sophiago20:12:16

ok, yeah. got it. phew

sophiago20:12:11

to think...i figured speccing this project would be an easy way to learn spec...like it's actually organized in a way i'm able to manually debug

sophiago20:12:12

anyway, thanks for all your help @joshjones and @geoffs!

lvh21:12:36

Is there a some that returns item rather than (pred item)?

lvh21:12:12

I mean, besides (comp first filter) 🙂

bfabry21:12:27

nope, there's no equivalent to ruby's find in core. presumably because (first (filter is not particularly less readable

bfabry21:12:55

I suppose because of chunking you could have a situation where that's less efficient.. maybe. but in that case you could use the transducer version instead

lvh21:12:48

@bfabry Thanks for the sanity check 🙂

adamfrey22:12:33

@lvh @bfabry fyi here’s a recent ticket on Clojure’s JIRA to add that function to core: http://dev.clojure.org/jira/browse/CLJ-2056. You can vote on it if you’d like.

lvh22:12:50

I didn’t realize you could vote for tickets

adamfrey22:12:49

I believe you have to sign the contributor agreement and set up a JIRA account, but after that you can vote on a ticket.

bronsa22:12:19

no need to sign a CA to vote on jira

adamfrey22:12:39

thanks bronsa, I misremembered that.

bronsa22:12:55

CA is only required for code contributions

lvh22:12:14

I wasn’t logged in on this machine 🙂 thanks!

lvh23:12:07

Is there a transducer that captures applying a transducer to each element of a collection?

gfredericks23:12:09

so you have a collection of collections?

gfredericks23:12:21

or...a collection of reduction functions...?

lvh23:12:17

I had a bunch of maps and mapcats; and then I decided that I wanted them grouped by some intermediate value fairly early in the chain

lvh23:12:42

Now I have

(def ^:private json-models
  "All of the JSON model files in the AWS SDKs."
  (into
   {}
   (comp
    (map (fn [fn-var] (-> fn-var meta :amazonica/client)))
    (map (juxt identity src-location))
    (filter (comp second cp/jar-file?))
    (distinct)
    (map (fn [[client location]]
           [client
            (->> location io/file JarFile. cp/filenames-in-jar
                 (filter (partial re-matches #"models/(\w+)-\d{4}-\d{2}-\d{2}-model.json"))
                 (map (comp json/decode-stream io/reader io/resource))
                 (map #(get % "shapes")))])))
   safe-aws-fns))

lvh23:12:00

That inner mapping fn has some filter, map, map that’s operating over collections

lvh23:12:14

I could, of course, just use sequence or into with a separate xform there

gfredericks23:12:30

something like that would be my guess

gfredericks23:12:48

but I don't have a transducer certificate or anything like that

lvh23:12:16

cool; yeah; I’ll just extract those fns to keep it a bit more legible

lvh23:12:09

I guess it just feels a little gauche to be doing so much filtering, mapping on (second tuple) all the time

lvh23:12:15

maybe this is the kind of thing specter is great at

bbloom23:12:35

server folks: what’s your preferred strategy for dealing with failing subcomponents while working at the repl?