Fork me on GitHub
#off-topic
<
2023-01-02
>
sheluchin15:01:51

Is anyone here using ChatGPT to help produce documentation for their project? I saw a fairly mature project on GitHub start an initiative to start writing more of their docs in this way. I guess there is some concern around losing clarity and detail, along with licensing questions, but it seems like a pretty good way to reduce the burden of maintaining a project. It can provide a good starting text and you can always make smaller adjustments to it manually. What do you guys think about this?

Alex Miller (Clojure team)15:01:30

Chatgpt is great at “form”, giving you a structure with plausible sounding text so if you’re using it that way, seems reasonable. It’s not so great at “facts” or at know what is useful/necessary to doc in the first place :)

4
sheluchin15:01:05

Indeed, you can't trust what it confidently tells you. You can, however, "prime" it with some data and ask it to make adjustments along the way.

eggsyntax15:01:02

> I guess there is some concern around losing clarity and detail ...and correctness 😉

2
☝️ 2
sheluchin16:01:27

I think concerns around correctness are a little misplaced in the case of having it help you write docs for your own project. Presumably, as the author of the project, you are able to discern between right and wrong. The idea is to tell it enough about your thing and have it formalize the language and glue it together, not for it to be source of truth which you accept at face value.

Jan K17:01:56

I asked ChatGPT to explain some of my most convoluted, uncommented code, a random function or shell script with no context, and was really surprised how well it did. In most cases it even correctly guessed the context where the code was used, though it couldn't really know. With some manual correction I think it would be very helpful for making actual docs.

eggsyntax18:01:36

That's fair, as long as it's something you can confidently check for errors, it seems somewhat useful! At that point I feel like it would be almost as easy to just write the docs myself? But I guess it would at least be faster, especially if it does a good job explaining the code in an order that would work well for readers.

jdavredbeard14:01:45

What I'd really like is some AI that will translate release notes into updates to the documentation to keep it in sync!

kulminaator16:01:25

i can usually understand what a piece of code does, i prefer the documentation to explain to me why the code is needed

kulminaator16:01:38

chatgpt is unlikely to cover that 🙂

😢 2
lilactown03:01:49

this is really cool. I remember Alexis giving a great talk on this a year or two ago

phronmophobic20:01:04

Just fell down a rabbit hole following links from that post. Lots of interesting ideas. I'm pretty sure the effect handlers that ship with re-frame, fulcro, and membrane are all accidental algebraic effect systems. I was curious if there were any existing clojure libs for algebraic effects and found https://github.com/brandonbloom/cleff. I'm still fuzzy on some of the ideas, but it's possible that https://github.com/leonoel/missionary, https://github.com/IGJoshua/farolero, and interceptors are also in the same category.

Max20:01:08

Interceptors aren’t in the same category afaik, but farolero definitely is. Common Lisp has delimited continuations (aka conditions and restarts) and Clojure explicitly opted to not implement them because it doesn’t fit well in the JVM’s execution model. Other attempts include Cloroutine, https://github.com/pangloss/pure-conditioning, and https://github.com/swannodette/delimc.

phronmophobic20:01:03

why aren't interceptors in the same category?

Max20:01:00

Conditions and restarts allow you to pause execution in the middle of a function, execute some other code, and then resume execution. Interceptors are functions composed in a chain that can alter the evaluation of downstream functions. They don’t allow you to suspend or resume execution. Though perhaps I’m looking at different criteria than you, what seems similar about them to you?

phronmophobic20:01:46

I was comparing interceptors to algebraic effects systems.

phronmophobic20:01:26

> Interceptors are functions composed in a chain that can alter the evaluation of downstream functions. If you can insert "some other code" at the beginning of the remainder of the chain, how is that different from "Conditions and restarts allow you to pause execution in the middle of a function, execute some other code, and then resume execution."?

Max20:01:18

Imagine a simple effect called helloWorld which, when executed, prints “Hello, world” to the screen. That effect could be issued from anywhere inside a function or even within functions called by that function, that code is a black box to the effect system. All the effect system knows is that when helloWorld is triggered, it does its side effect. How might you implement such an effect as an interceptor? An interceptor can choose whether downstream code is executed, but can’t do things when requested by downstream code, it’s done running by the time the downstream code runs. The important part is that the downstream code is what gets to decide when and where the effect occurs, not the effect system.

phronmophobic21:01:28

> An interceptor can choose whether downstream code is executed, but can’t do things when requested by downstream code I'm not sure I understand what you mean by this. I'm not familiar with all interceptor implementations, but re-frame's interceptors allow you to modify the context and the control flow from within an interceptor. It may be clunky or require a workaround, but it's probably possible to achieve the same result. One of the reasons I labeled these options as "accidental" algebraic effects systems is that they often have similar goals, but these implementations are probably less rigorous and less general.

phronmophobic21:01:57

> How might you implement such an effect as an interceptor? There's probably a re-frame issue that describes a similar problem and a workaround. I'm interested in learning more about these more formal descriptions because I think they could provide a more general and rigorous approach. I was thinking of them in the same category because I think interceptors are being used to try to solve a problem that algebraic effect systems and continuations might be able to solve more cleanly.

Max21:01:10

I encourage you to try implementing an effect system with interceptors, I think the differences will become clear pretty quickly. Here’s an example to try: An effect handler wraps a function that may or may not trigger an effect. When triggered, the effect pauses execution of the wrapped function, prompts the user for input, and based on that input, either returns execution to the wrapped function or bails and returns to the effect handler. It’d look kind of like this:

(defn wrapped []
  (doseq [x (range 10)]
    (if (= x 3)
      (effect)
      (println "Waiting...")))
  {:error false})

(defn effect-handler []
  (println "Enter an even number")
  (print "> ")
  (let [x (read-line)]
    (cond
      (nil? (parse-long x)) {:error true, :type :not-num}
      (even? (parse-long x)) (continue)
      :else {:error true, :type :not-even})))

(defn wrapper []
  (let [result (handle-effect effect-handler 
                 (wrapped))]
    (prn result)))
When used:
Waiting...
Waiting...
Waiting...
Enter an even number
> 
If you enter 3, you’ll see
{:error true, :type :not-even}
If you enter foo, you’ll see
{:error: true, :type :not-num}
If you enter 2, you’ll see
Waiting...
Waiting...
<repeated 4 more times>
{:error false}
The challenge is to implement handle-effect and effect. You can do such a thing with exceptions and dynamic vars pointing to functions, which afaik is basically what farolero does. To me at least, interceptors seem fairly orthogonal to the above.

phronmophobic21:01:53

My point wasn't that you could replace an effects system with interceptors, it's that I think it might be a good idea to replace interceptors with an effects system. If you look at how interceptors are being used, it seems like it might be possible to switch to an effects system without changing much code while providing more features and making it easier to understand.

phronmophobic21:01:43

Do you think effects systems would be an inappropriate use case for the areas where interceptors are being used?

Max21:01:44

I think it depends on what you’re using interceptors for. I could see how in certain cases what specific interceptors do could be better accomplished by an effects system, e.g. the classic exception interceptor. In other cases the seem fairly orthogonal, like with Ring’s HTTP-parsing interceptors. I could even see adding effect handlers to the stack by putting them in individual interceptors. I’m not super familiar with the use of interceptors in re-frame though.

phronmophobic21:01:02

Yea, I tend to think of middleware as a separate use case. For an effects system, I'm really just focusing on how re-frame uses interceptors. It's also the same use case as fulcro's mutations, and membrane's handlers.

phronmophobic21:01:12

I'm not familiar with ring's http-parsing interceptors. Is that the same as ring's middleware? Afaik, ring's middleware doesn't allow you to reorder the queue of pending ops or modify the context (eg. what handlers are used for each effect).

Max21:01:04

Ring does use middleware, I mistyped. Pedestal uses interceptors, but mostly for the same things Ring uses middleware for

phronmophobic22:01:18

Also, it seems like pedestal's queue manipulation example is pretty similar to your challenge, http://pedestal.io/guides/what-is-an-interceptor#_error_handling. Is that on purpose? It seems like if their example just read from standard in, instead of parsing the context, it would be pretty similar to your example, no?

Max19:01:08

Yeah, that’s an example of the classic “error middleware” I mentioned above. It only solves half of the problem though: while it can interrupt execution and move to a higher point in the stack, the handling code higher in the stack can’t choose to resume execution at the point where the condition was raised. Sure you could work around that by encapsulating the resuming logic and having it be called by the down-stack code, but then the up-stack code doesn’t have full control over how the condition is handled. IIRC what farolero does is store the current set of handlers in a dynamic var, and the function that raises conditions first looks for handlers in the current context, and then if the handler decides to bail it throws a special exception. So while you can build something resembling a condition/restart system in Clojure today, it comes with a bunch of caveats: what if someone accidentally catches your magic exception? Will other devs/tooling recognize your system and e.g. warn when you’re missing a handler? etc. etc. Language support both makes these patterns work more cleanly and pushes the community to coalesce around the approach and build tooling for it.

Carlo21:01:30

Nice! I remember seeing Alexis' talk when this work was announced. Does this mean that we'll finally see the completion of the eff library? I lost touch with the effect libraries efforts in the haskell community, how did the situation progress?

lilactown18:01:11

I think that re-frame effects and algebraic effects might be solving similar problems but they are quite different in what capabilities they have in terms of code structured & semantics. the reason that effects require delimited continuations is because the fundamental thing that they provide is the ability to mutate the execution of a program.

phronmophobic18:01:03

algebraic effects also give you the ability to observe and simulate the execution of a program

phronmophobic18:01:23

which is also a shared goal with projects like https://github.com/day8/re-frame-10x

phronmophobic18:01:17

I think https://github.com/day8/re-frame/issues/639 is a good example of a current re-frame issue where it might be interesting to compare re-frame effects with a hypothetical algebraic effect option.

lilactown05:01:28

I'm not really sure how that issue is interesting re: algebraic effects. Algebraic effects are ordered like any other code you might write; re-frame is just weird because they initially chose to represent side effect data as a map of keys