beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
practicalli-john 2020-10-25T02:42:49.470900Z

If you can change op to a hash-map then it makes the code far simpler

(def operands {"+" + "-" - "*" * "/" /}
((operands "+") 4 3)

Mark Wardle 2020-10-25T08:31:00.472200Z

Thanks. I hadn’t thought of that!

Mark Wardle 2020-10-25T08:33:57.473700Z

Wow. That looks really interesting. Thanks for the pointer. Looks like a better way to both specify AND document your structures.

Jim Newton 2020-10-25T09:50:05.473900Z

@hiskennyness😎

Jim Newton 2020-10-25T09:50:46.474300Z

i've never made myself learn the looping options of format but I love it when i see it in action

1🍺
Jim Newton 2020-10-25T09:53:24.474500Z

When I look at the :post function, maybe I don't understand the semantics of :post. What I'd like to do is assert that the value returned from subtype? is explicitly true, false, or :dont-know. I think I may be confused about using sets as membership tests. I'll change the post function to:

(fn [v] (member v '(true false :dont-know) v))
I already have a member function in my utils library defined as follows: perhaps I should replace the final call to some with a (loop ... recur) which checks equivalence until it finds one? I suspect that would be faster than rebuilding a singleton set, and then checking set membership many times. I suspect a small (loop ... recur) would compile very efficiently? right?
(defn member
  "Determines whether the given target is an element of the given sequence."
  [target items]
  (boolean (cond
             (nil? target) (some nil? items)
             (false? target) (some false? items)
             :else (some #{target} items))))

Jim Newton 2020-10-25T09:57:20.474700Z

@andy.fingerhut You commented: It calls `subtype?` twice with the same parameters, once with `delay`wrapped around it, once without, and then compares the return values of the two. Thanks for finding that. I believe that is a bug. ITS GREAT to have a second set of eyes look at code. It should call subtype? within the delay with the arguments reversed. I.e., two types are equivalent if each is a subtype of the other. But don't check the second inclusion if the first is known to be false because such a call may be compute intensive and unnecessary. Looks like i'm missing something in my unit tests. :thinking_face: The semantics of type-equivalent? are if either of s1 or s2 are false, then return false (types are not equivalent). If both s1 and s2 are true, then return true. Otherwise call the given default function and return its return value if it returns.

2020-10-25T10:17:39.477800Z

I have a question about spec. I'd like to check whether infinite lazy seq is valid. But this code is infinite loop. What should I do?

(s/valid? (s/coll-of int?) (range))

schmee 2020-10-25T10:18:15.478500Z

how could you check an infinite sequence? you’d have to check every element, which by definition would take an infinite amount of time

2020-10-25T10:28:16.479800Z

I just want to check 100 of them. So, I've used it like this so far, but it's too messy.

(s/def ::coll #(valid? (s/coll-of int?) (take 100 %)))

(s/fdef func
  :args (s/cat :coll ::coll)
  :ret ::coll)

Jim Newton 2020-10-25T10:50:35.480Z

@andy.fingerhut WRT your comment: >>> (doall &lt;expr&gt;) is one general purpose way to force any `<expr>` that returns a lazy sequence, to realize all of its elements eagerly, without having to define separate eager versions of functions like `filter`, `map`, etc. I don't completely follow. my eager versions of filter, map etc simply call doall as you suggest. Are you suggesting that it's better just to inline the call to doall ? As a second point, I don't think do doall really forces all lazy sequences, rather only the top level one. For example if I have a lazy sequence of lazy sequences, then as I understand doall will give me a non-lazy sequence of lazy sequences. Unless I misunderstand, If I want to use dynamic variables, then I have to fall everywhere in my code which is producing a lazy sequence and somehow force it with doall.

alexmiller 2020-10-25T13:25:29.481200Z

s/every and s/every-kv do this already

alexmiller 2020-10-25T13:26:12.482300Z

They will check a bounded sample (up to 100 by default)

alexmiller 2020-10-25T13:27:39.483900Z

So just (s/def ::coll (s/every int?)) is exactly same as above (actually better for gen etc)

kennytilton 2020-10-25T13:46:18.484100Z

I once did a mildly hairy cl-format for production code but before making the PR thought I should rewrite for the benefit of the Klojure Kids, one of whom had already said he did not know it existed (but seemed enthusiastic). The rewrite was monstrous, so I left it in: better they should learn cl-format and be empowered forever.

2020-10-25T14:48:24.484400Z

You are correct that doall forces the top level sequence, not nested ones.

2020-10-25T14:50:41.484600Z

Set literals are constructed only once by the compiler's generated code, if they contain only constants, I believe. I would expect set containment to be faster than either member or some or an explicit loop, since sets use hash maps to check for membership and thus do not iterate over all elements, but for a 3-element set I doubt you will notice much difference in the context of your application.

2020-10-25T14:54:19.484800Z

I've done a few experiments putting debug prints in a few places here and there trying to determine why the code sometimes creates lists that get twice as long, but I don't have any good clues yet. I doubt I will spend much more time on it. I suspect there is some kind of mutable data structure being used somewhere, but that is just a guess without evidence.

Marek Jovic 2020-10-25T17:06:38.485800Z

Hello, how to flatten vector of vectors of maps to have vector of those maps?

2020-10-25T17:15:13.486500Z

This sample REPL session has integers instead of maps, but the code works regardless of whether the bottom thing is maps or any other type:

user=&gt; (mapcat identity [[1 2] [3 4] [5 6]])
(1 2 3 4 5 6)
user=&gt; (vec (mapcat identity [[1 2] [3 4] [5 6]]))
[1 2 3 4 5 6]

1👍
jsn 2020-10-25T17:46:53.487500Z

apply concat does that

dumrat 2020-10-25T18:18:09.488300Z

cljs::formula.events=&gt; (int (char 97)) ==&gt; 0 I'm having issues converting char to int on my cljs repl. This should not result in 0 right?

dpsutton 2020-10-25T18:24:34.488800Z

(int "a")
WARNING: cljs.core/bit-or, all arguments must be numbers, got [string number] instead at line 1 &lt;cljs repl&gt;
0
> (doc of int) Coerce to int by stripping decimal places.

2020-10-25T18:53:58.489200Z

(yet another clj and cljs difference)

dpsutton 2020-10-25T19:08:04.490Z

This is more a host language difference or vm difference to me

dpsutton 2020-10-25T19:08:33.490700Z

There is no char type in js. And on the jvm chars exist and are ints

2020-10-25T19:21:08.490900Z

they are not ints

dpsutton 2020-10-25T19:24:01.491400Z

> An int value represents all Unicode code points, including supplementary code points.

dpsutton 2020-10-25T19:24:06.491700Z

Is what I’m going from

2020-10-25T19:53:56.492700Z

The JVM type system has distinct types for char and short, even though the values of those two types have a one-to-one correspondence to each other.

2020-10-25T20:01:18.492800Z

on that note, how does it store chars with codepoints >64k. I know that Java uses UTF-16 encoding, but I guess you can’t store an (f.e.) emoji in a char ?

2020-10-25T20:03:04.493Z

(more, just bewonderment than a real problem I’m struggling with :p)

alexmiller 2020-10-25T20:04:11.493200Z

it uses multiple chars

alexmiller 2020-10-25T20:05:14.493400Z

there are apis that understand this (and some older ones that do not, so some care is required)

2020-10-25T20:07:34.493600Z

I haven't read this full wikipedia page on utf-16 to see how good of a job it does explaining this, but there is a range of 16-bit values called "surrogates" in UTF-16 encoding of Unicode, such that a pair of surrogates can represent all Unicode code points that do not fit in a single 16-bit value: https://en.wikipedia.org/wiki/UTF-16

2020-10-25T20:12:14.494100Z

Yeah right. Reading up on it (and what Alex says), if you charAt a char requiring 4 bytes to represent, you get half of it. Thanks 🙂!

alexmiller 2020-10-25T20:14:57.494300Z

the codepoint apis understand that stuff

2020-10-25T20:15:31.494500Z

Wondering how that came to be, but apparently surrogate pairs were not a thing when Java was first released. The more you know!

alexmiller 2020-10-25T20:16:22.494700Z

yeah, wasn't introduced until much later

2020-10-25T20:33:26.494900Z

My understanding is that when Unicode first started, they thought 16 bits would be enough for all code points. Java and a few other software systems started with UTF-16 with no need for surrogate pairs, then later added them when 16 bits was no longer enough.

2020-10-25T20:36:09.495100Z

The "History" section of the Wikipedia article on UTF-16 summarizes a few main points of who did what, although not necessarily exactly when (although the cited references might)

2020-10-25T20:50:52.495500Z

The history of computing is often fascinating 🙂 E.g.: we tried x, that turned out to be an oversimplification, then y and z — also an oversimplification, so now we started over with a, with little bits of legacy x, y and z in there.

2020-10-25T22:36:14.496Z

That's interesting. I thought it was the same thing because s/coll-of called s/every. I didn't know there was a ::conform-all in coll-of. Thanks

germ13 2020-10-25T23:26:16.496400Z

@jr0cket i did have that option, but i wanted to get a deeper understanding of symbols and evaluation in clojure. thanks.