Introductions and Weather Chat
00:00:17
Speaker
For 52 with Gary Fredericks. Did I pronounce it right? Sure, yeah. Ah, nice. So, this is Vijay from Holland. We're from Belgium. And Gary from somewhere. I'm from Chicago. Chicago, right. Is it the windy city?
00:00:37
Speaker
Yeah, I guess so. Yeah. Is it windier than Holland? It can't be windier than Holland. I've never been to Holland. Okay, then it is fucking windy here. I don't know if it's particularly windy. It could mean something else. Didn't it used to be quite windy before all the development? Because it's in a certain part of the country? I wasn't here then. It's a very flat part of the country.
00:01:07
Speaker
Ray was there. Ray was there because he was all Pantea. It's like the one continent. Yeah, exactly. When I was strolling the earth, you know. What is it called again? Pantea or Pantea? Pantea, probably. Pantea, Pantea, yeah. That's what we called it anyway, back in the day.
Gary's Software Journey and Programming Languages
00:01:36
Speaker
So, um, what's happening? Oh yeah. Okay. Um, closure. So Gary, please. So how did you get into closure? Maybe give us a bit of introduction about yourself and then, you know, tell us, yeah, tell us what you're doing these days and how did you end up here? Uh, here, like on the podcast, you mean? Yeah. Everything, everything, you know, lead to Rome. All closure code leads to deafen. Yeah. Okay. Right.
00:02:06
Speaker
So I guess it was maybe 10 years ago, I was starting off in software development and by coincidence, I ended up working for a guy who was interested in new languages. And he just told me to go learn Clojure and Ruby and Scala and Erlang. So I was just learning like all of those within the space of six months and not using most of them for anything serious.
00:02:35
Speaker
Um, but, uh, what kind of gig was that by the way, because, you know, I've never heard of that kind of approach to literally anything, you know? Well, I mean, I was worrying for, uh, for government. Um, so it didn't really, it didn't like nobody else there was doing that, but like the particular guy that was telling me what to do. Um,
Contributions to Clojure and Test Check
00:02:58
Speaker
you know, he was interested in languages.
00:03:00
Speaker
Um, and you know, we like, we ended up writing some code that got rewritten later in a more standard language. Um, so it wasn't, wasn't stuff that lasted there for very long. Um, but, but that was how I got into it. Um, and, and I guess I don't really know, remember like my impression of those languages at the time, but somehow closure ended up being the thing that sucked more than anything else. Um, so I've,
00:03:28
Speaker
And I've been using it professionally since then. Sometimes more, sometimes less. We usually like a lot of Ruby code nearby. So I'm familiar with that too. But I spent a lot of time on IRC in the earlier days. And so I learned quite a lot of closure just by watching and participating in those conversations.
00:03:57
Speaker
And I had time for doing random open source stuff at that point as well. So I've made a few libraries that have ended up being moderately useful to some people. None of them are extremely popular. I've made plenty that nobody ever used because they were terrible. And a few things that are just jokes mostly.
00:04:27
Speaker
You belong on the show. I had three or four jobs in a row that were all closure and writing generic kind of business code generally, whatever fits the context of the company or organization I was working for.
Public Speaking and Testing Concepts
00:04:51
Speaker
I guess I started doing more like speaking and maybe five years ago, like I tried out speaking at conferences and I enjoyed that a lot. I also took over the test check library. I didn't remember if it was a contrib library at the time. I think it already was. And Reed was interested in working on other things and I had already worked with him on it.
00:05:22
Speaker
because I was using it at work and wanted to, you know, wanted to add features. So I had gotten really familiar with it. And it was the, like of all the Closure ecosystem libraries, it was probably the one that was like closest to the sort of thing that I enjoy working on. Cause just all of the like algebraic or, yeah, algebraic is a good word.
00:05:50
Speaker
Aspects to like how you build generators and that sort of thing and I mean it's written in a really like pure functional style In a way that you can you can give us like a quick Intro about the library uh-huh for the people who don't know sure yeah so Ignoring history test checks a contrib library for doing old property-based testing and
00:06:15
Speaker
And that's usually contrasted with example-based testing. I think a term mostly used by people advocating property-based testing as a way to summarize all of the other kind of automated tests people do. And they say example-based testing because they want to emphasize that you're writing a test that just tests one particular example of how your program might want to run. Whatever test data you're using, it's just one thing that might happen.
00:06:45
Speaker
And you often have to explicitly think about what edge cases might be interesting to your program. And depending on what kind of programmer you are, you may or may not even bother testing edge cases. You might just write, happy to have tests. But regardless, the onus is on you to kind of list all of the edge cases that you want to test and actually think through those things.
00:07:11
Speaker
And so property-based testing is about describing more abstractly what your program should do without giving specific examples, like something that should be true regardless of what data or inputs are used. And then if you can sufficiently describe the data and inputs, then test check can just generate as many examples as you have time for and test all of them.
00:07:41
Speaker
Um, so, you know, there's a lot of trade-offs, um, there and like in the best case, it's, uh, you know, something that will find all of the edge cases for you and find bugs you weren't even thinking about. Um, it has
Emacs, Dvorak, and Org Mode
00:07:56
Speaker
a feature called shrinking where if it finds some data that fails the test, then it will, um, ideally simplify it to the like most basic, uh, example of, um,
00:08:09
Speaker
something that fails in a way that will hopefully make it obvious to you what the bug is. You can go like this. So yeah, I could go in a variety of directions from there. So I want to see what are you interested in, I guess.
00:08:27
Speaker
So I think usually one of the only questions that we ask our guests is like Emacs or some other shit. Yeah. Random direction now, dude. But OK. He said any directions. That is only one way. So like eight years ago or so, I was using Vim and a standard QWERTY keyboard layout.
00:08:56
Speaker
hands were hurting from typing too much. And so I just decided to try two things at once, um, which was I switched to Emacs, uh, which sounds odd at first cause like, yeah, especially if your fingers are, you may actually just have to like hit control and all like all the mod keys all the time. So it sounds like it wouldn't help. Uh, the rationale was that, well, you don't have to use Emacs that way. And Emacs is so configurable that like, if you find yourself,
00:09:23
Speaker
typing a whole lot, and then you can write an elift code and figure out how to not type as much, even if you are reaching for modifier keys. I mean, I'm sure in theory VIM is configurable as well, but in practice people don't like to do it. So I switched to Emacs, I also switched to the Dvorak keyboard layout, and I mean, largely my hands have not been hurting since then, so it could be that either of those two things helped, or by coincidence,
00:09:52
Speaker
something else. I just have no idea. It wasn't very scientific, but now I use Emacs and funny keyboard layouts. I do a lot of weird things with Emacs. I think the thing that would make it hardest to quit, at least especially for personal stuff, is the org mode. I didn't know that org mode when I switched, but it's exceptionally useful in all sorts of ways. I use it for
00:10:23
Speaker
my entire life basically, and using quite a lot at work as well. Is it like Jira?
Generative Testing and Asynchronous Code Challenges
00:10:33
Speaker
That's one of the kinds of things you can do with it. I guess I use it in that way and lots of other stuff as well.
00:10:43
Speaker
I think you got the direction of relationship wrong, Ray. I mean, it's not like Jira. Jira is like, everything is like org mode. So the direction points that way. It's not the other way around. Yeah. Jira does a few other things that org mode can do.
00:11:00
Speaker
Exactly. And everything is like Emacs or something. Anyway, so awesome. I think that's the exact answer that we wanted to hear. Now we can go into all sorts of directions. So coming back to the test check. So before coming to Clojure, as you said, or maybe writing Clojure code, you said there were plenty of other languages that somebody suggested to you to learn.
00:11:26
Speaker
Usually, if you see generative testing, I think that's coming from really statically typed languages like Haskell. So how do you contrast that with closure generative testing versus, for example, something like Haskell or Scala, where there are types and everything? Well, one of the differences is I think it grew up in the statically typed
00:11:54
Speaker
language ecosystem, partly because when the computer knows your types already, it can create rudimentary generators for you. So that saves some work. And that's the exact same strategy as with spec, where you're using spec, and so you've already described the shape of your data. And so ideally, spec can create the corresponding generators for you.
00:12:24
Speaker
I certainly haven't done generative testing in statically typed or property based testing in a statically typed language. So I can't talk too intelligently about it. My sense is, well, I was gonna say something about how, like I know when you use spec with test check,
00:12:49
Speaker
Once things are complex enough, you find yourself needing to write your own generators anyhow to describe things that are probably either not captured by the native specs, or you've written some credit kits to test consistency in some larger data structure, but spec can't just use your predicate to write a generator. And so you need to do something custom in order to generate stuff that matches the predicate.
00:13:19
Speaker
My guess was that that sort of thing would apply in Haskell, et cetera, as well. That you can generate things from your types, but there's still inevitably some more complex things. So you'll be forced to write some of your generators. But that might not be true. It might be that if you were really diligent about correct by construction kind of approaches,
00:13:48
Speaker
that you would end up with just all the generators just work because it's impossible to generate something that's invalid. I have no idea how feasible that is in real life, but it sounds nice and serious. Well, my guess is that with certain typed languages, the number of options that are possible are kind of explored a little bit as well.
00:14:17
Speaker
What do you, by options, you mean like kinds of things you might want to generate? Yeah. Well, you know, if you, if you, if you've just got a spec then to some, you know, I mean, how, how, how do you choose which, which path of a, of a, of a, you know, when you're, when you've got a compiled language, you still have to follow a certain path, don't you, to get to a particular type. And if you're using generics or, you know, something like that, then in theory, there are lots and lots of implementations of this thing.
00:14:45
Speaker
Yes, but if you're using generics, ideally I think you're in a situation where you can prove that it doesn't make a difference what the parameterized type is. For example, if you're testing a list reversal function, you're in Java and the type is a list of some type parameter.
00:15:12
Speaker
you know, a list of foods, I mean, not foods, you know, it's something abstract where it could be any concrete thing when you actually call it. The compiler shouldn't let you do anything that depends on, you know, what kind of type is being used, unless you specify that it, you know, it has to be something that implements this interface or something of that sort. But like for a list reversal function, you don't need to know anything about the objects.
00:15:39
Speaker
that are in the list. And so that should be evident by the type. And then if your generator system is sophisticated enough that it can tell that, that it's impossible for you to do anything that depends on what kind of objects are in the list, then it maybe doesn't need to spend any effort generating weird things to put in the list. Like generate a bunch of numbers or something like that and be satisfied with that. That makes sense, yeah. So it could actually optimize it a little bit ahead of time.
00:16:09
Speaker
Whereas with Clojure, you don't have those static guarantees and ultimately you can pass anything to any function. There's a lot more of, especially when you use spec. I don't know if spec does this, but spec has this aspect where you describe maps that are open and then you can have arbitrary extra keys.
00:16:35
Speaker
And like one approach to generating those things could be that the generator just adds lots of random garbage to every map just in case that happens to be something that your code books at by accident. And I don't think it does that because, you know, I would pull everything down and it would be lots of garbage on the screen that you'd have to sish through every once in a while. That's just one of the trade-offs that makes. But I mean, on closure, like that would be a valid way of testing.
00:17:01
Speaker
You know, you can always just add random stuff everywhere. So this is also obviously useful on ClosureScript as well, right? Both Closure and ClosureScript. Yeah, there's a caveat to that, at least currently, which is that I don't think that we have anything wired up for doing asynchronous testing in ClosureScript.
00:17:28
Speaker
Um, so it's, uh, mostly just useful for testing, like business logic, your functions, that sort of thing. Um, I haven't, I haven't done a lot of that, but I, you know, I, I made sure that it's, uh, you know, the library at least compiled and close your script and all the test paths and that sort of thing. Yeah. So what's the async story then? Um, you mean like, what would you do if you wanted to test async code with test check? Yeah, in general. Yeah. Um,
00:17:59
Speaker
There might be a like a variant, like a fork somewhere that does it. There's probably a branch in the test check repo maybe. You know, I'd have to look into it. It partially depends on what the test runners currently do with async code. I think Closure test is set up to do async in Closure Script. But I don't know that for sure. I haven't tried this. Oh, in Closure?
00:18:28
Speaker
Oh, well, I mean, if you're on the JVM, then you can always take any kind of asynchronous code and just wrap it in thread that wait for something to be done. So it's not really an issue. Like it's an issue in Clojure scripts because the JavaScript runtime won't let you lock, like run one thread that waits for another thread and then does something afterwards.
00:18:52
Speaker
Well, I mean the, the, the, the issue, generally issue with a synchrony is just the order ordering of things. So is that something which test check, uh, kind of managers as well? Oh, no. Um, that's something that Reed really wanted to do because he was, uh, the model that he built test check on was an Erlang implementation.
00:19:18
Speaker
Right. Um, we might be called early and quick check. I'm not sure. Yeah. I think quick check. Yeah. But, um, I think it, it, or some associated library has a feature where it will manage all of the backgrounds, asynchronous message passing stuff so that it could test things happening in different orders and isolate race conditions.
00:19:39
Speaker
So Reed wanted to do that with Clojure. I don't know if he wrote any code for that. That would be a lot of work because you'd have to get into the guts of at least Clojure's multi-threading stuff. I assume all like atoms and agents and futures and all of those things.
00:20:03
Speaker
you would want to be able to orchestrate what's going on. And that might be possible technically. I mean, ideally, you'd be inside of the JVM manipulating all the JVM level concurrency mechanisms. And that's, I'm sure, a lot harder and maybe not possible most of the time. And so you'd be doing this compromise where it only applies to people that are using the closure level concurrency thing.
00:20:35
Speaker
I don't know if it would end up working very well. But that's the story as far as testing or race conditions. And in practice, when I have code like that that I'm trying to test check, what I'll do is wrap it in a synchronous code like I described earlier. And so now you have a test that
00:21:00
Speaker
could fail randomly. It's not deterministic, which is not ideal for a test check. But if it fails often enough that you could say wrap it in code that will just run the test 10 times and only pass if it passes all 10 times, you can get some leverage out of that. That'll, of course, slow your test down even further.
00:21:28
Speaker
fail that often, then you're in a situation where if it ever fails, it will at least tell you that here's an example where
Property-Based Testing and Shrinking
00:21:40
Speaker
your test can possibly fail. And so now what you can do is take that example and just run your test on that example 10,000 times and just measure how often does it fail. Hopefully it fails often enough that I can
00:21:56
Speaker
uh, tell whether it's failing or passing at least within like an hour or a day or something like that. You know, it's not fun, but you know, if you have a race condition that you care about, then you'll, you'll, you know, you'll be able to invest the time to track it down by that mechanism. And so test check is something that will, um, you know, at least find bugs like that, even if, even if it's difficult to really debug it and fix it.
00:22:25
Speaker
But that really depends on the amount of iterations that you run, right? Because the generative testing always seemed to be, at least to me, it's not an exact testing, but we're going to try with the computational power and the time, depending on how long it's going to take, then hopefully it is going to find out. It's like SETI, isn't it? Is that a correct assumption? Yeah. What did you say, Ray? I said it's like SETI.
00:22:48
Speaker
Oh, the like alien thing. Yeah. Um, yes. Yeah. It's the kind of like, if you really wanted to, and I'm sure some people do, you could have a machine that's just full time dedicated to running your property based tests 24 hours a day. Um, I, there was like one, uh, one thing I worked on where that was
00:23:14
Speaker
That was useful. It was open source, actually. A library that's about test check called test chuck. And the most interesting thing in it is a generator of strings that match regular expressions. So you give it a regular expression, it gives you a generator of matching strings, which means that the work it has to do is to parse and understand the regular expression. And, you know, understanding a regular expression means
00:23:44
Speaker
but allowing the JVM means that you have to understand all the details of JVM's regular expression class, which is very complicated. And so like in writing this code, I also used test check to test that code to make sure that I was understanding the regular expression correctly. So like one,
00:24:08
Speaker
What the first thing you have to do is given a string, like a string version of a regular expression, decide whether it's even valid. Like, can I parse this correctly? And you have a built-in reference implementation of that in the JVM. You can also, the enclosures, I think it's called re-pattern. The function, you give it a string and it'll return a regular expression, or it'll throw an exception if it's not a valid regular expression. So I could test my parsing code like this. I could generate a random string that may or may not be a valid regular expression,
00:24:39
Speaker
check if my parser thinks it's a valid regular expression and check if the RE pattern function thinks it's a valid regular expression, then it just asserts that those two things should match. They should either both succeed or both throw exceptions. That was a really good test of my parser.
00:24:57
Speaker
That was something where I could run it for 24 hours. And, you know, once I had gotten out the easy bug, it would take 24 hours to find the next bug. It's like bitcoins.
00:25:10
Speaker
Yeah. Yeah. Mining bugs. Yeah. So it's like a cryptocurrency for bugs. Yeah. Yeah. That's what you should really put. You should put like, you know, people do these Easter eggs for JavaScript where they embed like a Bitcoin mining code. Right. That's what you do. That's what you should do. Yeah. You've got a website and all of your users are secretly running your tech.
00:25:35
Speaker
Exactly. And when you get coins, you're like, that was an easter egg. I was just mining bitcoins on your behalf, you know.
00:25:42
Speaker
Yeah, if I ever succeeded in mining Bitcoin, I'd send it to you, obviously. Good to know. And how does the other side of the thing work? Because this is also something that is very fascinating to me. What is it called? The narrowing? The shrinking. The shrinking. Yeah. So how does that work? Because I don't want to make any stupid explanations because I don't know how does it work.
00:26:09
Speaker
This is the biggest difference between test check and the original Haskell quick check. I think Reed may have guessed how it worked in the Erlang version and used that.
00:26:29
Speaker
It could have been completely original. I'm not even sure. I think a lot of more modern quick check variants do something similar. But anyhow, in the original Haskell, you would have to supply a shrinking function. If you made a
Spec, Test Check, and Future Improvements
00:26:41
Speaker
generator, you would need to give a function that takes some example data and then returns a list of smaller pieces of data. And so that's a lot of work, and you have to think creatively about it.
00:26:56
Speaker
I mean, you can probably just decide not to do it, and then you don't get as much of the feature. But anyhow, in test check, the shrinking is intended to be just automatic. All the built-in generators have shrinking functionality built in. Go with them. And when you write your own generators, you're doing it using the provided combinators in test check.
00:27:21
Speaker
So there's the FMAP combinator that says, I want to generate this thing and then transform it using a function. And the FMAP itself has built-in shrinking. So if you write a custom generator that way, then you're still going to get shrinking for free because it can shrink the original thing and then pass the shrunken version of that thing to your function and get a smaller version of the output for that function.
00:27:49
Speaker
That's true for all of the combinators. The intention is that you should never have to think explicitly about shrinking. It should just work. In practice, it's useful to know something about how it works so that you can optimize things so that it shrinks faster. I think that's usually the only issue.
00:28:16
Speaker
Shrinking can take a long time if you're generating very big things, or if you're generating big things and your test is really slow. I guess this would happen to me where I was running these really sophisticated tests that would have to generate like a megabyte of data, and then the test itself would take several seconds for each instance. So it would run for a while. If you want to test 100 trials, then it'll take a few minutes.
00:28:43
Speaker
But if it found a failure and now it has this several megabyte data structure and wants to shrink it, that could take a day in the worst case. So when you're in that situation, it matters whether you have options for optimizing shrinking. I don't think I told you how it worked really, did I? No. No. Well, you give us the outline always. You give us the outline always. That's good.
00:29:17
Speaker
There's only one generator that has a really original shrinking algorithm built in, and that's the positive integer generator. That was probably a false thing I just said, but I don't know how it's false, so I'm going to stick by it for now. There's this generator, really fundamental generator, that just generates a number up to
00:29:41
Speaker
I guess I should say, back up, when you're running tests, there's something called a size parameter. So this is because it wants to start with small instances of data so that you can fail quickly. If it doesn't even work for the small things, then it'll fail right away, and it'll be small, and it won't have to shrink very much. So it starts out small, and then tests on larger and larger things.
00:30:05
Speaker
And the way this actually works is that it just has this parameter that starts at zero and goes up to 199. If you run 200 tests, it'll go all the way up to 199 one by one. And then if you run more tests than that, it goes back to zero and just cycles around. That's how it works by default. And so there's this integer generator that just generates a number uniformly from zero up to the current size.
00:30:32
Speaker
So it'll generate small numbers at first. And once you get up to like 199, it's generating integers all the way up to 199, which isn't very big. But regardless, there's the way that that shrinks is, I might even not be able to describe it accurately. It'll, I probably like try zero first. Like if you can shrink the number to zero and the test still fails, then it saves a lot of effort.
00:31:00
Speaker
If that doesn't work, it'll probably try dividing it by two. In the best case, if you have a test where it fails above some amount, then it should get there quickly using a binary search. And I think that's what it ends up being, something like a binary search. So divide by two, and if that doesn't work, then try halfway in between those.
00:31:27
Speaker
It might end up being something, you know, slightly different algorithm, but it's, you know, certainly smells like binary search. But, so then you have a lot of other, like a lot of the built-in generators are created using the combinators that are available to users. The, like, there's like collection generators.
00:31:53
Speaker
So a collection, I guess, also shrinks kind of in a custom way. So if you generate, say, a vector of things, if it's not a particular, it's not intended to be a particular size, then it can shrink in a couple ways. It could shrink the individual item in the vector, or it could shrink by just removing items and giving you a shorter vector. And so it interleaves those strategies. You know, it might try with an empty vector first.
00:32:19
Speaker
Um, and then, you know, try cutting the vector in half. And if it can't remove things at all, then it'll just start shrinking individual. Um, it's amazing how much I don't know about this, even though I've worked so much. Um, I think you're doing well. Uh, so F map I described earlier, like it's just a pure function that.
00:32:42
Speaker
that you're mapping the generated value and so it can shrink the prior value of the input function and then call your function again. There's generators like tuple where you want to, you supply several generators and you want to generate a vector that has an element that, one element from each generator.
00:33:08
Speaker
And so that shrinks by just individually shrinking the generated item. We can't shrink by removing them because it's static length. But each of the combinators are built in things, sort of has its own natural way of shrinking.
00:33:27
Speaker
And this can be fairly complex operation for arbitrarily deep structured or data structures enclosure, right? If there is a vector of a map of vector or something like that, then especially because it's not only at the top level form, it needs to shrink the individual vectors inside a map, you know, value, something like that. Yeah, so I mean, it's,
00:33:55
Speaker
It's sort of defined recursively. So if you have some sort of deep structure like that, if you can look at what's the top level thing, the collection, and so we'll try removing elements at the top level, and we'll try shrinking elements at the top level. And so if you're shrinking one of the elements, and that element's a map with a whole bunch of stuff in it, then you have to think about how to map shrink. That sort of thing.
00:34:23
Speaker
Yeah, there's another generator called such that that will filter generated items on a predicate, for example. So you give it a generator and then some predicate and it'll give you a new generator that only generates things from the other generator that match the predicate. So that has a natural shrinking definition too, which is you shrink the original thing, but only try things if they match the predicate. So, yeah, I mean, in a lot of cases, I think,
00:34:53
Speaker
you can kind of figure out what's the natural thing to do here without having to actually look at the code.
Quirky Libraries and Programming Preferences
00:35:01
Speaker
does the, because we have spec now and then in alpha, but we had spec for a couple of years now. And so how does that help in terms of this one? Because obviously some of the generator guessing can happen by just treating the specs and then using specs as the input, right?
00:35:24
Speaker
Yeah. Um, that's certainly the intention. I haven't, I don't think I've used this. I don't think I've used spec with test check myself very much. Uh, certainly never at work. Um, and I, like, I understand how they're, how they're wired together. My,
00:35:47
Speaker
My sense is that if you're using it for serious stuff, then you're gonna have to be familiar with how TestCheck works. You can't just rely on Spectre in your test because once you have complex enough stuff, you need to write custom generators. There's a few different gotchas in how they're connected. And I mean, TestCheck in general has
00:36:17
Speaker
a variety of little things that are kind of difficult to use about it, I would say, which is something I've thought about a lot and tried to make it easier to use when it's obvious how to. But that's one of the most difficult things for me in maintaining it was
00:36:40
Speaker
You know, watching people use it and seeing what's difficult and trying to think about something that would make it easier without, like, ruining other things and making it more complicated to understand. And, you know, most of the time I just don't know what to do because it's a weird kind of constraint to work under where you're writing code for thousands of people that you never talk to and they never tell you they're using it and you want to
00:37:09
Speaker
like not break stuff when you change things. Um, and I don't think I'm answering the question. You asked test check-in and spec relate to each other. I mean, you don't need to answer the questions at all. It's, it's, it's to go in any direction you like. Yeah. I mean, so yeah, so it, it, it has a, uh, like for all of the different kinds of built-in specs that you can use, it will have,
00:37:38
Speaker
a definition for how to generate something from that. So like if you use a call of generator or spec to describe a collection of some other things, and that's some other spec, then it's going to use one of the generators for generating a collection. So there's a lot of obvious pairing between the specs and the generators. There's a few weird edge cases. And then it also has code for instrumenting functions
00:38:08
Speaker
Um, and, and they made this choice and surprised a lot of people where the default, I guess this doesn't have to do with test check. I was thinking about like the way they only test the input, not the output in instrumentation. Um, that's not actually about generators. I guess test check, that's a different entry point where you give it a function and say, test this thing. Um, and it will,
00:38:36
Speaker
generate the inputs and call your function and then I'm going to make sure it doesn't throw an exception and then also test the type of the, like the outputs need to match the spec. And with spec, you can also add a, I forget what they call it, but it's like a validation function that will take the input and the output and assert something about them.
00:39:01
Speaker
And I assume that's also getting checked when you when you do the property based testing. So it's not only like rate the generator is an effective rate the test for you. And like one of the difficult to use aspects is that that the entry point for running those tests isn't wired up to any of the normal like closure test stuff. So you have to
00:39:28
Speaker
At least last time I looked you had to write some minor amount of custom code to make us like in your test, you run this other thing and you make an assertion about it. I don't know where you see shrunken values when your tests fail and that sort of thing. Like one of the difficulties in working on testing libraries is that there's this whole ecosystem of testing tools.
00:39:53
Speaker
And they all need to know about each other, sort of. If you want it to be really ergonomic, then I talked to Colin about what's this thing, an intelligent cursive. And he wanted to be able to show little things about what values were getting generated in the test check test. And so I had to think about what does test check need to expose, make that possible.
00:40:22
Speaker
And then there's like other ways people run their tests and there's, you know, like there's test runners and there's IDEs and, you know, when it's just this like flat ecosystem of lots of different tools playing lots of different roles, all trying to interoperate. I think it gets really difficult to make it a good user experience.
00:40:46
Speaker
So what is the future for test check? What are the things that are planned or what do you want to focus on or what do you want people to contribute to? Right. So let's see. Like I described some of the difficulties in maintaining it.
00:41:10
Speaker
One of the things I did after I took over was I filled in a lot of generators that felt like they were missing to me, things that I would need frequently. And I did this whenever I thought it was obvious what good implementation would be, like I added, like generators for larger integers and for collections that have
00:41:36
Speaker
distinct elements, which was a hard thing to do in user land, and UUID, and a bunch of other random things. And that was all in the 090 release, which was, I think, three years ago now. And then I started working on all of the stuff that was not easy enough to do in that release. And so I had all these hard things. And so, I mean,
00:42:02
Speaker
Between that and not wanting to devote too much time to it, all those features have sort of dragged out. And I made some alpha releases a few times along the way. But it was only in the last month or so that I decided I wanted to finally try to put together a proper release out of those three years worth of sort of hodgepodge efforts.
00:42:33
Speaker
Partly because there's at least there's one or two things that are fairly useful for spec and I like spec can't be changed to use those things until it's really released. So there's like this release dependency there and you know there's also like things that would just make the user experience better. So I like I really wanted to get that released and that requires like
00:43:01
Speaker
abandoning some of the things I wanted to do that are just too hard. Um, but last month I got it in what I think is a good enough States release. Um, so I, I made an RC release, um, and have no, like no other things I'm planning on changing. Um, so I'm just letting that bake. Uh, one, one person told me he was using it and I haven't heard anything bad from him or anybody else. So, so I assume, uh,
00:43:29
Speaker
I assume nothing else will come up. And then in a few weeks, I'll cut an actual release. After that, I think I'll probably be more passive. At this point, there's only really, really hard stuff left. You've got to go to your hammock at this point. I talked to Stu Hallway about this a little bit. And one of his comments is that the best thing you can do is just leave it the way that it works.
00:43:59
Speaker
You know, like adding a bunch of features might end up breaking stuff. Yeah, I mean, he's really focused on stability. And you can see that in the language as well. So in a sense, people haven't been clamoring to have stuff done. It's just all these like vague things that are not ideal about it, but don't have obvious solutions.
00:44:27
Speaker
So anyhow, I don't think I'm going to be actively working on another release after that. So I'm happy to talk to anybody that wants to work on that. And I have a long list of things I wanted to do, like problems I saw and ideas I had. I really wanted to reboot some of the namespaces.
00:44:55
Speaker
like the generator's name space or the quick check name space or the def spec stuff. One of the most difficult things about making it easier to use is you need to also, like the stuff that was hard to use needs to stay there and still work.
00:45:14
Speaker
and be documented and that sort of thing. So it's a constant problem of how do I have both of these things and eventually you just end up making it more confusing because you've got all these versions of things that people have to understand and choose between. Yeah. So yeah, I have a long, long list of like fantasy ideas that I largely didn't
00:45:39
Speaker
didn't do, but they're still there. And I think I still understand them and can explain them. But I think it's a really, really great bedrock for this kind of testing. And like you say, a lot of things that you maybe people want to do on top of it, they can do on top of it. They don't have, you know, the library itself doesn't have to have the answer to all of these possibilities, does it? Right. Yeah. I mean, there's, there is a lot of stuff you can do in user land. And that was part of why I created the, the test chuck library was,
00:46:09
Speaker
Like I saw things that I could make more ergonomic by shredding these helper functions. Um, but it would be harder to decide to put them into test check. You know, I, like I created that library before I was maintaining test check, but even afterwards, like I wasn't really tempted to just take all of the stuff in it and then dump it into test check. Um, cause I mean, there's a different standard for stuff you put there.
00:46:34
Speaker
It has to fit with everything else. It has to be something you believe is useful for everybody or at least something that everybody should
Static Typing and Computational Theory
00:46:41
Speaker
know about and have to decide whether or not to use. Whereas sticking it in a third-party library, there's a lot lower bar. So I think that's one way to solve the problem. But it's also not fun for newcomers to come in and be told, well, we use this library for this thing. And then there's this other library you should pull in
00:47:02
Speaker
you know, this other thing and they probably worked together well, but, um, yeah, I, it's the closure way though. Come on. Yeah, it is. But I, yeah, they will come. I, I, I, part of this, I think is that I was like, I've always worked
00:47:27
Speaker
near people who have a lot of rails experience and they're used to this really cohesive thing where most anything you might want to do is something where you can Google and here's this one liner and you don't understand what it's doing but you type it and it works and you're happy and you keep going and the closure ecosystem is not that way. That's the ideal that I want because I want to make those people happy too.
00:47:58
Speaker
And yeah, it's probably just not possible. I think it doesn't, just before we go on, there isn't a lot of it, I was just going to say, there isn't a lot of this kind of stuff depend upon, you know, essentially an opinionated perspective, because I think, you know, the main thing to me about Ruby on Rails is that DHH had a way of doing things.
00:48:24
Speaker
He had a strong opinion. He's a strong leader of that framework. A lot of these tools like TestCheck, maybe I'm missing it, but it seems less opinionated. It's more of a toolkit rather than a directed solution to a particular generic problem like web applications. Yeah. That's true in a way. It has its own kind of opinion.
00:48:54
Speaker
Um, like one of the things about rails is not a programming language, you know, it's, it's restricted to a, uh, a very particular kind of application. Um, and when you use it for other random things, it starts getting more awkward. Um, but you know, when you're trying to build the thing that rails was designed for it, you know, pretty easy to do. Um, enclosure was never.
00:49:18
Speaker
I mean, it's just, it's a generic language. So you're supposed to be able to use it for anything. And there is no like community primary thing that we're all building. So all of these libraries are, you know, either built with like, whatever random thing the maintainer happens to be working on in mind, or else nothing in mind there, you know, they're supposed to work for everything. So yeah, there's a lot, I think a lot less cohesion in terms of what application you're targeting and the style of thing you use.
00:49:48
Speaker
That's why, what I see from people in the consulting world like Matossian and Juxt and people like that is that they tend to have a preferred pack of libraries and then a preferred bit of glue code that they write. I think that's the way people tend to do things, is that they don't have one overarching framework.
00:50:12
Speaker
I think Cognitec did Pedestal, didn't it? That was the original idea of a kind of replacement for Rails. But it's a lot of work to do the full stack and I don't think it fits the culture very well. So as far as I know, it's mostly just like backend stuff and a better version of Ring basically with async functions.
00:50:35
Speaker
So, you know, good stuff, but, you know, it's very much a sort of slice of the, of that particular domain rather than the whole thing. Yeah. I haven't used it or like done the sort of things that would benefit from, and I'm fairly distant from it. The vague like observer impression I got was that it perhaps could have been a lot more popular if they hadn't like gotten unlucky and
00:51:02
Speaker
designs and released it like right before React became a major thing. So the whole like web development ecosystem kind of shifted out from under that. I mean, it was, Ohm came out around the same time, I think. I think the front end story in Pedestal was fairly complicated. Yeah, just unlucky timing. Like I,
00:51:28
Speaker
If they had done it a couple of years later, it would fit a lot better with those things. Maybe it would have been popular, I'm not sure. Yeah. So there are two other things that I wanted to just ask you. Like, what is going to happen with your library 71? I think I have a medical request.
00:51:55
Speaker
I don't know if there is a good idea. My Gmail inbox is my to-do list or one subset of my to-do list. But that made it into org mode. Oh, yeah. There are two pull requests and three issue spending. So what do you have to say about it? Maybe first explain to people what 71 is, and then that's easier.
00:52:18
Speaker
71 is a library that provides the number 71. Um, enclosure. I don't remember what the, like, if there's anything in particular, I'm yeah. Yeah.
00:52:32
Speaker
I think I wanted to just like make fun of libraries in general when I made it. This is like the next level. I mean, leftpad actually has some like functionality in it. This is the next level of shit. I think we should have like one library for every natural number. And then, you know, people complain about there are not enough libraries in Closure. Like we have infinite amount of libraries, minus one. Yeah. And then go on. And then 71 it is. I might stress the like Closure or Maven.
00:53:01
Speaker
ecosystem to try to deploy an infinite number of libraries. I really want to use it, but you know, the major version is still zero. So I'm a bit concerned about the stability of the library. That's just the closure style, isn't it? The zero dot doesn't contain any information. Exactly. Zero dot one dot five. Well, that seems to be okay. Yeah. I'd be more in favor of just using, like at work we use integers, which,
00:53:31
Speaker
I guess it's easier since you're not trying to communicate to somebody what features are supported. But I wasn't at one of Rich Hickey's ideas in his talk about backwards compatibility with just these integers per version. I haven't seen anybody doing that.
00:53:46
Speaker
I think some people started doing it because I see this, whenever I try to do pip install something, I get some weird number that doesn't make any sense to me anymore on Python ecosystem. You're saying Python people are doing it? Yeah, like if you do, I don't know, pip install something, and then suddenly it will put in something in my, you know, virtual enrollment, okay, what does this number mean? I have no idea. But I think they are also catching up to the semantic thing a bit.
00:54:12
Speaker
But there are people who are using dates for releases. I think it's a complicated thing. If you're committed to the backwards compatibility thing, it feels like that could work. I just haven't really been maintaining anything that's significant enough that I needed to do anything beyond just increment a number for the version.
00:54:36
Speaker
71 seems like a solid library, you know, for me, I think, you know, I think I might need to take a look at the problem I've got with it is that, um, it just doesn't have, um, depth or Eden support. So it's, uh, it doesn't know. I think there's that's one of the pull requests, right? Yeah. Number, number 19 is, uh, I don't remember. Maybe it's just the issue.
00:55:00
Speaker
No, is this an issue? OK, yeah. Well, yeah. I mean, yeah, that's something that's something we can improve. That's an easy one. Some loser opened that one. Oh, it was you. One thing I haven't figured out is the whole like library deploys release lifecycle without line again.
00:55:24
Speaker
Um, with depth seeding. Yeah. No, you just, you just, just to put, put the last commit is the shah. Then you're all done. Basically, you know, just like upload it to, you got to make a jar and upload it. No, you don't know. If you make, if you make, if you make it, yeah, yeah, yeah. If you make it, your commit is a deploy. So you make a depth so even file and then I can depend on it and we're all good.
00:55:52
Speaker
Is that what a lot of people are doing? They're not even going to Clojars? Exactly. Yeah. I don't know, man. You need GitHub to be there. That's cheating, I know. I think they've got a bigger CDN than Clojars have. Right. It's just a single point of failure thing. There's got to be other downsides to that. I haven't thought about it too much.
00:56:20
Speaker
I mean, like you can't, the line again, people can't use it at all. At least a short term downside. I think let's get to some other less serious libraries than the final one. So can you maybe give a quick idea about what is CoinDB? Is it like competing with Redis? Awesome.
00:56:46
Speaker
But it's MongoDB. I think it's a, uh, kind of a trailblazer. I don't, I don't know that it has any competitors at the moment. It's too far ahead. Yeah. Fair enough. It's so advanced. Nobody's using it as far as I know. You need, you need quantum computers. Yeah. That's what the, the QE was supposed to mean. I think that makes sense. Everything makes sense to me now. Yeah. Uh,
00:57:15
Speaker
Go ahead. Yeah, so maybe enlighten us a bit. Like, what is CoinDB doing? And then what can I use it for? CoinDB is both a coin and a database. So coin meaning it's
Gary's Complex Interests and Future Plans
00:57:33
Speaker
a program you can run and it just prints itself out. So it's a bash program in this case. So it's a bunch of bash code.
00:57:43
Speaker
And it's a database because the auxiliary functionality beyond printing its own source code is the value store. And so it does both of those things by using the two different output streams on Unix. So the source code goes the standard out, I think.
00:58:06
Speaker
And then all of the like database based functionality goes to standard error. Yeah. So like, so if you run it with no arguments, it just prints its own source code. And then there's a few different commands that you can run. Like there's one for reading the value associated with the key. So, you know, you call coin DB and the first argument is get, and then the second argument is the key.
00:58:32
Speaker
And then it'll print its own source code, of course, to send it out. But then it'll also print the value that you stored under that key to standard error. And then you can also set the key to a value. And when you're doing writes, then it does something special, which is that it's not quite printing its own source code. It's printing a variance of its own source code that now has the data you wrote inside of it.
00:58:58
Speaker
So you have to, if you want to keep your data, you have to be careful to redirect standard out to somewhere useful. And you can't, I mean, I think a normal Unix bash situation, you can't just redirect it to the file that you're executing because it'll like truncate that file before it even tries to execute it or something of that sort.
00:59:25
Speaker
redirect it to a different file and then move it or just keep both of them if that's what you want to do. But you're getting a copy of the database that has your modification in it. That is beautiful. It's kind of a mini datomic as well. It's kind of a mini datomic almost. Yeah, it's kind of a mini datomic. You can keep as many versions as you want. You know, it's great for backup and stuff like that. It's like next version, like a datomic.future. Yeah, that's right. Yeah.
00:59:54
Speaker
I mean, of course, there's like quadratic slowdown as you add more and more keys. Oh, that's the Q4. The what? The QQ is for quadratic slowdowns. Oh, yeah, that's right. I think it probably makes it more secure as well. It's less accessible to rainbow attacks.
01:00:18
Speaker
The rainbow attacks are about passwords and there's no passwords or any security involved here. That's where I want to store my passwords in the future. Come on. Yeah. All right. Yeah. Perfect. It's a key value store, username, password. Well, what are you talking about? I don't understand why this is less susceptible to rainbow attacks. I think that would just depend on your password hashing implementation, right? It's independent.
01:00:46
Speaker
Oh, I thought like the running of it after you store a certain number of, uh, a certain number of passwords. Oh, making it slower. You mean? Yeah. Yeah. Uh, yeah. So the fact that it would take a very long time to pull a password out of the database. Yeah.
01:01:03
Speaker
would definitely make some kind of attacks slower. Yeah, that's true. I mean, quadratically slower. Yeah. Oh, yeah. That is the idea. Is it really quadratic? Maybe it's just linear. The runtime is... Okay, now I'm disappointed. I mean, you think it should be. We need the big ores on this one. Yeah, exactly. There's something in the reading about this.
01:01:29
Speaker
So I was able to insert 100 key value pairs into the empty database in a mere 10 seconds, and the runtime of each operation is probably in login.
01:01:40
Speaker
I think they should be one of the themes of software development, right? I remember when I was, I think in Italy or something, there is something called slow food movement. So, you know, like all these rust people saying, oh, my shit is so fast and all that, and then we go to the other side, like slow software. That is our thing. Over the time, it goes slower and slower and slower. So you can relax and then you don't have a tea or whatever.
01:02:04
Speaker
insert into something and then you just go and have a cup of tea and then by the time you're back the insert is finished. Yeah, it encourages people to slow down and do other things. Are you all mindful? Yeah, chill out. Manjana. Yeah, I think that's right. We'll have your password for you, Manjana.
01:02:27
Speaker
I think this is going to be fucking amazing if we have test check testing coin DB that is getting slower and slower for every, and then that could be awesome. Yeah. Like, you know, shrinking is going to be really, really useful there. Arbitrarily slow. Yeah. Yeah. I did notice that you had test check on 71, so that's pretty impressive. Oh yeah. And I might've used it for coin DB to make sure it worked. I have,
01:02:56
Speaker
I have some unit tests in Ruby because I wanted to write them really fast. No, it's like the fastest thing I could like think of that needed to run a bunch of shell programs or shell out to a bunch of stuff.
01:03:14
Speaker
But I may need to just check, I don't know, but no. Go ahead. One of the things I, off topic really a little bit, one of the things I noticed was that you say the QuineDB requires Bash 4. And I just happened to notice today that Mac, the Mac uses Bash version 3. Yeah, go ahead and search here. And it, well, I know. And do you know why that is? I do not.
01:03:42
Speaker
It's because the Bash version 4 went to GPLv3. Oh no. So like, you know... No fucking way, you know, we're not having that. Wow. You can install it via brew, so I think you should definitely be friendly to the Makos guys and help them out with a brewing stall there.
01:04:09
Speaker
Provide the command. Yeah. In the next version, macOS will switch to Zshell, right? Or Zshell, whatever you want to call it. In the next version, they're going to switch to Zshell as the default one. I think that would be nice. So maybe you need to port it to... Yeah, it's already announced. So they're going to make Zshell as the default shell in Catalina or something, the next version.
01:04:35
Speaker
That might be, uh, I mean, I, I've resisted using alternate shells because I feel like the, uh, I don't like having to know several kinds of fundamental tools. Like I don't want to use more than one kind of text editor and I don't want to use more than one kind of shell. And I feel like you always have to know bash. Yeah. Um, but if Apple is switching to shell, maybe.
01:04:59
Speaker
maybe it'll become more ubiquitous. Yeah, but it's a bullshit reason. It's just because of this licensing crap, you know? Yeah, yeah. I mean, no matter what the reason is though, it might, I don't know if it's, is it available in modern Linux operating systems or do you have to install it? Z shell. Z shell. Oh, totally. Yeah, yeah, yeah. Let's just, you just type VSA, right? Oh, does that show? Yeah. Yeah. Does that say G? Not Z, not Z. Nope.
01:05:28
Speaker
command zsh not found but can be installed with sudo apt install zsh yeah zsh yeah yeah it's not there not there uh maybe well i think i think i think debbie in 2027 will probably catch up and then have this this one in this table what we're talking about now is like the the year of the zshell desktop yeah
01:05:49
Speaker
That's right. Yeah. Here's that show on the desktop. Uh, and there's also windows is trying to, to get all the Linux developers. Yeah. So that's another, another factor. Uh, I don't know if you have to get them to switch to the, I don't know. I assume they have bash. I don't, I don't know what else they'd be doing. Yeah. So, um,
01:06:18
Speaker
So, but what is, what is, uh, what are the other languages that you're looking at? What is on your radar now, apart from closure? Uh, I mean, I, I used to, to care a lot about languages. Um, like I was, I was advocating closure a lot, maybe six or seven years ago. Um, but I'm like, my personality is just really wishy washy and I don't like to commit to anything.
01:06:47
Speaker
Um, so as soon as I saw anybody having trouble with closure, uh, I was just sort of back down and like, I don't know what anybody should do ever. Um, so, uh, I mean, lately I've been, uh, more like professionally, I've been more interested in, uh, like working on, uh, just whatever, um,
01:07:13
Speaker
the business people think is important and trying not to have strong opinions about languages unless that really is the core of the problem. So you're going to be a global developer? Yeah, that's probably what's going to happen. You're going to be a SAP developer, aren't you? A SAP developer, is that what you said? No, SAP. Oh, SAP. I don't remember what that is. That's an old thing.
01:07:40
Speaker
Well, it's like an old and olden days version of Salesforce, you know? It's from what? An old school type of thing that Salesforce is now, you know, it's like an accounting resource management software. Everything. Salesforce has no language. A lot of factories and, you know, kind of like small businesses run on SAP. Small, yeah. The entire Germany. Them as well, yeah.
01:08:10
Speaker
Yeah. BMW runs on SAP. Yeah. Okay. Is it just a language or is it like a whole language? Yeah. It's like a whole ecosystem.
01:08:23
Speaker
Yeah, it's like a huge amount of software, including a database and all of the nonsense that comes with it. And then it has different modules to manage your HR, payroll, logistics, insurance, this and that, invoicing, practically the ERP system, enterprise resource planning. It's basically business software. But let's not talk about it.
01:08:45
Speaker
I mean, it's not as complicated as 71. I'm just saying, if you are really going to care about what the business think, then you're going to have to become a SAP programmer or something similar. Yeah. They're all about, they're all, you know, app things. Anyway. So what do your business care about?
01:09:10
Speaker
What, what'd you say? What does your business care about? What kind of things do they, do they care about? Well, they want to make money. Um, yeah. Uh, no, I, so there's a lot of, I work at a trading firm, um, your W and, um, you know, there's a lot of variety of people doing different things, different languages. Um, I think, uh, there's a lot of people that like Java in different ways. Um, you know,
01:09:40
Speaker
Anybody close to like data science kind of application, probably kind of Python, something similar. So, I mean, there's certainly people that use C++ fast. I haven't done that yet. I think that would be fun. At least it's like being done for a good reason, you know. It's not fun. It's rust. It's fun in a statistic sort of way. It's definitely fun. I mean, yeah, well, yeah. Get your kicks, that's what.
01:10:11
Speaker
I like, I like knowing how things work. And so like using a lower level language would force you to, you know, at least know more about things like processor details. I think you'll definitely know how things don't work. Yeah. Um, but I think C is still quite nice. You know, um, if you think there is a, like a particular subset of C plus plus that is nicer than C.
01:10:39
Speaker
Yeah. That's what people keep shouting on the Internet. I think Rust is a nicer version of C. Yeah, it's got more exceptions and yeah, it's a bit it's it's got it's more static typing. That's the main thing. Whereas with C you don't have that, which is kind of be very nice. The mixing is very flexible. But
01:10:57
Speaker
If you, if you use C in a particular way, will you get enough static type checking or can you not even opt into that? No, there's nothing. So it's got nothing. Yeah. Well, it's got things like, you know, integer and, uh, it's got, it's got enum, you know, union and a pointer somewhere. That's right. You can make a bunch of structs and get type checking on that. Not really. No.
01:11:20
Speaker
Really? Yeah. No, because usually you don't pass the structure by value, right? You just give a pointer once you have a pointer. Yeah. You just start filling it. So it's just a bunch of bytes and then pointing to somewhere and it could be anything. Yeah. That's a fun story. You think Closure's loose, you typed. Forget it, you know. It is pointing to some memory addresses that Loosely might follow some bullshit that you say, you know.
01:11:49
Speaker
But okay, so if you have a function that takes a pointer to some struct, and at the call site, it's, you know, what you have is declared to be a pointer to something else. Won't that be a compile error? Yeah, that'll be a compiler error. Like I know you can write code that will get around it, you know, the same way you can like typecast in Java. But I like what I want to believe is that if you are disciplined and, you know, avoid doing the trapdoor stuff,
01:12:18
Speaker
then you'll get static type checking. For level one, yeah. For level, for the very, very surface level, yeah. But it's almost impossible to stay at that level and see. I know a lot of the more OS-oriented libraries and functions are really insane to work with. You have to check Erno everywhere. Oh, yeah. But that's like Go, I think, is like that.
01:12:51
Speaker
There's something worse about it too, I think where you have to like save its value before you do anything in case it gets overwritten and then restore it or I don't know. It sounds like a lot of fun.
01:13:05
Speaker
But that's what if it is making money for business, why not? Yeah. I mean, it might take you 15 years to write the thing that you're making money for, but, you know, keep the fifth. Hey, you know, Linus made Git in, I don't know, what, a weekend or something? Is that what we say now? That's what you just said. So I'll buy it.
01:13:26
Speaker
Yeah, exactly. So he made it in Nest one weekend. And I see a lot of noise on Twitter these days, like 10x programmer or something. So if you're a 10x programmer, then it's like in two days, you can create a game. You can do anything in C in two days. Yeah. You're probably right. Anyway. Well, another direction for the language question is something I would be interested in seeing would be statically typed
01:13:56
Speaker
closure-esque language. The main difference from other statically-typed functional languages would be more of an emphasis on generic data. I think that's one of the more interesting things about closure. But I've never gravitated toward dynamically-typed languages in general. I like having a computer tell me that something's possible or impossible.
01:14:25
Speaker
You know, I could believe that maybe you just can't put your program into that paradigm and it's always going to be costly or something like that. But, you know, I still want to try. And so the one thing I think about a whole lot is like a language or VM that's based around JSON. So it has like a totally closed set of possible types. Like you can only have a map or a list
01:14:53
Speaker
or strings or numbers or Boolean. And that's it. You just have to assemble everything from that. And then you got static types around that. And there's lots of other ideas that probably don't actually work if you try them.
01:15:11
Speaker
You know, something like a little bit like JQ, but like a full fledged programming language. Yeah. Is this the, is this the main thing that that is kind of pulling you away from closure or getting? No, that's just a random fantasy. Um, no, I, the, I mean, using closure less than it's just that, uh,
01:15:32
Speaker
There's a lot of people doing other things with other languages. I'm just more interested in what the work is accomplishing than I am and what language is being used. Cool. But what are the main features in Closure that you would say that
01:15:55
Speaker
that were very valuable so far, of course, given the lack of static typing. Obviously, that is one thing that probably other languages, different paradigms have. But what would be the pros of Clojure in your experience so far? Just the general question of what I think is good about Clojure, I think of Clojure as being the combination of this
01:16:25
Speaker
pure functional core and then a lot of like really messy stuff for gluing it together and interoperating and doing things. And so I think there's a lot of value in trying to write pure functional code for your business logic as much as you can. Especially for things like debugging
01:16:54
Speaker
This happened to me like a week ago. You find out something in production is not doing what somebody expects. And you somehow get via logging or something like that. You print out the argument to the largest pure section of the code that's behaving as expected. And then you can just paste that into a REPL and run it
01:17:21
Speaker
on your version of the code and hopefully reproduce the bug and just iterate on that. And so I think that's fairly useful. That part would presumably apply to a statically typed functional language as well. So the, I,
01:17:46
Speaker
I don't know. Like I said, I'm a really wishy washy person. You're going to have a hard time getting me to like really sell something. No, no, no, you don't need to. I mean, I get certainly like, I know the tooling very well and so I can be very productive in it because I know like how things work and how to move around and accomplish stuff. And that's definitely not true for everybody. And you know, I,
01:18:17
Speaker
I think the generic data stuff is interesting to contrast with the more nominally typed functional programming you see in Haskell, etc., where they model things by creating a new type.
01:18:41
Speaker
Yeah. Um, so you're like, you've created a new kind of thing and it's something that can really only exist in your program. Um, and like if somebody created a type in another program that happened to have the exact same name, you like, it means something different probably. Um, and so like you're modeling only, uh, only talking about what about things inside your program.
01:19:09
Speaker
And I think Closure has this approach where it's attempting to give you modeling tools and other tools that apply outfit a program as well, like can be used in an open ecosystem of software. I have this analogy with Erlang where Erlang is to a large extent about concurrency and
01:19:39
Speaker
I feel like the rationale there is that you're going to have to like run your program on multiple machines and have a distributed program at some point anyhow, if your program is important enough. So why don't we just bite the bullet and write all of the code from the beginning as if it's a distributed program. And if it happens to be all in one machine, then that's cool, but it doesn't need to be. And
01:20:05
Speaker
So I feel like Closure does that kind of thing, but not about concurrency necessarily. I mean, a lot of like Closure's concurrency stuff only works on one machine, but it's about the data modeling and the fact that like the data is immutable because once you're passing data in between programs, effectively immutable anyhow. Like I can't call some web service and get a JSON response and
01:20:34
Speaker
then locally manipulate that response and expect that that has any effect on what's happening in the server. It's immutable in that sense and I should treat it immutably. And so I feel like Closure has this same sort of bite the bullet strategy of saying you have to pass immutable data around once you grow outside of a single process anyhow. So let's do that inside the program as well.
01:21:03
Speaker
Um, so ideally that, you know, leads you to programs that you can more easily split out because they are structured in such a way that you're just passing an immutable data from one part to another. Then you can do that from one machine to another and it's in a pay system way. Um, so that's, uh, like that to me feels like something you can't do in the statically typed functional programming paradigm.
01:21:31
Speaker
Not because of static types in particular, because of the nominal typing approach of make a new kind of thing to describe your data. So that's why I think it would be really interesting to have a structural type static type system for something that's like Clojure. I'm not sure that that could be bolted onto Clojure. I know that's what the core types library tried to do.
01:21:58
Speaker
I'm not an expert on static type systems, so I can't comment too intelligently on that. But it could be that one of the reasons that that didn't become more popular is that the language wasn't designed with that in mind. So I'm sure it was difficult to make a sound type system that described whatever closure happened to do.
01:22:22
Speaker
I think it works OK. I think it's not idiomatic. So it's an ecosystem problem, actually, because you've got types in one part of your program, but not in others. And it makes the value proposition a bit less compelling, basically. Yeah, the libraries don't have them. Yeah, yeah. Yeah. Yeah, I could see that. It was really slow for a while, too, I remember. Yeah, yeah.
01:22:53
Speaker
Well, that made it difficult. I tried using it for a year or two. Yeah. Very interesting project though. And he's got his PhD, so everyone's happy. That's what matters. Yeah, exactly. So, um, I think we are, wow. One and a half hour almost. Yeah. Awesome. Um, are there any other topics that you want to touch upon?
01:23:24
Speaker
I don't know. I mean, what do you like to talk about? Maybe a quick, quick, um, just of, uh, computationology talk that you gave. Oh, okay. What is it about? Uh, yeah. So that, that, that talk was, um, a, like an excuse for me to describe one of my favorite things from computer science.
01:23:53
Speaker
that I feel like is fairly unknown among programmers, largely because it's entirely useless, as far as I can tell. But I've got this part of me that's really fascinated with the set theory, infinite sets, that sort of thing, like different sizes of infinity.
01:24:18
Speaker
And I ran into that like 10 years ago. Probably one of my favorite things ever. So this is a part of computer science that sort of overlaps with that a little bit. And the talk itself, I broke into two parts. So like the second half is what I was just describing or didn't even describe yet. The first half is slightly more familiar, which is computational complexity.
01:24:48
Speaker
So like the talk is framed as what things happen mathematically when you ask the question, what can computers do? And so it's like looking at mathematical structures that come out of that. And so like one direction you can go with it is like, what can you do under certain constraints, like time or space, the computational complexities about, and there were
01:25:18
Speaker
That's a topic I enjoy. I don't know a whole lot about it the way an actual researcher would, but I think I know more than average about it. Enough to talk about it for a half hour and point out an interesting thing. I go into enough detail about what P versus NP means and then some of the more stranger associated phenomena.
01:25:43
Speaker
Most of the talks I do are like I pick some like overly ambitious topic because I really enjoy trying to figure out how to explain complicated things. It's one of my favorite activities and so that's what most of my public speaking is and I don't know if it is a good idea or if I succeed but you know I think I've
01:26:09
Speaker
I've done okay a few times. So I've kept trying up till now. So anyhow, first half is computational complexity. And there's a lot of topics like this, like I did this with quantum computing, where there's this topic that a lot of programmers know some surface amount about.
01:26:32
Speaker
You know, like quantum computing is a topic that you'll see a lot of summaries about and just like hand wavy stuff that's not really, like it avoids all of the mathematical details and is probably misleading because of that. And so I, you know, I like taking topics like that that people know a little bit about and then trying to go deeper in an hour than anybody else would normally try to by like just trying to think of clever ways to explain things quickly or illustrate them visually, something like that.
01:27:02
Speaker
Um, so, so I, that's part of what I did with computational complexity was, you know, like people know that P versus NP means, you know, some sound bitey thing. Um, so I tried to explain it in much more like detail and in a way where you can actually understand what the implications are and that sort of thing. But anyhow, the second half of the talk is, uh, about,
01:27:30
Speaker
A topic that I don't know if there's a good official name for it. I think sometimes it's called recursion theory or theory of computation. It's basically if you take the topic of the halting problem and then you just run after that and see what else you can figure out that has very little implications for programming. So the main idea is about
01:27:58
Speaker
the concept of an oracle, which comes up in computational complexity also. But it's like, what could you do with a computer if you had a magical oracle that could solve a particular kind of problem for you? So the most straightforward thing you can do with respect to the halting problem is say,
01:28:19
Speaker
Well, the halting problem is not solvable by normal computers. But if we had a magic oracle that knew the solution to the halting problem for every input, and then we stapled that to a computer so it could use it as a library or something like that, then what kind of computers would we have? And what would they be able to do? And they'd be able to solve the halting problem kind of trivially, and they'd be able to do lots of related things. But then there'd be another halting problem about those computers.
01:28:46
Speaker
We have these fantasy computers that can solve the halting problem, and you can run programs on them that may or may not halt. We've got this fantasy halting problem, and those computers cannot solve the fantasy halting problem. It's unsolvable. Now you can posit that you have an oracle for the fantasy halting problem, and now you have even more powerful computers that can solve even more impossible problems. Obviously, you can take as many steps as you want.
01:29:14
Speaker
Um, yeah. And you can go further than that. Like it gets really, it gets really bizarre. Um, so that's, that's what I talked about. All of the like weird things that come up when you do that. It's basically a talk about religion. Yeah, yeah, sure. The religion of numbers.
01:29:37
Speaker
Okay, I think maybe I think you need to come back again to explain all the quantum computing and computationology for us again. Okay, that would be fun. For now, I think we got to the meat of the...
01:29:53
Speaker
Yeah, exactly. We're going to continue on the next episode. Once we get deeper into 71 and then I think that requires its own episode, like the whole librarian. Yeah. Makes sense. I think that's valid.
01:30:10
Speaker
Yeah, yeah. So thanks a lot, Gary. Thanks for thanks for taking the time. And, you know, thanks for the test check, of course, you know, bringing this kind of testing to closure and hopefully, you will find more time to build the things that are going to make money for the business using closure or otherwise. Yeah.
Episode Wrap-Up and Announcements
01:30:36
Speaker
Thank you very much. I had a great time.
01:30:39
Speaker
Thank you. And Ray, any last words for this episode? Thank you, Gary. Yeah, it was really good. Very interesting. And I'm a big fan of the QuineDB. So let's keep it going. Well, it's good to hear. So all we need to do now is write migration scripts from every other database to QuineDB, and then we are ready. Yeah. Yeah, I'll let QuineDB on cloud. I'll accept pull requests along those lines. Awesome.
01:31:07
Speaker
All right, so I think this is the episode number 52 and maybe a quick logistical announcement. I think we'll be there at, not I think, but we will be there. Ray and I and probably Walter as well at Heart of Closure.
01:31:22
Speaker
August 2nd and 3rd in Loven. So hopefully if this episode is out before that event, stop by and say hi. That's a closure conference I can cycle to.
01:31:42
Speaker
yeah so it's super close and i think that gives away like it's in the middle of nowhere but it's belgium so you know belgium man belgium as the guide would say of course we're also on patreon so check us out and yeah i think next time
01:32:02
Speaker
We'll continue this amazing closure podcast journey into episode number 53 soon. And thanks again, Gary, for taking the time on Sunday and hopefully we'll meet in real life at some point. Thank you. Bye.
01:32:53
Speaker
Lemmy, from Motorhead. THE EYES OF SPADES!