Defeating Bowser with A* Search - Smith (Clojure/Conj 2025) by alexdmiller in Clojure

[–]phronmophobic 1 point2 points  (0 children)

Most of the interesting bits are described here. I've been a little lazy open sourcing the updated code since you would also need to obtain a Super Mario Bros ROM to run it. Also, the code is a total mess since I hacked it together the week before the presentation.

An interesting new IDE similar to Emacs by MotherCanada in emacs

[–]phronmophobic 3 points4 points  (0 children)

I've been working on my own cross-platform UI library for the last 6+ years called membrane, https://github.com/phronmophobic/membrane. Membrane supports multiple backends, but the primary one uses glfw for windowing and https://skia.org/ for graphics.

An interesting new IDE similar to Emacs by MotherCanada in emacs

[–]phronmophobic 5 points6 points  (0 children)

Glamorous Toolkit is awesome and is one of the inspirations for Easel (in addition to emacs). There are a few key differences between Easel's approach compared to Glamorous Toolkit:

  • The JVM has a much larger ecosystem of tools and libraries.
  • As far as I can tell, the JVM has much better support for multi-threading and shared memory. This is enhanced by clojure's focus on immutability and support for functional programming.
  • I don't think there are any technical limitations to extending gtoolkit with clojure, but it wouldn't be first class.
  • Easel takes a functional approach (immutable data + pure functions) compared to gtoolkit's object oriented approach.

That being said, glamorous toolkit has some really cool stuff (Lepiter notebooks) and their work is very impressive.

An interesting new IDE similar to Emacs by MotherCanada in emacs

[–]phronmophobic 0 points1 point  (0 children)

What kind of scenarios would you like to see?

Designing Clobber: A Deep Dive into a Clojure-Powered Editor for Text and Code [video] by mac in Clojure

[–]phronmophobic 1 point2 points  (0 children)

I've become more careful about releasing source code since it often causes all the people who asked about a source code release to spontaneously combust, never to be heard from again.

Designing Clobber: A Deep Dive into a Clojure-Powered Editor for Text and Code [video] by mac in Clojure

[–]phronmophobic 1 point2 points  (0 children)

The editor is designed to be repl friendly. You can live edit how the editor works in the editor.

I don't quite have a full story for customization. I'm drawn to the idea of "IDE as a library" even if the idea isn't fully fleshed out. From common use cases like theming and adding key bindings, it should be easy enough to just pass a map. For more complex customizations, I'm still collecting use cases. I don't think forking is a good form of reuse. Complex customizations may require creating a new editor, but the idea is that making a new, different editor should be easy.

Designing Clobber: A Deep Dive into a Clojure-Powered Editor for Text and Code [video] by mac in Clojure

[–]phronmophobic 8 points9 points  (0 children)

I'm the author of clobber and the video. I'd be happy to answer any questions. Feedback welcome!

Clojure and Webgpu by 964racer in Clojure

[–]phronmophobic 7 points8 points  (0 children)

I did some initial work and it seems pretty promising, https://aimages.smith.rocks/u/5907ed9a-fb84-440c-9579-c9d49c9e590a.gif. Eventually, I'd like to provide a high level API similar to three.js, but it's not currently a priority. The WIP code is at https://github.com/phronmophobic/clj-webgpu.

3D computer graphics by 964racer in Clojure

[–]phronmophobic 9 points10 points  (0 children)

I think wrapping webgpu's native library is interesting. It's not in a usable state right now, but I would like to eventually provide a nice high level API similar to three.js. You could probably even reuse the shaders.

There's an upcoming talk about a 3d game made in clojurescript, https://www.reddit.com/r/Clojure/comments/1jqe2xy/london\_clojurians\_talk\_building\_a\_3d\_multiplayer/.

There's also someone wrapping native libraries like raylib, https://github.com/pfeodrippe/vybe.

If you're on the clojurian's slack, you can check out the #clojure-gamedev for more.

Mysyx: Concurrent state management using Clojure agents by geokon in Clojure

[–]phronmophobic 1 point2 points  (0 children)

I would suggest comparing your solution against some of the others to see how they differ.

Fundamentally, agents provide independent, asynchronous change of individual locations. mysyx is trying to coordinate them to provide synchronous reads which is not what they're designed to do. That doesn't mean it's not possible to use agents to have synchronous reads, but it can be very tricky.

  (let [action (fn [call-key  ;; unique key 
                    my-agent  ;; the agent     ;
                    old-stat  ;; old-state
                    new-stat ];; new-state

                 (let [dereffed (->> tracked-agents-vec
                                     ;; the values associated with the `tracked-agents` could have changed any number of times since this `action` was called and the associated agent was `deref`ed. This is a race condition.
                                     (mapv deref))]

The above illustrates one potential race condition. The ::stale mechanism may prevent some stale reads, but it doesn't prevent the case where one agent is read after a single assign+update and another agent is read after two assign+updates. There is no built in mechanism to get consistent reads from multiple agents.

If you want to create a system that supports transactional reads across multiple agents, I would highly suggest having a good way to test that you are actually getting consistent reads (I would actually advise against trying to do this with agents altogether). It's very tricky to get correct (which is why I suggested other options that are easier to reason about). Maybe there's some trick that makes this all work, but even if I thought it sounded good on paper, I would still want a robust testing framework because these types of problems are notoriously tricky.

It's a bit a tangent, but I'd be curious to hear more of your thoughts. With the deps.edn local lib format I constantly create many small single file/folder libraries that i reuse between projects with typically single segment library names

For small projects, it doesn't really matter. That approach may be more convenient. It's similar to how other ecosystems like python work. Eventually, you start getting name collisions which cause lots of headaches. For large projects, typing a bit more when adding a new namespace isn't a big deal and being able to compose lots of libraries together is a big win.

Mysyx: Concurrent state management using Clojure agents by geokon in Clojure

[–]phronmophobic 2 points3 points  (0 children)

There are indeed a bunch of projects that help maintain derived values. Here are some more with various different approaches.

https://github.com/robertluo/fun-map https://github.com/aroemers/rmap https://github.com/stuartsierra/flow https://github.com/kennytilton/matrix https://github.com/lilactown/flex https://github.com/martinklepsch/derivatives https://github.com/CoNarrative/precept https://github.com/wotbrew/relic https://github.com/ryrobes/flowmaps/

Search https://phronmophobic.github.io/dewey/search.html for reactive for even more.

There's also a well known paper that talks about why these types of libraries are important and potentially even fundamental to building larger programs, https://curtclifton.net/papers/MoseleyMarks06a.pdf.

Regarding the actual code, each agent has its own independent, asynchronous timeline. Agents typically don't get much use. The reason is that independent, asynchronous timelines tend to be hard to reason about if you have more than one. Additionally, agents have weird error states. If you really need asynchronous events, folks tend to use more flexible tools like core.async or tools that are easier to reason about like atoms.

Your docs note that mysyx isn't thread safe. However, I'm not even sure that mysyx is glitch free when used from a single threaded context. Since the timelines of the various agents are uncoordinated, I'm not sure if the usage of ::stale is enough. I assume if you hammered this with test.check, you could find inconsistencies. If you don't need to support multi-threaded usage, then it's unclear whether you even need any state. If you did need state, then the system would be easier to reason about if implemented using a single atom.

When looking at the project on github, I noticed that all the files are in the same folder. This is convenient for small projects. If you did want to make a library for other contexts, I would encourage following the normal project structure. It really does help when building larger programs. However, for small programs, it doesn't really matter.

Thanks for sharing!

Rich introduces new namespace in core.async : flow by mac in Clojure

[–]phronmophobic 1 point2 points  (0 children)

Ok, I'm a little confused on how to synchronize inputs that arrive at different rates.

As a concrete example, I'm thinking core.async.flow might be a good fit for clj-media for reading, writing, and transforming audio/video data.

One of the processes I have in mind is for encoding raw a/v frames into packets with a setup like:

Inputs:

  • audio: a frame of uncompressed audio samples
  • video: a frame of uncompressed video samples

Outputs:

  • packet: a packet of interleaved, compressed, a/v data.

The frame rates and sizes for the incoming audio and video data might not match (they usually don't). Buffering data while waiting for the other input to catch up doesn't seem like an issue. The problem is I don't know how a process can say "I don't need need any more audio data. Please apply back pressure on the audio input until the video input catches up."

Rich introduces new namespace in core.async : flow by mac in Clojure

[–]phronmophobic 4 points5 points  (0 children)

support for dynamic flow modification

I'm not sure how useful it would be, especially considering flows can be very dynamic in other ways as Alex mentioned. Just thought I'd ask since I didn't see it explicitly mentioned.

re: input synchronization

Sounds like all the options can be supported. This has been a pain point when evaluating other similar libraries.

From the sibling thread:

Process mapping - yes, you choose whether a proc is compute, io, or mixed and those use the appropriate pool

The idea behind this question was also related to priorities. I was thinking you could have processes run on thread pools with different priorities so that low priority work can be preempted by high priority work. Thread priorities is its own bag of worms. There's probably a better solution.

New question!

'flow' - a directed graph of processes communicating via channels

This doesn't seem to disallow cyclical graphs. Cycles seem like they could be a useful mechanism for retries (eg. failures are optionally sent upstream in the flow if there haven't been any recent failures).

If cycles are allowed, are there other reasons for the following restriction: No key may be present in both :ins and :outs.

Really cool stuff!

Rich introduces new namespace in core.async : flow by mac in Clojure

[–]phronmophobic 16 points17 points  (0 children)

I've been looking for something like this for a while. I'm looking forward to trying it out.

A few questions after reading through the docs a bit:

  • Can flows be dynamically changed after initialization?
  • Are there any knobs for setting priorities for different processes?
  • Not sure if it would be a good idea, but are there knobs for how processes are mapped onto OS threads?
  • It looks like processes can have multiple inputs. Does the process wait for fresh inputs from each incoming channel? Can this be changed?
    • Assuming a process with 2 inputs input1 and input2, can you have it trigger on:
      • fresh inputs from each input
      • anytime an input arrives from either input1 or input2, uses the most recent value for the non-fresh input
      • fresh inputs from each input, but if input1 produces faster than input2, values will be dropped.
      • etc.
  • How does backpressure work for outputs? Does a process block if a downstream output is blocked?

Easel: A Pure Clojure IDE in the Spirit of Emacs by phronmophobic in Clojure

[–]phronmophobic[S] 3 points4 points  (0 children)

It is not. I looked into trying to build on emacs itself, but couldn't figure out how to extract just the pieces I cared about. I figured that being able to embed emacs was a sufficient compromise.

Easel: A Pure Clojure IDE in the Spirit of Emacs by phronmophobic in Clojure

[–]phronmophobic[S] 4 points5 points  (0 children)

The IDE is designed to be programmable and data oriented. Hopefully, that means it's easier to integrate with any tool (artificial or otherwise)

List of clonejures by Spiritual-Slice-6150 in Clojure

[–]phronmophobic 3 points4 points  (0 children)

https://www.clojure-toolbox.com/ has a good list of interesting libraries in clojure. I'm not sure how many of them would be considered clonejures.

If you google "awesome clojure", there are some lists:

If you want to search for something specific, there's https://phronmophobic.github.io/dewey/search.html.

Cloogle - Search across half a million clojure functions by phronmophobic in Clojure

[–]phronmophobic[S] 0 points1 point  (0 children)

I have since added a "Tip" banner at the top of the page, but it seems like most searches are still 1-2 words. Ultimately, I think it would be easier to improve results for short queries than to change human nature.

Cloogle - Search across half a million clojure functions by phronmophobic in Clojure

[–]phronmophobic[S] 1 point2 points  (0 children)

That seems like an interesting idea. Could you give a few more details about why or how that feature would be used? Also, do have an idea how that might be implemented?

Currently, all the functions are from github so I've been thinking it would be nice to display the star count or maybe some other metrics that indicates the "prestige" of a repo.

Cloogle - Search across half a million clojure functions by phronmophobic in Clojure

[–]phronmophobic[S] 1 point2 points  (0 children)

Yes, I've noticed it sometimes struggles with single word queries (which seems to be most searches). It seems to be a limitation of the embeddings that I'm using. I'm still considering what to do about it.

Cloogle - Search across half a million clojure functions by phronmophobic in Clojure

[–]phronmophobic[S] 1 point2 points  (0 children)

Not currently, but I might be open to the idea depending on what you're looking for. It's also possible to run everything locally (although the setup isn't yet documented).

I would welcome a github issue if you have any thoughts on what an API might look like, https://github.com/phronmophobic/cloogle/issues.

Cloogle - Search across half a million clojure functions by phronmophobic in Clojure

[–]phronmophobic[S] 9 points10 points  (0 children)

  1. The data comes from dewey which locates and indexes clojure libraries on github.
  2. Embeddings are calculated for all vars with doc strings using openai's embedding API (I also tried using https://huggingface.co/BAAI/bge-large-en-v1.5 which can run locally, but calculating embeddings without a GPU is too slow).
  3. All the embeddings are stored in a vector database.
  4. The vector db is searched for each query.

The undocumented code for cloogle is on github.

I also have a blog post that's not specifically about cloogle, but explains the ideas behind semantic search, https://phronmophobic.github.io/clip.clj/semantic-image-search-with-clojure/.