off-topic

https://github.com/clojurians/community-development/blob/master/Code-of-Conduct.md Clojurians Slack Community Code of Conduct. Searchable message archives are at https://clojurians-log.clojureverse.org/
solf 2021-01-29T00:48:40.204400Z

> Historically, to pay your monthly bills in Brazil, you had to go to a bank branch and wait in line — often outside in the heat — until it was your turn. The lines wrapped around the block like that of an Apple Store upon the release of the latest iPhone. Being from Peru, this resonates with me 😕

clyfe 2021-01-29T15:31:01.206100Z

What is "strict paredit" as opposed to "paredit"?

2021-01-29T15:39:43.208700Z

paredit is about “Structural editing” strict paredit also protecting integrity of your code disallowing deleting of closing/opening parenthesis if it introduces inbalance s-expression For examle: calva: https://calva.io/paredit/ enable strict paredit by default

👍 2
1
dpsutton 2021-01-29T15:45:25.209500Z

the delete forward says it will prevent you from getting into an unbalanced state but the attached gif has an unbalanced close paren after a few deletions

🤪 1
flowthing 2021-01-29T16:36:27.210500Z

> It is common to conflate any interactive language prompt with a REPL, but I think it is an important aspect of Lisp REPLs that they are a composition of read-eval-print. I'm not sure I understand what that means. How is e.g. JShell or IRB not a "composition of read-eval-print"?

blak3mill3r 2021-02-03T04:06:26.453700Z

Yes, and in IRB for example, there is no distinction between read and eval (only the latter is provided and it takes a string of code)

flowthing 2021-02-03T06:57:27.454900Z

Right, I understand. What is the practical benefit of that from the point of view of using the REPL for interactive development, though? I understand the benefit in general (macros etc.)

2021-02-03T13:10:17.490600Z

For me it’s the tight iteration time that comes from working with a running program. I can inspect the working state of the program and re-define functions on the fly.

2021-02-03T13:13:21.490800Z

Note that most seasoned Clojurists recommend that you not usually type at the REPL prompt, but rather that you set things up so you can send forms to your REPL from your editor. You’re still just editing your program source files, but as you do so you’re sending bits and pieces over the REPL and updating your running program in real time.

flowthing 2021-02-03T13:17:27.491Z

Totally agreed, that's how I do all of my Clojure development. I guess what I'm really after is this: Imagine I'm a Ruby programmer who makes heavy use of IRB or Pry. A Clojurian comes along and says "Well, IRB or Pry aren't really REPLs. A Lisp REPL is a composition of read-eval-print." The Ruby programmer is like, "huh?", you know? Everything you said is true and that's already what I do, but I guess I'm just trying to figure out a way to explain the "composition" statement in such a way that someone who's used to a "non-compositional" REPL understands what I mean. I haven't used IRB or Pry etc. in a long time, but I think you can also use them to inspect the working state of the program and redefine functions, etc. You can't (easily) send things from the editor window into the REPL, but I guess that's more of a property of Lisps than Lisp REPLs, as such.

flowthing 2021-02-03T13:18:02.491200Z

I wonder if I'm making any sense. 🙂

flowthing 2021-02-03T13:19:28.491400Z

I guess it's just quite difficult to explain the benefits of a Clojure (or some other Lisp) REPL without actually showing what writing programs by evaluating things directly from your editor looks like.

2021-02-03T13:31:40.491800Z

Yeah, I’m not really sure what the “compositional” argument is about TBH.

flowthing 2021-02-03T13:32:28.492Z

Well, I think your initial comment was bang on.

2021-02-03T13:40:09.492200Z

I mean, if a Ruby dev can achieve a similar effect with IRB, does it matter whether IRB reads code differently from the regular Ruby startup? They might not find “composition” a compelling argument.

flowthing 2021-02-03T13:40:31.492400Z

Yes, exactly!

2021-02-03T13:40:35.492600Z

I come from a Java background so the differences are a little more stark.

blak3mill3r 2021-02-03T21:42:12.497500Z

I think what you're saying makes sense, and I don't think there is any benefit to R and E being separate composable pieces, in the limited context of typing strings of code and seeing the result of evaluating it. In that sense, the irb user is not missing out on anything.

blak3mill3r 2021-02-03T21:42:21.497700Z

except, as @flowthing said, macros and so on

blak3mill3r 2021-02-03T21:42:40.497900Z

but if you aren't modifying code as data then a REPL is a REPL even if RE are not decoupled

blak3mill3r 2021-02-03T21:43:13.498100Z

I would say irb is precisely a REPL where the RE are one thing

flowthing 2021-02-04T06:52:55.007Z

Yes, agreed. I believe we're on the same page. 🙂

flowthing 2021-02-05T18:41:28.098800Z

I guess I gained some new insight into this today... if you try to copy-paste multiple expressions at once into a Python shell, you get an error saying "SyntaxError: multiple statements found while compiling a single statement". I think @jkrasnay's first comment is bang on: with Clojure (and presumably with other Lisps), using the REPL is exactly the same as running the program via other means (e.g. via a main function or something), whereas that isn't (necessarily) the case with other languages. irb does allow you to copy-paste multiple expressions, but it might have other limitations -- not sure. In any case, I think that's what "composition" refers to: since reading is separated from evaluation, the REPL is guaranteed to work the same way as when reading forms from a file, whereas that's not necessarily the case with other languages.

flowthing 2021-01-29T16:38:51.210800Z

(I'm not trying to say that JShell or IRB etc. are as good as a full-fledged Lisp REPL — I'm wondering about the "composition" bit in particular.)

borkdude 2021-01-29T16:45:32.211300Z

Periodic reminder: there is a #contributions-welcome channel where you can ask for contributions for your OSS projects

borkdude 2021-01-29T16:45:42.211600Z

(this channel was called #pr-welcome before)

2021-01-29T18:50:41.212200Z

I think the point is that read and eval are the same building blocks that the Lisp uses to run your program. This means that you can do everything from the REPL that you can do by writing source files and running your program. In other languages, you can eval expressions at the REPL, but there are certain things that are out-of-bounds, such as adding new classes in Java.

flowthing 2021-01-29T19:27:49.212500Z

Thanks for the insight! That totally makes sense. :thumbsup::skin-tone-2:

λraulain 2021-01-29T19:42:35.217600Z

This might be a stupid question but i really wish to understand: Why do libraries and frameworks make so much emphasis on the fact that they might have just a few milliseconds faster startup times? For example does a 3 milliseconds difference in startup time really matter? or are developers just becoming too impatient ?

borkdude 2021-01-29T19:44:09.218100Z

@kraulain Can you give an example of this?

λraulain 2021-01-29T19:45:14.219500Z

Off the top of my head i can see this in comparisons of frameworks like quarkus vs micronaut

borkdude 2021-01-29T19:45:57.220500Z

The difference there isn't ms, it's probably seconds (when compiled to native which both frameworks support). And this can be a significant win in cloud environments.

👍 1
bherrmann 2021-01-31T01:09:20.272400Z

Starting fast also helps if your language doesnt support a repl... so if you can changed code -> deployed fast... then you can work faster.

2021-01-29T19:46:04.220700Z

the mirage project got ocaml startup times so low, they can feasibly spin up a new http server on demand for a request

🙀 1
2021-01-29T19:46:58.221100Z

oops, I mean start up a container running an http server :D https://mirage.io/

λraulain 2021-01-29T19:47:07.221200Z

You mean like it will be cheaper to run?

borkdude 2021-01-29T19:47:40.221800Z

yes

2021-01-29T19:47:43.222Z

it allows things like on demand scaling - I've worked on microservices that take multiple minutes to spin up

borkdude 2021-01-29T19:48:18.222800Z

also think e.g. AWS Lambda where you pay per nanosecond or something like that

👍 1
💯 2
2021-01-29T19:48:19.223Z

if it's seconds instead, you don't need to leave as much idle

λraulain 2021-01-29T19:49:18.223700Z

Yeah, i see. That makes total financial sense

clyfe 2021-01-29T19:51:26.225Z

In servers, 80% of the situations the runtime speed of code don't matter because the DB is a few orders of magnitude slower. And the most remaining 20% optimization gains pennies. What remains is HFT & Google electricity.

👍 1
clyfe 2021-01-29T19:52:34.225700Z

Relevant speed gains is babashka running circles on my antique laptop 🙂

λraulain 2021-01-29T19:54:40.227700Z

Yeah, I never thought of that. I think a single ms difference can be a big deal in High-frequency trading

2021-01-29T19:54:59.227900Z

both the jvm and the clojure language make multiple design decisions that trade more resource usage (read: spending more money on your containers per server) and longer startup times (read: needing to leave more servers running because "on demand" spinup is too slow), in exchange for runtime throughput (oops, the bottleneck was IO anyway...)

2021-01-29T19:55:33.228200Z

of course the thing clojure is really great at is optimizing programmer time (you probably spend a lot more on that than you do on hardware)

👍 2
clyfe 2021-01-29T19:58:44.228600Z

Large legacy clojure not that fun on programmer time. Immutability helps a lot, but no types is shaky business.

clyfe 2021-01-29T20:00:02.228900Z

Not that with types is so much better... 🙂 makes changes harder.

tvaughan 2021-01-29T20:02:55.229200Z

> 80% of the situations the runtime speed of code don't matter because the DB is a few orders of magnitude slower. Right. Which is why concurrency matters (more?) Some requests can only be sped-up so much. But certainly you'd never want to intentionally slow down other requests

👍 1
clyfe 2021-01-29T20:08:43.230600Z

• CPU-bound -> multiprocessing • I/O-bound, fast I/O, Limited Number of Connections -> multithreading • I/O-bound, slow I/O, many connections -> asyncio https://luminousmen.com/post/asynchronous-programming-python3.5 (was reading this the other day)

👍 1
pez 2021-01-29T20:10:38.233100Z

That is because the recording is cropped. The extra paren is from the outer scope. I'll re-record it, since it does look like Calva paredit is not delivering on its promise.

dpsutton 2021-01-29T20:14:31.233500Z

ah makes sense. the paren is colored black which made it feel even more like being highlighted as mismatched rather than from an outer scope.

pez 2021-01-29T20:21:48.234900Z

Yeah, the rainbows do work for parsing structure. 😃

borkdude 2021-01-29T20:58:13.238800Z

I am trying to come up with a glob function for a library (similar to clj-commons/fs) but there are some nuances. The API: (glob path pattern) Questions: - Should the behavior be recursive by default? Some shells (bash/zsh) and languages (Python, golang) seem to have conflicting opinions on this. - If not recursive by default, what would you make of (glob "." "**/*.md") then, the pattern assumes recursiveness - Should it include hidden dirs by default?

Ben Sless 2021-01-31T06:46:14.273Z

you can also refer to Tcl's implementation, might find it useful https://www.tcl.tk/man/tcl/TclCmd/glob.htm

alexmiller 2021-01-29T21:11:44.239800Z

Have you looked at the glob stuff built into java?

alexmiller 2021-01-29T21:12:00.240100Z

It’s a bit buried

borkdude 2021-01-29T21:14:06.240600Z

yes, that's what I'm building on, but they do not provide any function like this, only the raw building blocks

clyfe 2021-01-29T21:20:40.243200Z

Looking at ruby's https://ruby-doc.org/core-3.0.0/Dir.html#method-c-glob • not recursive by default • **/ makes it recur on the matched dirs • hidden files not included by default Generally ruby api follows unix forefathers wisdom.

alexmiller 2021-01-29T21:21:54.243900Z

Gotcha, I have written this too :)

alexmiller 2021-01-29T21:22:05.244100Z

Ish

borkdude 2021-01-29T21:41:02.244900Z

thanks! so **/ means recursive, instead of an explicit :recursive option right? (double checking)

clyfe 2021-01-29T21:51:10.245500Z

Yes. Also see https://ruby-doc.org/core-3.0.0/File.html#method-c-fnmatch

borkdude 2021-01-29T21:54:07.246200Z

perfect, thanks

👍 1
ghadi 2021-01-29T22:35:52.246900Z

That walkFileTree visitor in Java makes me so sad

ghadi 2021-01-29T22:36:21.247700Z

So bound to mutable state

ghadi 2021-01-29T22:37:19.248800Z

But IIRC it has hooks that the Stream-based variant doesn’t provide. Anyways, OT

ghadi 2021-01-29T22:38:02.249400Z

Oh, well this is the off-topic room 🎸

borkdude 2021-01-29T22:42:15.250Z

do you mean the DirectoryStream class? afaik this isn't like file-seq, it only lists one level deep

borkdude 2021-01-29T22:42:49.250300Z

it does take a glob object though, so for non-recursive globbing, I'm using that

borkdude 2021-01-29T22:49:43.251200Z

@ghadi yeah, I mean, what Stream-based variant were you referring to?

ghadi 2021-01-29T22:50:22.251600Z

Files.walk()

👍 1