clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
emccue 2020-10-26T02:03:28.190Z

@misha The obvious solution is a "seen" map

emccue 2020-10-26T02:03:56.190400Z

and only put the fields you want to compare into the elements of that map

emccue 2020-10-26T02:05:31.191900Z

generally though, are you just doing a search?

misha 2020-10-26T08:05:48.212100Z

not exactly. There is a complication of time, where state is "the same", but time (since game start) is not. Which is kind a problem for your line 92. The goal is not to do search from start state for every query. the goal is to generate all possible states for a certain time period from the initial state, and then search through those. then, since there is a bunch of those states (millions per second after some point in time) – i'd like to parallelize it too. And it is a problem for your "doseq" on line 93 part. Then, the "searching" is typically like this: - what is the earliest state/time I can have this unit/upgrade/building, and - what are steps that led to it. (tracing it back to the initial state)

emccue 2020-10-26T02:05:57.192300Z

emccue 2020-10-26T02:06:02.192800Z

if so, this might be useful

emccue 2020-10-26T02:06:24.193200Z

there are def. libraries and whatnot that are better examples and actually tested

emccue 2020-10-26T02:07:04.193600Z

you can start from a "starting game state" and go forwards from there

2020-10-26T04:32:45.194Z

Good article on how one can "discover" lisp:

2020-10-26T04:32:55.194300Z

An Intuition for Lisp Syntax: https://stopa.io/post/265

2020-10-26T04:52:06.194700Z

or you could use a sorted-set with a custom comparator that dissoc's :id before comparing (or select keys :a and :b) .. you can get rid of the meta usage that way

Александр Стоянов 2020-10-26T06:26:15.198400Z

Hello! I have some bug: (go (def row (:body (&lt;! (http/get "<http://localhost:5000/test>"))))) (def clean (subs row 1 (s/index-of row (last row)))) (hash-map clean) It returns {} in clean some data like :id 1, :name "Ab Bc Cd", :sex "M", :birth "01.01.1999", :address "Street 1", :oms "0001" and when i put this data in hash-map: (hash-map :id 1, :name "Ab Bc Cd", :sex "M", :birth "01.01.1999", :address "Street 1", :oms "0001") It works. But why and how can i fix it?

p-himik 2020-10-26T07:55:08.211800Z

Not sure what's going on in your code. First of all, (hash-map clean) would immediately fail in Clojure, no matter what the value of clean is because hash-map expects either no arguments or an even number of arguments. So you must be using ClojureScript. Second of all, you're assigning the result of subs to clean. subs returns a string. You cannot magically turn a string into data without explicitly converting it. If you want to read EDN strings, just use clojure.edn/read-string.

Александр Стоянов 2020-10-26T22:10:48.256800Z

It's in cljs but i did think there's no difference so i wrote in this channel

p-himik 2020-10-26T22:12:10.257Z

Either way, you have to read that EDN string first.

Александр Стоянов 2020-10-26T22:21:31.257200Z

Thank you

Александр Стоянов 2020-10-26T22:21:34.257400Z

It helps me

2020-10-26T10:52:47.215300Z

hello. I'm looking for something which behaves like an Atom, but which records a stat like 'number of tries per successful update' - anyone know of such an impl?

borkdude 2020-10-26T11:02:53.215800Z

@henryw374 Don't know of any. Probably implementing your own variation of https://github.com/clojure/clojure/blob/cbb3fdf787a00d3c1443794b97ed7fe4bef8e888/src/jvm/clojure/lang/Atom.java#L15 ...

2020-10-26T11:04:47.216700Z

@borkdude cheers yeah I've been thinking of doing that ... just being lazy!

zilti 2020-10-26T14:14:36.218800Z

I have issues with clojure.data.csv. I am getting "Unexpected character: C". How do I find out what's causing this? The input file is a tsv file and I've told data.csv to use \tab as separator.

alexmiller 2020-10-26T14:20:24.220Z

read-csv will give you a lazy sequence - if you read that line by line (with loop/recur), you should be able to count lines and print or try/catch around the body to determine where the bad data is

Hayden Sartoris 2020-10-26T15:32:22.223300Z

Anyone experienced issues involving clojure.tools.logging, threading, and try? The following causes Can't set!: *current-length* from non-binding thread :

(defmethod d/create! :impl/ad
  [ad-inst complex-user ad-user]
  (log/trace ad-user) ; fine
  (try
    (log/trace ad-user) ; not fine
    ; etc
    ))

Hayden Sartoris 2020-10-26T15:34:16.224100Z

Method is being called from pmap

Hayden Sartoris 2020-10-26T15:35:02.224400Z

Exception is thrown from within clojure.pprint

borkdude 2020-10-26T15:46:28.224800Z

@hsartoris Could it be a laziness issue?

dpsutton 2020-10-26T15:47:08.225600Z

my guess would be this is an async issue.

Hayden Sartoris 2020-10-26T15:47:17.226Z

Actually I have to amend, the try likely has nothing to do with it; can only consistently repro with log/spy

2020-10-26T15:48:00.226800Z

pmap does return a lazy sequence, and there are dynamic vars that affect clojure.pprint's behavior. I haven't checked, but wouldn't be completely surprised if clojure.pprint's implementation attempts to set! one or more dynamic vars in its implementation.

2020-10-26T15:49:06.227400Z

Just checked, and there definitely are a couple of set! calls within pprint's implementation.

borkdude 2020-10-26T15:51:15.228200Z

@hsartoris You could try (doall (pmap ..)) to see if it's laziness causing this

Hayden Sartoris 2020-10-26T15:52:44.228700Z

@borkdude yup that does it

Hayden Sartoris 2020-10-26T15:56:51.230800Z

Thanks! I guess the dice have just fallen in favor of not breaking for the previous iterations... weird

Ben Sless 2020-10-26T17:19:02.231500Z

@hsartoris in general, be wary of mixing side effects with laziness. You'll get surprises

2020-10-26T17:22:27.233200Z

But it is fairly common when someone is debugging issues with laziness and side effects, debug print/log statements are a common way to do that. In this case, it is an extra bit of surprise that the function that was attempted to be used for printing, pprint, has inside of itself some implementation details that don't mix with laziness, more so than if one tried to use println instead.

2020-10-26T17:22:37.233500Z

Agreed on the general recommendation you gave.

Ben Sless 2020-10-26T17:32:09.234300Z

Would it be correct to say dynamic bindings are a form of side effects? You're reading from an impure environment instead of writing to it (the classic example)

borkdude 2020-10-26T17:34:42.235100Z

dynamic vars are global mutable variables that don't combine well with the mathematical concepts of FP like laziness and purity

borkdude 2020-10-26T17:36:24.236500Z

I worked on an application once that had a dynamic var for the Datomic db value (as of a certain date, defaulting to today). This caused tremendous confusion in combation with laziness. I refactored the entire codebase to take a db argument instead.

💪 1
borkdude 2020-10-26T17:39:27.237400Z

This was before component was a thing. Currently I work on an app where lots of functions take the system as an argument. Nice to see how things evolved during the years ;)

2020-10-27T16:06:39.293600Z

I have an interest in this area of Clojure software design. I could find very few write ups on the topic, and nothing in depth. According to you, should the system map contain A) as much as possible or B) as little as required ? In my app, getting passed the system map carries the implication that you are going to do something side effectful with it, like getting a record from a database. In https://www.youtube.com/watch?v=vK1DazRK_a0, R. Dittwald advocates for deferring side effects to as late as possible and using as many pure functions as can. Isn't passing the system to lots of functions some kind of design smell in that context ? I'm having trouble reconciling "system map given liberally everywhere" and "use as much pure functions as possible".

dpsutton 2020-10-26T17:41:24.238400Z

They don’t seem like side effects to me. They for sure break referential transparency though

Ben Sless 2020-10-26T17:42:55.239100Z

> Despite this, the fact is that we are using functional values to simulate state. There is in principle nothing to stop functional programs from passing a single extra parameter into and out of every single function in the entire system. If this extra parameter were a collection (compound value) of some kind then it could be used to simulate an arbitrarily large set of mutable variables. In effect this approach recreates a single pool of global variables — hence, even though referential transparency is maintained, ease of reasoning is lost (we still know that each function is dependent only upon its arguments, but one of them has become so large and contains irrelevant values that the benefit of this knowledge as an aid to understanding is almost nothing). This is however an extreme example and does not detract from the general power of the functional approach. Out Of The Tar Pit, 5.2.3 Kinds of State

Tamas 2020-10-26T17:47:45.240900Z

I don't think that is the same thing though. He is talking about pure functions (no side effects) that accepts some large mutable collection.

2020-10-26T17:48:04.241500Z

he's not talking about a mutable collection

2020-10-26T17:48:47.242100Z

at least that's not how I remember the paper

Tamas 2020-10-26T17:48:57.242200Z

yes, the mutable part doesn't matter actually.

2020-10-26T17:50:22.244100Z

using dynamic scope in combination with laziness doesn't exactly introduce mutation in the normal sense, but it does introduce changes in bindings that are equally spooky and unpredictable, so as @dpsutton says they break referential transparency

2020-10-26T17:50:51.244800Z

to me (and for many of us I think), avoiding mutation isn't the end goal, it's a means to having referential transparency

Ben Sless 2020-10-26T18:07:31.245300Z

Eventually you have to mutate something, otherwise your code isn't doing anything besides heat CPU

Ben Sless 2020-10-26T18:08:12.245700Z

(unless you're writing a theorem prover or something)

2020-10-26T18:09:02.246400Z

right, the question is whether the calculation is reified into the explicit flow of data, or spooky

🎃 1
bronsa 2020-10-26T18:09:04.246600Z

there's a massive amount of mutability in theorem provers :)

👀 1
dpsutton 2020-10-26T18:10:54.248200Z

mutating the set of proven theorems and lemmas? largely like clojure namespaces?

2020-10-26T18:11:29.249Z

I think the point of that quote from Out of the Tar Pit a few comments back is that even if you write pure functions, if one of the parameters is some big collection, e.g. a Clojure map with many key/value pairs, but any given function only examines a small fraction of them, then the fact that it is a pure function doesn't help a human much in reasoning about which part of that big collection is relevant for any given pure function. That is a kind of incidental complexity for a person who wants to reason about the code's behavior.

1
☝️ 2
dpsutton 2020-10-26T18:11:33.249200Z

(def zorn's-lemma ...) etc?

Tamas 2020-10-26T18:13:07.250900Z

@andy.fingerhut that's how I understand it as well. Even more so if you pass that large collection around from function to function it complicates things even more.

2020-10-26T18:13:16.251300Z

It is better than reading global variables, because you know that whatever the pure function accesses is somewhere in that big collection, rather than outside of it, but it isn't localizing things very much if that collection is large.

Tamas 2020-10-26T18:14:12.252400Z

and why I said it is different is that if a function refers to an ear-muffed variable it isn't pure at all

Tamas 2020-10-26T18:14:26.252900Z

so it is a different case altogether

2020-10-26T18:14:48.253400Z

If you read a dynamic variable's value, one that is in the environment and not a parameter, then yes, to that extent you are reading global variables.

2020-10-26T18:15:35.254900Z

Note that pretty much every Clojure function you write depends upon the current definitions of other Clojure functions that you name inside of its body, and those are mutable variables (via def). It is just very very uncommon practice to mutate those vars, except during interactive development.

Tamas 2020-10-26T18:17:56.255900Z

and also in this particular case we're talking about printing functions so I don't think it is claimed they are side-effect free

bronsa 2020-10-26T18:19:38.256Z

nah I meant the implementation of theorem provers usually makes use of a lot of mutability internally

bronsa 2020-10-26T18:19:47.256200Z

in order to be efficient

👍 1