Fork me on GitHub
#off-topic
<
2024-03-21
>
mauricio.szabo00:03:55

Folks, I decided to do something weird. Because I'm starting a Ruby job right now, and I didn't want to lose my workflow in Clojure, I am trying to migrate my workflow to Ruby. That means, porting nREPL to Ruby, then porting Chlorine to work with Ruby code. It... surprisingly... works, in a way 😄 There are some tricks, obviously. I do "watch" methods to save the local bindings and such; I also have some magical parsings to better capture if what I "watched" is useful for that method or not. But it does work 😄

👍 1
👏 6
🤯 1
❤️ 1
Noah Bogart00:03:03

How does reloading code work internally?

mauricio.szabo00:03:46

It's basically a load-file

mauricio.szabo00:03:45

But there's also a load-file-and-inspect which rewrites the methods to add a NREPL.watch!(binding, <some-id>) at the end of each method, keeping the return code

mauricio.szabo00:03:11

Ruby is more "dynamic" than Clojure, so just reloading the class overwrites all methods and things work properly

👍 1
Noah Bogart01:03:57

even instances? that's very cool

mauricio.szabo01:03:05

Yep, this video shows examples of some instances being evaluated too ;)

vemv04:03:35

If I tried to move my clojure workflow to Ruby I'd be fired sooner than later 😄 I mean, that would be a never-ending endeavour... However I tend to be very happy with https://github.com/dgutov/robe - very impressively accurate/fast set of features without going the Sorbet path

Stef Coetzee10:03:20

Men will literally port their Clojure workflow to Ruby than leave the REPL 😜

😂 2
mauricio.szabo12:03:52

Oooh, I did so much more than port only the Clojure workflow hahahahhaa

😂 1
mauricio.szabo13:03:14

I mean, I'm even developing the whole freaking editor :rolling_on_the_floor_laughing:

😂 3
mauricio.szabo12:03:34

There's an interesting side-effect of me trying to promote this idea/plug-in to the Ruby community (so much that I'm also sending to the channel because it's almost a different discussion) - the "paradigm shift". For now, I sent this example video (and another one) for 4~5 communities. So far, the community that was most active, gave me more feedback, and overall was more interested and surprised, was this one - all the other 4 (that were Ruby communities, by the way) commented one or two things, and that was it. It seems that REPL-Driven is indeed a great shift on how we think about programming - to the point that people that haven't experienced it don't even imagine it changes so much, and in a way, end up not caring... What do you think?

vemv12:03:13

Isn't Rails (Ruby, even) essentially a not possibly repl-driven environment? i.e. you can have irb, but you can't modify the running Rails server (that is, with the same guarantees/expectations you'd get in Clojure) Which in practice isn't as terrible as it sounds, since Rails has code-reloading for free (which is notable more than transparent than in Clojure - I never find people discussing about anything like "tools.namespace" for Rails - they have code reloading, they know nothing about it except that it works) All this is to say, in absence of a big problem, people can be understandably less interested in innovations.

ericstewart17:03:16

I work in Ruby a lot (though trying to work more and more in Clojure), and I think it is very much like @U3Y18N0UC first said - it is difficult to get developers to really care or even pay attention if they haven't experienced it. Even watching a demonstration doesn't sell it often. Many people need to experience the feedback/flow to really appreciate it and you can't really get that full experience yet in Ruby. It's just hard to break the perception that all repls (Ruby, Python, JS, etc) are basically the same, probably because the repl is just part it. You've got to get to the point where people can easily feel it, not just read/hear about it or see it done (though those may encourage a few to try) I know there have been attempts over the years to bring Ruby close (interactive_editor, irbtools, Utility Belt, pry) and I'm very interested in what you are attempting here for any continued work I do in Ruby. I hope your efforts can not only improve Ruby workflows but also help steer people to Clojure when they realize the experience there will probably be better then ever possible in Ruby

jpmonettas19:03:13

IMHO getting the hang of interactive development takes a long time, even when using languages designed specifically for it like Clojure, where interactivity is much easier to explain, since the compiler is form based (instead of files), almost everything is stateless, so when you re-eval a piece of code you are almost always swapping a function, all this possible because namespaces and vars. The cognitive load when trying to do interactive development on object oriented systems is higher in my opinion, since you have instances with state everywhere. So what does it mean to add/remove a method to a class, to add/remove a field, to delete a class. What happens to all the instances living. How running threads interact with all this changes? If I remove a field from a class what happens to all methods that are maybe currently running and using this field?

mauricio.szabo19:03:42

@U45T93RA6 currently, no - Ruby is not a REPL-Driven. That doesn't mean it's not possible - we just need to change the workflow a little. Ruby is more dynamic than Clojure - if you redefine a method, in runtime, in Ruby the new definition is used instead of the old one. In Clojure, (defn something...) essentially defines a new version of that function - in Ruby, it literally mutates the class. That means that, indeed, it is possible to modify the running server - and my project is actually doing that right now 😅

mauricio.szabo19:03:22

The bad part (actually, the horrible part to be sincere) is that Ruby is a highly complex language. You have three different "kinds" of classes, you have self-referentiating instances, self is weird in some cases, you have closures but only if you don't define classes or methods (or unless you define it in a special way), there are lots of magical stuff, you can't "copy-paste" code from the editor to a REPL, there are an insane number of ways to do the same things and in some cases, spaces don't matter and in other, they do, there are "contexts" that are essentially different things (methods, class methods, the class itself, spec files - currently I only support methods and some kinds of class methods - it's not always simple to understand that something is a class method) and other stuff.

mauricio.szabo19:03:15

At the same time, there's something that helps - binding. For some reason, Ruby decided that the current binding needs to be an object. That helps me in the sense that I can easily "instrument" the code and keep all local variables, self, instance variables, and other stuff, essentially forever. This all means - the Ruby workflow will probably never be "evaluate block", or "evaluate top-block", or things like that. In Lazuli (my plug-in) it translates to "load file and inspect" to generate "watch points", then an interaction with the app (that can be anything - run a test, visit an URL, even run a code in Lazuli itself) so that watch point can store the "current binding" basically. Starting from this point, basically everything is the same as Clojure - even with autocomplete and go to var definition.

mauricio.szabo19:03:31

@U068R74HE which editor are you using? Currently, Lazuli is only available for Pulsar, but supposedly there's nothing in it that make it "pulsar-specific", and considering that I'm using the same approach as my other plug-in Chlorine, it might even be easy to port to VSCode actually

ericstewart19:03:35

I mostly use Spacemacs(Emacs) but I occasionally use VSCode too. I had never heard of Pulsar actually. So many editors…. Edit: Ah, I'm slow. I hadn't realized that Pulsar is the evolution of Atom.

mauricio.szabo02:03:39

No worries, Pulsar is basically a community effort to keep the editor, spreading the word that it exists is important but it's not the first priority in our list 😄

Joseph Graham04:03:55

An example of a ChatGPT win:

🙌 1
Joseph Graham04:03:20

Though it might be more efficient to not count the length of the collection every time I guess

Duminda04:03:57

FYI, Claude Opus is way better at Clojure than ChatGPT 4 in my experience.

Joseph Graham04:03:39

Wow cool. I heard some talk of "Devin" too.

Joseph Graham04:03:35

Wow you're right. Even the free version of claude wrote the same function, but gave it a more sensible name.

Joseph Graham05:03:07

now I just need to decide what subscription to cancel so I can afford Claude Pro

adi06:03:51

LLM skeptic here... Before I critique anything, technologically, it's wild that a system can do even this much. No arguments about that. However, this code is going to fail my bar for code review and for productivity. 1. This naive solution will always check :first and :last for all items in the collection, whereas the common case is :middle. 2. The dec is redundant too in each iteration. 3. It is missing a check to make sure the input coll contains at least three elements (the semantic guarantee we seem to want). 4. The cond may not be necessary at all. I'm sure there is a solution that will produce output that is correct by construction. Curious: what does it do if you tell it to not use branching logic? 5. Overall, the solution is of low educational value. If it revealed map-indexed for the first time, that would be somewhat useful. Clojure docs has better odds of revealing the same. Barring that, it's a plain old imperative solution, like any other popular language out there. 6. The solution took way too much scrutiny even at the naive level and is not worth the mental effort expended to figure out the prompt.

👍 2
adi06:03:47

Not bad at all :)

Duminda06:03:32

I've tried generating Clojure with Chatgpt 4 mid last year. Chatgpt couldn't even give me code with balanced parens. And it obviously didn't know anything about Clojure. I don't know if it's improved since. I've tried Claude at a few small Clojure code generation tasks (Including elisp code generation). It certainly hallucinates and makes up stuff if you push it long enough, but it's way smarter than chatgpt.

👍 1
adi07:03:12

BTW, the nice thing about the solution you posted is that it works for coll of size 0, 1 (has only :first), 2 (has only :first and :last), and more (has :first, :middle s, and :last). And that is because repeat conveniently floors out at 0 (negative numbers are zero, instead of being errors). This is why a "by construction" implementation can be more correct, more directly, than imperative ones.

👍 1
adi07:03:28

Though, this particular question begs the question, why stuff extra data into our existing data, instead of using functions? last, first, and (def middles (comp butlast rest)).

practicalli-johnny07:03:16

Fail: no docstring

😅 2
💯 1
adi07:03:50

Anyway, not to beat on the poor LLM too much (not that it cares). I am happy to watch and wait and remain poor by missing out on the gravy train 😅.

😄 1
Duminda07:03:27

Except there's no gravy 😅

1
Samuel Ludwig15:03:11

honestly, this is one of the first times i've been impressed by a model, never heard of this one before

Joseph Graham04:03:34

@U051MHSEK in answer to your question, the use-case is rendering a table in html where the first and last items are special cases due to buttons for changing the order:

Joseph Graham04:03:02

I realised this function wasn't suitable due to the special case where there is only one item so ended up annotating it with a map with boolean values for :first and :last (both may be true). Claude Opus wrote me this (docstring added by me):

(defn annotate-positions
  "we need a way of knowing if the element is first or last."
  [coll]
  (let [coll-count (count coll)]
    (map-indexed (fn [idx item]
                   [item {:first (zero? idx)
                          :last (= idx (dec coll-count))}])
                 coll)))

Vincent01:03:51

I am hitting usage limits on just one AI friend, so having 2 is good to jump between x) intense development / intensive innovation bursts

Joseph Graham15:03:40

I found a prompt that GPT-4 succeeds at and Claude Opus 3 fails at:

This Clojure function gives a syntax error "Unable to resolve symbol: bla in this context". can you help me fix it?

(defn vector-fn-keys
  "given a vector of maps, a key and a function, transform the value of that key
  in each map"
  [vec-of-maps key fn]
  (mapv (fn [bla]
          (update bla key fn))
        vec-of-maps))

💡 1
Duminda09:03:28

Is there a practical apporach to approximate a curve in an image as quadratic bezier curves? Any tools?

p-himik09:03:41

There are tools that convert raster images into vector images. Not perfect by any means, but sometimes can help. Of course, if you know additional details about the image, you can do it yourself in a much more precise way by using e.g. OpenCV to extract lines and then converting those lines into curves.

👍 1
Duminda09:03:02

I tried couple of jpg->svg converters online and they produced horribly long paths. > OpenCV to extract lines ok will check this out.

Nundrum18:03:49

I came across this project recently, and it claims to have compact output: https://github.com/visioncortex/vtracer

👍 1
Duminda18:03:03

@U02UHTG2YH5 Thanks, will take a look

jpmonettas16:03:21

I'm not a mac user but for people using OSX and thinking to upgrade to 14.4 I just found this https://blogs.oracle.com/java/post/java-on-macos-14-4 after a FlowStorm user told me it stopped working. Looks like many things could fail. In the case of FlowStorm pushing JavaFX to 23-ea+3 seems to solve the issue.

p-himik16:03:38

(Granted, a different channel with fewer people.)

jpmonettas16:03:28

oh, great, haven't seen it

seancorfield16:03:24

Not everyone seems to run into the issue but if you do, you're hosed since you can't easily roll back the update and you can't use any version of Java if you are hitting the issue. In another Slack, someone was complaining that corporate IT forced all Macs onto 14.4 without knowing about this issue 😞

facepalm 3
1
Lari Saukkonen17:03:12

I have 14.4 and been running it now for a week without issues. 🤞

p-himik19:03:30

Seems 14.4.1 fixes it.

🙌 3
emccue23:03:38

Any opinions on nushell? I've been doodling on using it over bash since it is cross-compatible with windows

Nundrum23:03:21

It's a very pleasant experience. I like where it is going. However, it had several major failings for me, enough so that I couldn't adopt it. The biggest was not being able to get compact output. Really, I don't need ls to fill the whole screen with details I don't want. And nu eschews using flags to control things way too much. Everything-as-a-table eventually becomes tiring when you're moving fast. The second biggest was the vi-mode was lacking.

mauricio.szabo12:03:34

There's an interesting side-effect of me trying to promote this idea/plug-in to the Ruby community (so much that I'm also sending to the channel because it's almost a different discussion) - the "paradigm shift". For now, I sent this example video (and another one) for 4~5 communities. So far, the community that was most active, gave me more feedback, and overall was more interested and surprised, was this one - all the other 4 (that were Ruby communities, by the way) commented one or two things, and that was it. It seems that REPL-Driven is indeed a great shift on how we think about programming - to the point that people that haven't experienced it don't even imagine it changes so much, and in a way, end up not caring... What do you think?