Fork me on GitHub
#clojure
<
2017-05-01
>
cfleming00:05:19

IMO that’s a little extreme when we’re talking about something like seq working on arrays of primitives.

danielcompton00:05:05

seq creates an IndexedSeq on arrays

andy.fingerhut00:05:30

Sorry if my tone sounds extreme, but clojure.set/union is an example of something that in some cases returns what you want if you give it sequences rather than sets, but if you think it returns the union, you are in for a big disappointment. What seq does on Java arrays of primitives is anyone's guess until/unless you understand the source code.

danielcompton00:05:03

which looks like it should handle long-arrays jsut fine

andy.fingerhut00:05:59

The doc string for seq promises absolutely nothing in that case.

nagi00:05:00

@andy.fingerhut That sounds like a mistake I may bump into. Using a funtion in an undocumented way. This sounds like something a Linter could catch. I guess I should be linting my clojure code.

andy.fingerhut00:05:14

@nagi clojure.spec when enabled may help in catching you if you pass a non-set as input to clojure.set/union, I believe, warning you of using a function in undocumented ways. I don't know if it would give any warnings/error for using seq with an undocumented argument.

andy.fingerhut00:05:11

Or I suppose now it is called clojure.spec.alpha?

nagi00:05:42

Ahh, I havn't encountered clojure spec yet. Thanks for the tip. I really will have to get my code reviewed, I havn't written it yet, but I'm sure my first clojure app will be bad in lots of ways like this.

nagi00:05:22

Oh well, at least I'm aware it will be bad this time around.

andy.fingerhut00:05:00

To be clear, I am not saying that these kinds of things are likely to hit you at every turn in Clojure. They are relatively few and far between in my experience. But when they bite, they bite.

nagi00:05:51

I get what you are saying.

qqq02:05:03

@tbaldridge : block vs park: is "block = pauses the underlying jvm thread" and "park = underlying jvm thread goes and does other thing; only the go block is paused" -- since the model ns N go blolcks on M threads

qqq02:05:18

(if not, I'm among those misusing go blocks)

tbaldridge03:05:39

that's pretty much right

tbaldridge03:05:04

park really means the go block turns your code into a callback and adds it to a list on the channel itself

tbaldridge03:05:45

@qqq so it's not so much about "the thread goes on and does other things" it's more that "the code currently being executed is attached to something else

qqq03:05:26

oh right; there are 'no go threads', it's all giant state machines created by this macro which inverts everything with respect to <! and >!

tbaldridge03:05:03

aset-float, and aget

fossifoo07:05:32

somehow my brain is stuck today. what's the easiest way to make a "stateful" function that returns elements of a list, first call the first, then the second etc

leonoel07:05:29

@fossifoo what you describe is a java.util.Iterator

fossifoo07:05:57

yes, that seems to be the case

fossifoo07:05:24

now, i still don't know how to create something like it from a vector or such

leonoel07:05:08

(.iterator [1 2 3])

leonoel07:05:50

most (all ?) clojure collections implement java.lang.Iterable

igrishaev07:05:20

your function should have inner state (atom maybe) and return lambda that, in addition to returning an item, changes those atom

igrishaev07:05:50

smth like (swap state rest)

fossifoo07:05:51

well i only want a finite amount of calls supported, so i think that's too complex

fossifoo07:05:02

basically it's just for testdata

fossifoo07:05:33

i want to return 42, then 13, then 1 for example

fossifoo07:05:03

(let [b (.iterator [41 13 7]) a (fn [] (.next b) )] (take 3 (repeatedly a))) this works

fossifoo07:05:15

but it's so unclojurish

leonoel07:05:45

handling stateful functions directly is unclojurish

fossifoo07:05:26

i guess i could generate 3 functions and put those into a vector

leonoel07:05:59

what are you doing with list elements ? would a reduce be more suited ?

fossifoo07:05:41

i just with-redefs a function in a test

fossifoo07:05:57

and i want reproducible results

fossifoo07:05:30

but, well, maybe it's just a stupid idea to want a "stateful mock" in clojure

fossifoo07:05:47

when the "mock" could just be stateless as well

leonoel07:05:09

depends what you're mocking

fossifoo07:05:29

(deftest should-calculate-score []
  (with-redefs [subs/score-entry (fn [_ _] (rand-int 100))]
    (is (= {:stable-result true} (subs/calculate-score {:some "user-entry"} testdata/valid-data)))))

fossifoo07:05:19

basically i want this in place of the rand-int

fossifoo07:05:41

so i know my funtion first gets passed 42, then 13 then 7

leonoel07:05:30

what does the actual function ?

fossifoo07:05:37

oh, calculate-score calls score-entry for every element in valid-data

leonoel07:05:14

no, I mean subs/score-entry

fossifoo07:05:14

basically a (map score-entry param), with a few more calculations for the endresult

leonoel07:05:19

is it stateful ?

fossifoo07:05:25

no it isn't

fossifoo07:05:34

but it's complex

fossifoo07:05:50

so i want to unit test the calculate-score seperately

fossifoo07:05:13

as i said, i could maybe make a simpler mock that depends on the two params being passed in

fossifoo07:05:21

and not have it be stateful

john07:05:41

(def dripper (atom [41 13 7]))
(defn drip []
  (let [d (first @dripper)
        _ (swap! dripper rest)]
    d))
(drip)
;=> 41

fossifoo07:05:55

but it seems so complicated for "just" wanting to return 3 values one after the other

john07:05:30

and you can close over that atom if you make a mk-dripper function that returns a function

fossifoo07:05:40

but i guess this is part of why midje exists

leonoel08:05:33

here's how I would do it you know with which arguments subs/score-entry will be called each of the 3 times the best way to make a function from a finite set of inputs is a literal map

leonoel08:05:00

(deftest should-calculate-score []
  (with-redefs [subs/score-entry (comp {[x1 y1] r1, [x2 y2] r2, [x3 y3] r3} vector)]
    (is (= {:stable-result true} (subs/calculate-score {:some "user-entry"} testdata/valid-data)))))

fossifoo08:05:02

ah, that's a good match, yes

fossifoo08:05:43

still a bit of a hassle, but easy enough

borkdude10:05:20

What’s the clojure way to tell if something is a directory in a jar file?

matan11:05:08

Why not use an existing (java) api for jar wrangling?

dominicm13:05:53

@borkdude I'm guessing you'd get a url in an jar

dominicm13:05:15

@borkdude the slurp method has some machinery around treating them the same.

mhjort13:05:23

@looveh You were asking earlier about Clojure AWS Lambda experience in production. I have mostly experience on Clojure JVM Lambdas. They work well if you are doing something asynchronous and you accept that in worst case processing can takes seconds (cold Lambda startup with Clojure is sloooow)

qqq16:05:00

can defprotocol have a default implementation or return a default value ?

tbaldridge16:05:09

@qqq, sure extend it to Object

matan16:05:23

@mhjort Clojure JVM lambda? what is that actually?

mhjort16:05:39

Aws lambda supports both node.js and java

mhjort16:05:17

So I meant Java Lambda

mhjort16:05:59

If you use clojurescript you can use node.js lambda

istvan16:05:34

@mhjort do you have a working example? i have trouble using even the basic example from the AWS site

qqq17:05:44

What is the standard way to serialize / deserialize defrecords ?

souenzzo17:05:10

qqq: Not sure, but datomic do it very well. db/id record serializes to #db/id[-1231]. (Aka: it's possible)

tbaldridge17:05:02

@qqq transit does it pretty seamlessly, as does Fressian

qqq17:05:25

I understand that records are just 'tagged maps'; what I don't get is: when reading things back, when transit sees a map, how does it know whether to create a map or a record?

tbaldridge17:05:28

Well the correct way to do it is to write a tagged reader/writer for the maps (it's about 10 lines of code to do this)

tbaldridge17:05:01

so it writes the data out as [record-name record-data], and when it reads the data back in transit will dispatch on record-name to create the record

qqq17:05:43

Whenever I use defrecord instead of plain maps, I get all types of weird subtle hard to debug issues with code reload and interactive development. When transit writes/reads records, how does it assure that "record at time of writing" and "record at time of reading" match up? [sorry for ambigious terms; I can't find the right words to express this]

Lambda/Sierra19:05:30

It doesn't. That's up to you. But records can have arbitrary keys, however.

matan19:05:10

hi, should I be using clojure.spec for validations for my data maps, or should I wait for clojure 1.9 to use it? would you recommend any other library for nicely validating the structures (and some times maybe also some values) of maps?

bcbradley20:05:51

I'm implementing a clojure binding of the vulkan api by using lwjgl. In vulkan there are a lot of functions like:

VkResult vkEnumeratePhysicalDevices(
   VkInstance instance,
   uint32_t* pPhysicalDeviceCount,
   VkPhysicalDevice* pPhysicalDevices);
which returns a value (error or success code) and which mutate the arguments. For instance, this function checks to see if pPhysicalDevices is null, and if it is then the number of physical devices on the system is overwritten on the memory pointed to by pPhysicalDeviceCount, otherwise pPhysicalDeviceCount must contain the length of pPhysicalDevices which will be overwritten by the pPhysicalDevices of the system (to capacity if necessary), and the number of physical devices written will be written over the pPhysicalDeviceCount.

bcbradley20:05:29

In other words a lot of vulkan function are stateful to the extreme, and I'm trying to think about how best to expose the vulkan api in clojure

bcbradley20:05:06

The best idea i've come up with so far is to expose all these stateful arguments as atoms

bcbradley20:05:11

do you think that would be a good or bad idea?

bcbradley20:05:37

The other alternative is to expose the vulkan api without using stateful arguments (would involve some copying), but that begs the question of how to return it-- the return value is already occupied. I suppose I could expose the VkResults a different way but that feels overly circuitous.

bcbradley20:05:58

How would you approach this problem?

taylor20:05:57

bcbradley: I don’t have much good advice, but lower level graphics APIs are traditionally heavy on mutability for performance reasons… it’ll probably be hard to contain/abstract that away without significantly changing the API

gazaxian05:05:54

It depends, the API call you’re highlight could turn into a passing a hash and returning a new one. For enumerating devices that’d make sense as you’re only going to call it once per app so you’re not going to be too bothered about efficiency

gazaxian05:05:58

I only know a little about Vulkan but with most low level APIs mutability is something you try to keep for low frequency operations

gazaxian05:05:34

And if you have things running nicely you’re mostly updating params that get sent one way to shaders

gazaxian05:05:54

So hopefully expensive calls where you’d have to copy new data back to clojure from mutated arguments though slow wouldn’t mean a properly writtten clojure app would be slow

qqq22:05:01

in standard logic programming, during unification, there is an 'occurence check' right? to avoid infinte oop;s what happens if lhs = var a rhs = list of all vars that start with 'b' does it just infinite loop ?

hiredman22:05:21

if I recall most prologs leave out the occurs check for performance

hiredman22:05:12

minikanran (and hence core.logic) of course does the check

hiredman22:05:18

core.unify has with and without

hiredman22:05:50

I don't think your hypothetical logic program is well formed enough to give an answer

qqq22:05:50

I don't know either. My question may be illformed.

hiredman22:05:55

logic variables are similar to mutable variables in that the name is kind of a pointer to a location, so when you unify A and B, you are saying A and B both point to the same place

qqq22:05:22

I was just implementing unify again in a different way, and this thought hit me -- "what is one of lhs / rhs is a lazy infinite seq" 🙂

qqq22:05:34

before this, I'd always assumed both lhs and rhs were finite, in which case this issue would not show up

qqq22:05:56

on a related question; what is the fastesxt way to merge a list of sets (apply merge lst)

donaldball00:05:50

qqq: Probably a reduce using a transient for the accumulator

Tim22:05:13

maybe someone here can help. I am going through the java trails for digital signatures https://docs.oracle.com/javase/tutorial/security/apisign/gensig.html and from this I have the following in clojure:

(ns crypto-test.core
  (:import (java.security SecureRandom KeyPairGenerator)))

(defn keyGen
  []
  (KeyPairGenerator/getInstance "DSA" "SUN"))

(defn rng
  []
  (SecureRandom/getInstance "SHA1PRNG", "SUN"))

(defn initKeyGen
  []
  (.initialize keyGen 1024 rng))

(defn pair
  [kg]
  (.generateKeyPair kg))

(defn hexify [s]
  (format "%x" (new java.math.BigInteger s)))
but whenever I run
(let [key (keyGen)
      random (rng)
      _ (.initialize key 1024 random)
      pair (.generateKeyPair key)]
  (println (hexify (.getEncoded (.getPublic pair)))))
308201b73082012c06072a8648ce3804013082011f02818100fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c70215009760508f15230bccb292b982a2eb840bf0581cf502818100f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a038184000281805f083516344e7a14f347ec3c58ada2ebd3a829b2b12f7185f149eec2eecdeb09620f303e3144908ae8556f511294688c8fc5537d919cbc82c307cfc7322315849efd7a4a44d2add6cbb87882d5242d242e42d79e7d86e0f446997932c65a47d2fc25f224bc43d223ee78a9297d7a9008ff081a77ebbd41783dd62e190e4b9e07
=> nil
I get the same hex string over and over again. Shouldn’t the rng function provide some sort of random or pseudo-random value each time it is called?

hiredman22:05:20

why do you think you are getting the same hex string over and over?

Tim22:05:32

I run the same code over and over again

hiredman22:05:36

are you just visually inspecting? it is a long string

Tim22:05:51

oh I see that is a possibility

Tim22:05:56

let me check

Tim23:05:07

ok yes they are different in fact

Tim23:05:17

at the end of the strings they are different

Tim23:05:30

although only the last 40 characters out of the 670 characters are different

Tim23:05:17

I wonder why only the last 40 characters are distinct

Tim23:05:54

I guess there is a bunch of meta-data tied up in most of the hex encoding or something?

csm23:05:04

keys in public key crypto often have fixed parameters; in DSA, there are three integers that are parameters, and one value that’s the unique part of the key pair

csm23:05:20

I assume the JDK chooses a default set of DSA parameters if you don’t specify any