Gave it a shot real quick, looks like I need to fix something up about automatically running the migrations either in the CI script or locally...
But if you're curious, task was this:
----
Title: Bug: Users should be able to add tags to a task to categorize them
Description:
Users should be able to add multiple tags to a task but aren't currently able to.
Given I am a user with multiple tasks
When I select one
Then I should be able to add one or many tags to it
Given I am a user with multiple tasks each with multiple tags
When I view the list of tasks
Then I should be able to see the tags associated with each task
One thing to note that I've found - I know you had the "...and you should be able to filter/group tasks by tag" on the request - usually when you have a request that is "feature A AND feature B" you get better results when you break it down into smaller pieces and apply them one by one. I'm pretty confident that if I spent time to get the migrations running, we'd be able to build that request out story-by-story as long as we break it out into bite-sized pieces.
You can have a larger model split things out into more manageable steps and create new tickets - marked as blocked or not on each other, then have the whole thing run.
Thanks, and having another step for reviewing each other's code is a really cool extension to this, I'll give it a shot :) Whether it works or it doesn't it could be really interesting for a future post!
Yeah, totally agree that something related to this will likely be the next paradigm. I've been putting together experiments in different directions trying to find that thing that's missing but haven't really found a killer use case yet to pull it all together.
That's a really cool idea that once you can get something somewhat reliably consistent generated, you can kind of let your A/B tests start to run themselves with just rough guidelines on what you're trying to optimize for...
I love that this is more art piece than serious software... more like offering someone an expedition than a product.
(Though I'm not sure I'll get on the expedition, I am a little worried about sandboxing and setup and getting distracted...)
If I was to start the expedition, I'd probably try to overshoot by describing a site that I could not myself fully imagine, or using attributes that lacked a single meaning. Like, "the artist's interactive portfolio, as though the artist is looking over your shoulder, the artist keeping a carefully neutral expression while seething inside." Then I'd probably continue, imagining just the outline of some site that satisfies some unarticulated desire, putzing around as I see a concrete articulation of that idea, as much reforming the idea in my head in response to those results to an equal degree that I am articulating the idea in more detail.
Ahh I absolutely love this idea of trying to infuse more emotional and fuzzy attributes to see what the LLM comes up with!
When I broke out the layout and style components I was thinking of being able to change the whole site aesthetic from something like "standard b2b" to "geocities fan page", but I'm excited to try getting fuzzier with the descriptions!
I've been having a lot of conversations recently with people about LLMs and how a prototypal inheritance-like approach to working with them seems to be surprisingly effective. Especially for writing code.
Also, this quote jumped out at me: "Insights from the dynamic world can have application in the static."
Ahh yeah - so I've found prototypal inheritance (or what Hofstadter calls The Prototype Principle) is a useful way to think about what's going on with in-context learning and few shot prompting and ways to take it further.
If you provide a "prototype" to a model, you can operate on that prototype and create new instances or variations of it. This is useful for working with code by defining an abstraction or a class, and then having the LLM work with and modify it, generating new code that fits or inherits conceptually from that original prototype.
I've been working with Ruby + AI for the last year and couldn't agree more with this post. It feels like there are so many brand new ways to build software with LLMs that have yet to be discovered and I find Ruby's flexibility makes it easy to try out new ideas almost as quickly as you can think of them.
Obie also mentions my company's product Blueprints. Blueprints allows you to capture existing, known-good patterns in your code base, and then use them as a base for an LLM to generate variations from. We've got editor plugins for the major editors and we're also starting to roll out downloadable packages like this DaisyUI-styled Phlex component one: https://blueprints.sublayer.com/packages/phlex-daisyui
I've been using Blueprints extensively. I see a future that includes curated collection Blueprints servers for many different programming languages and niches.
It is a really long post and heavily references Godel, Escher, Bach but this section I think explains the difference really well:
Hofstadter offers several supporting examples for this thesis, but I'll paraphrase one of my all-time favorites. It goes more or less as follows.
Imagine you're listening to announcers commenting on an NFL (American football) game. They're talking about a new rookie player that you don't know anything about. At this point, the rookie – let's say his name is L.T. – is just an instance of the class "football player" with no differentiation.
The announcers mention that L.T. is a running back: a bit like Emmitt Smith in that he has great speed and balance, and he's great at finding holes in the defense.
At this point, L.T. is basically an "instance" of (or a clone of) Emmitt Smith: he just inherited all of Emmitt's properties, at least the ones that you're familiar with.
Then the announcers add that L.T. is also great at catching the ball, so he's sometimes used as a wide receiver. Oh, and he wears a visor. And he runs like Walter Payton. And so on.
As the announcers add distinguishing attributes, L.T. the Rookie gradually takes shape as a particular entity that relies less and less on the parent class of "football player". He's become a very, very specific football player.
But here's the rub: even though he's a specific instance, you can now use him as a class! If Joe the Rookie comes along next season, the announcers might say: "Joe's a lot like L.T.", and just like that, Joe has inherited all of L.T.'s properties, each of which can be overridden to turn Joe into his own specific, unique instance of a football player.
This is called prototype-based modeling: Emmitt Smith was a prototype for L.T., and L.T. became a prototype for Joe, who in turn can serve as the prototype for someone else.
These are really different facets of the same rookie and have to do with the role he can play in various relations -- each facet can come from a different prototype (or class...) if necessary. So "viewed as a" or "in the role of" a Catcher, we "see" certain attributes, and "as a runner" we see others. Certain knowledge representation schemes (frame systems, description logics, default reasoning and truth-maintenance schemes, etc.) can deal with this context-sensitivity well -- programming languages tend to have some weakened notion of these things, such as Inferfaces or Traits.
Hah that's a good question. I haven't really thought about that or explored type systems that would interact with this pattern. Would be really interested in reading about it though!
It's not just about static type systems, though. nerdponx was asking about type systems in general. It's a tricky question even for dynamic type systems. Javascript keeps reference to the constructor and the prototype, so you can determine the "type" that way, but that's not the only way a prototype-based OOP language can work. A language can work without keeping such references and instead simply copying each property on cloning. How do you determine the type of an object then? Is the type based on the presence of certain properties? Does it include the equality of the values of such properties or does just their presence suffice? Does having additional properties change the type? There seem to be many questions with arbitrary answers in making such a dynamic type system.
I think I had static type systems in mind when I asked the question, but that was helpful all the same. It seems in the case of Self it does in fact keep the reference around.
I suppose the whole point of a static type system is moot with a fully prototype-based language. Instead maybe you can enforce compile-time checks (contracts?) on the messages an object is expected to receive.
> I suppose the whole point of a static type system is moot with a fully prototype-based language. Instead maybe you can enforce compile-time checks (contracts?) on the messages an object is expected to receive.
I think if you can do the latter, you can probably do the former. By that I mean you can probably do neither.
If cloning is something you do in runtime, how can you enforce compile-time checks on the messages they're supposed to receive? Such messages are defined at runtime.
Shot in the dark here, but I vaguely remember a blog post that used birds in an explanation for monads and I can't seem to find it again. It had hand-drawn birds, and I think it started out with the identity monad, with the bird representing it only able to speak their own name.
Does anyone remember that post? I'd love to find it again, I got really excited when I saw the title, thinking that it had finally come around again.
AI Algorithms, Data Structures, and Idioms in Prolog, Lisp, and Java, by George Luger, free from the author's personal page on Florida State uni, here:
This is an excellent resource also for LISP (and Java!) and AI algorithms, particularly various search strategies.
I'd also recommend the standard Prolog textbtook, Prolog Programming for AI, by Ivan Bratko. You can most likely find an edition in most university libraries.
I've learned a lot from Adventure in Prolog, a Prolog tutorial on the Amzi! Prolog website (though I used a different Prolog to do the exercises, which is a very good sign of nice, basic and portable examples):
Those are practical resources. On a more theoretical side, another commenter recommended Perreira & Shreiber, which I can't recommend enough. Also, for a more formal text on logic programming, with proofs and all, the classic reference is J. W. Lloyd, Foundations of Logic Programming. Again, you can probably find a copy in your friendly neighbourhood university library (or, er, google it for a very bad copy of dubious legitimacy, like).
The exposure most people have to prolog in school is about a chapter in the "programming languages" course.
Yes, pick any book and work through it from page 1 to the end. Preferable 3!
Read and pour through the manuals for whatever interpreter & compiler you use.
Be warned, Prolog will ruin you, you shall be able to slay dragons and at the same time you most likely will not enjoy programming in "modern languages" anymore.
(Intro/Novice)
Learn Prolog Now (free on the web)
Adventure in Prolog(free on the web)
Logic Programming with Prolog
(Intermediate)
The Practice of Prolog
Prolog Programming for Artificial Intelligence
Prolog Programming In Depth
Prolog Experiments in Discrete Mathematics, Logic, and Computability
(Advanced)
The Art of Prolog
The Craft of Prolog
Clause and Effect
Simply Logical
Prolog and Natural Language Analysis
Meta Programming Logic
Intelligent Image Processing in Prolog
Expert Systems in Prolog
Functional Grammar in Prolog
(Papers)
Warren Abstract Machine
Negation and Control in Prolog
For a really nice explanation of the Warren Abstract Machine, see "Warren's Abstract Machine: A Tutorial Reconstruction" by Hassan Aït-Kaci: http://wambook.sourceforge.net
Clocksin & Mellish has the benefit of being a slim volume, which makes it approachable.
Sterling & Shapiro (Art of Prolog) has much more depth. Not sure I'd recommend to a beginner. (It has a beautiful cover, though and is almost worth getting just for that.)
My favorite Prolog book is Pereira & Sheiber's "Prolog and Natural-Language Analysis". It's slanted toward NLP but the coverage of Prolog itself is top notch.
I just googled that and don't know if it's a legitimate source, but I've previously downloaded a copy from the site of one of the authors, so it's probably all right.
Peter Flach's "Simply Logical: Intelligent Reasoning by Example" also deserves to be mentioned as a wonderful introduction to Prolog and computational logic in general. It's available as a PDF from the author (http://people.cs.bris.ac.uk/~flach/SimplyLogical.html) and also in an interactive version where the examples can be run in-browser, using SWISH: https://book.simply-logical.space/
People have already recommended it, but "Programming in Prolog" by Clocksin and Mellish was the text book for the Prolog course that SWI-Prolog offered back in June.
But if you're curious, task was this:
----
Title: Bug: Users should be able to add tags to a task to categorize them
Description: Users should be able to add multiple tags to a task but aren't currently able to.
Given I am a user with multiple tasks When I select one Then I should be able to add one or many tags to it
Given I am a user with multiple tasks each with multiple tags When I view the list of tasks Then I should be able to see the tags associated with each task
----
And then we ended up with:
GPT-4o ($0.05): https://github.com/sublayerapp/buggy_todo_app/pull/51
Claude 3.5 Sonnet ($0.09): https://github.com/sublayerapp/buggy_todo_app/pull/52
Gemini 2.0 Flash ($0.0018): https://github.com/sublayerapp/buggy_todo_app/pull/53
One thing to note that I've found - I know you had the "...and you should be able to filter/group tasks by tag" on the request - usually when you have a request that is "feature A AND feature B" you get better results when you break it down into smaller pieces and apply them one by one. I'm pretty confident that if I spent time to get the migrations running, we'd be able to build that request out story-by-story as long as we break it out into bite-sized pieces.