HN user

ryjo

100 karma
Posts37
Comments47
View on HN
github.com 6mo ago

Show HN: CLIPSmqueue: A POSIX message queue (mqueue) library for CLIPS

ryjo
3pts1
github.com 9mo ago

Show HN: CLIPSQLite – A SQLite Library for Clips Resources Readme

ryjo
4pts0
github.com 10mo ago

Show HN: CLIPS1wm – a minimal X11 window manager in CLIPS

ryjo
4pts0
ryjo.codes 1y ago

Tour of CLIPSraylib

ryjo
1pts0
ryjo.codes 1y ago

Tour of CLIPSraylib

ryjo
1pts0
groups.google.com 1y ago

CLIPS 6.4.2 Released

ryjo
3pts0
github.com 1y ago

CLIPSraylib: Clips with added User Defined Functions that wrap raylib

ryjo
3pts0
ryjo.codes 1y ago

Write a Ruby C Extension to Use Clips from Ruby: Part 3

ryjo
3pts2
www.gnu.org 2y ago

Input/Output on Streams

ryjo
2pts0
matt.might.net 2y ago

The Language of Languages

ryjo
2pts0
stackoverflow.com 2y ago

When should we use a scatter/gather(vectored) IO? (2010)

ryjo
1pts0
drewdevault.com 2y ago

Writing a Wayland Compositor, Part 1: Hello wlroots (2018)

ryjo
2pts1
en.wikipedia.org 2y ago

Vectored I/O

ryjo
5pts0
ntrs.nasa.gov 2y ago

CLIPS: The C Language Integrated Production System [pdf] (1994)

ryjo
1pts1
github.com 2y ago

CLIPSockets: CLIPS low-level socket implementation

ryjo
1pts0
github.com 2y ago

Sidorares/node-x11: X11 Node.js network protocol client

ryjo
1pts0
github.com 2y ago

Multicast in Ruby (2013)

ryjo
1pts0
ntrs.nasa.gov 2y ago

Integrating Clips Applications into Heterogeneous Distributed Systems (1991) [pdf]

ryjo
1pts0
ryjo.codes 2y ago

CLIPS: An Elevator Pitch

ryjo
2pts15
ryjo.codes 2y ago

Forgoing Implicity and Using Abstractions: Clips

ryjo
1pts0
docs.freebsd.org 2y ago

Chapter 28. USB Device Mode / USB OTG

ryjo
1pts0
github.com 2y ago

CLIPSockets: Clips low-level socket implementation

ryjo
3pts0
ryjo.codes 2y ago

Tour of CLIPS (2022)

ryjo
75pts41
ryjo.codes 2y ago

A JSON Validator in C

ryjo
3pts0
ryjo.codes 2y ago

Run Clips in a C++ AWS Lambda

ryjo
1pts0
ryjo.codes 3y ago

Write a Ruby C Extension to Use Clips from Ruby: Part 2

ryjo
4pts1
ryjo.codes 3y ago

A Shell Script Calling ChatGPT That Uses ChatGPT to Describe Its Usage

ryjo
3pts0
ryjo.codes 3y ago

Write a Ruby C Extension to Use Clips from Ruby: Part 1

ryjo
3pts0
ryjo.codes 3y ago

Conway's Game of Life Written in Clips

ryjo
7pts0
ryjo.codes 3y ago

A* Algorithm Written in Clips

ryjo
1pts0

Still working on CLIPS-related libraries. My most recent one is CLIPSmqueue[1]. I'm employed full-time, so progress is slow as CLIPS stuff comes second to that. However, I've got a much larger CLIPS-related project in the works that I've been taking my time on, and I'm excited for when I finally feel ready to release it.

I'm not sure these projects will ever "go anywhere," but at the very least I'm honing my craft as a programmer. I've learned so much, and I have so much more to learn.

---

[1]https://github.com/mrryanjohnston/CLIPSmqueue

Hey, HN. This is a small C library that enables usage of POSIX message queues (mqueue) in CLIPS. This enables IPC between multiple CLIPS processes using kernel-managed message queues, including load-balancing receives and priority-handling.

The repo includes a fairly full test suite as well as examples that demonstrate multi-process communication between CLIPS rules engines.

My purpose in providing this library (and other CLIPS libraries I've released) is to expand the usecases in which CLIPS can be leveraged. Feedback welcome.

Very cool. Neat how you managed to get logical symbols in to the language itself! When might someone use preconditions in Lean theorems?

This article caught my eye because it's focused on imperative programming, and I've been very focused on declarative vs imperative programming over the last few years. I implemented a version of your function in CLIPS, a Rules-based language that takes a declarative approach to code:

(defrule sum-is-0 (list $? ?first $? ?second $?) (test (= 0 (+ ?first ?second))) => (println TRUE))

(defrule sum-is-not-0 (not (and (list $? ?first $? ?second $?) (test (= 0 (+ ?first ?second))))) => (println FALSE))

(assert (list 1 0 2 -1)) (run) (exit)

The theorem you write in Lean to prove the function kind-of exists in CLIPS Rules; you define the conditions that must occur in order to execute the Right Hand Side of the Rule. Note that the above simply prints `TRUE` or `FALSE`; it is possible to write imperative `deffunction`s that return values in CLIPS, but I wanted to see if I could draw parallels for myself between Lean code and theorems. Here's a gist with the simple version and a slightly more robust version that describes the index at which the matching numbers appear: https://gist.github.com/mrryanjohnston/680deaee87533dfedc74b...

Thank you for writing this and for your work on Lean! This is a concept that's been circling in my head for a minute now, and I feel like this article has unlocked some level of understanding I was missing before.

  Location: Pittsburgh, Pa
  Remote: Yes
  Willing to relocate: No
  Technologies: CLIPS, Ruby (on Rails), Go, JavaScript, C, SQL
  Résumé: https://drive.google.com/file/d/1M-tC7qpehmsJfd3JBk3KtXEQ5wDJz89t
  Email: mrryanjohnston (at) gmail
  Website: https://ryjo.codes
12+ years of experience writing code professionally, active in open source, passionate about education and freedom of knowledge. Very interested in Rules Engines. Love working on teams of self-starters, enjoy pushing the boundaries of my understanding. Comfortable mentoring others as well as helping non-technical folks with difficult-to-grok concepts.

From the article:

Conventional programming languages, such as FORTRAN and C, are designed and optimized for the procedural manipulation of data (such as numbers and arrays). Humans, however, often solve complex problems using very abstract, symbolic approaches which are not well suited for implementation in conventional languages. Although abstract information can be modeled in these languages, considerable programming effort is required to transform the information to a format usable with procedural programming paradigms.

One of the results of research in the area of artificial intelligence has been the development of techniques which allow the modeling of information at higher levels of abstraction. These techniques are embodied in languages or tools which allow programs to be built that closely resemble human logic in their implementation and are therefore easier to develop and maintain. These programs, which emulate human expertise in well defined problem domains, are called expert systems. The availability of expert system tools has greatly reduced the effort and cost involved in developing an expert system.

Really awesome. Thanks for this thorough write-up. I don't totally understand the deeper math concepts mentioned in this article around RNNs, but it's sparked some of my own thoughts. It feels similar to things I've been exploring lately-- that is: building your app interwoven with forward chaining algorithms. In your case, you're using RNNs, and in mine, I'm building into the Rete algorithm.

You also touch on something in this article that I've found quite powerful: putting things in terms of digesting an input string character-by-character. Then, we offload all of the reasoning logic to our algorithm. We write very thin i/o logic, and then the algorithm does the rest.

This is another reason I am learning CLIPS. It implements a form of the Rete algorithm. A Rete network provides the same benefits of a neural network without the bells-and-whistles, and thus would be a great candidate for anyone who thinks they could benefit from the reasoning power provided by LLMs.

I jump between client projects relatively often

Using debuggers makes a lot of sense in this case. If I had to switch context that frequently between relatively stable applications, it would be helpful to have a debugger framework for doing work.

`printf` statements are helpful when the error exists beneath the debugger: in the application framework itself.

they're not always available

100% agreed. `printf` is "one tool" I can use to follow the control flow of a function call across frameworks, programming languages, and even operating systems. It's also something I can reliably assume my coworkers have in their tool belt, and thus provides a common language that even multiple different organizations can use to cross-collaborate a specific debugging session.

Writing a JSON parser is a good way to teach yourself better programming practices. I attribute my understanding of pointer arithmetic and i/o streams to my own efforts in parsing/generating JSON.

Ok, then it's aparently the intermediate representation (what the parser feeds to the evaluator), which makes sense. The evaluator doesn't care, whether it comes from the parser or from constructs-to-c generated code.

Precisely!

For some years I was thinking about using CLIPS for algorithmic music composition

This is a great use case! I'd be interested in seeing what you come up with.

in which format the code/rule-base is kept

When you use constructs-to-c, the generated C files represent your rules engine constructs as pointers to pointers of CLIPSLexeme, CLIPSFloat, CLIPSInteger, and CLIPSBitMap structs. It does not store it as the raw clips code fed into the interpreter. You can later use functions like `save-facts` to generate the rules in CLIPS syntax based on these pointers to pointers of structs.

I'm sorry, but I still think I'm not sure what you mean by interpreter. I hope you don't mind if I press further, but I'm very much enjoying this deep dive into the CLIPS C API with you.

When you compile your code including the c files generated by the constructs-to-c command, you must update the main.c file as well as the makefile that ships with CLIPS. During that update, there are a few things you must do:

1. add the generated c files to the makefile 2. you remove the function calls in the main.c file that cause CLIPS to capture STDIN and STDOUT. That is: you remove one layer of abstraction that sits between your rules and i/o streams. 3. you remove the generic CreateEnvironment function call in main.c and replace it with InitCImage_1, a function that calls CreateRuntimeEnvironment.

CreateRuntimeEnvironment differs from CreateEnvironment because you are able to pass in pre-built:

1. symbolTable 2. floatTable 3. integerTable 4. bitmapTable

Which are your rules engine constructs represented in C.

In addition to these four things, CreateRuntimeEnvironment passes in functions the user may have defined as UserDefinedFunctions (UDFs) in C. This is a more direct path than having CLIPS first interpret CLIPS rules like `(defrule foo =>)` and then translate them into these C representations.

So you were! I apologize for my oversight.

you have seemed to use it more for "indexing" and "caching", which is a domain shared by other interpreters used for the web

That's the idea! I think CLIPS is a good framework for a generic run-loop (or `while` loop). If you can conceptualize your app as such, you can reap the benefits inherent in the rete algorithm within your application logic.

To see what I mean, take a look at the tcp server in the CLIPSockets repo: https://github.com/mrryanjohnston/CLIPSockets/blob/6.4.1/exa...

UPDATE: I edited the link to point to the 6.4.1 tag version of the repo. The `main` branch is using the latest (7.x) from CLIPS svn as the base.

UPDATE2: I edited my previous comment to specify that it is a tcp server, not an http server.

I thought that you might have specific experience with "real world" applications, thus my question.

As to this point: I don't at present have "real world" experience writing CLIPS. My experience thus far has been entirely research-driven based on observations I've made in "real world" scenarios.

If you want to read about some other people who have used CLIPS in real world scenarios, here's the most comprehensive HN thread to date so far on the subject:

https://news.ycombinator.com/item?id=40201729 - 30 days ago

One in particular that stands out to me is the usage of CLIPS in MTG:Arena, a real-time web-based card game with and arguably large amount of rules.

Good find in the apg! That thing is a wealth of info. It look like contructs-to-c wouldn't make things faster, but would instead reduce the compiled code size.

If I'm understanding your meaning, you mean "interpreted" in a sense that it translates to C code, and C code is interpreted and translated into machine code. Is that accurate?

It's possible that you and I are referring to different things when we use the word "interpreted." When I think "interpreted" in the context of computer programming, I'm thinking in terms of interpreted-at-runtime programming languages like Ruby, Python, and CLIPS before you use `constructs-to-c`. In my mind, using `constructs-to-c` changes this from an "interpreted" to a "compiled" language in that the expert system you write in CLIPS code is its own language with its own data structures, algorithms, and DSL. When you use `constructs-to-c`, you "compile" your application using the programming language of your expert system, thus it is no longer interpreted at run time.

Do you mean the "constructs-to-c"?

Yes

But does this actually give a speed-up?

There is an objective benefit to using `constructs-to-c` and that is something you mention in your original comment: you generate a single binary file containing all of your business logic, thus avoiding running a "fully interpreted" app in production.

In order to determine if it gives a performance boost to your particular rules engine, you should test it out and benchmark it with something you'd consider a "real world" example.

You can compile CLIPS (including your rules) into C code from within CLIPS itself, which then gets compiled to a dedicated binary.

Rete algorithm 2 years ago

rete0.cpp is a faithful implementation from the thesis, to the extent that it has page number markings in the source code to refer to the thesis

Music to my ears :) thanks for sharing this!

Rete algorithm 2 years ago

I've been studying Rete for the past few years, and I've been working exclusively in CLIPS for the past year, a programming language that uses the Rete Algorithm at it's core. It's a very clever algorithm, and provides a lot of "nice features" that developers find themselves re-implementing in mature code bases. Things like:

- pattern matching - custom DSL - caching

I find it difficult to summarize in an "elevator pitch," and I only started seeing things fall into place after trying to use it in earnest on my own. I highly recommend reading the CLIPS documentation posted on the main CLIPS website. The PDFs are long, but quite complete and well written.

Self promotion: If you prefer something a little more interactive, check out the Tour of CLIPS I made: https://ryjo.codes/tour-of-clips.html

Just a heads up: this is not light reading. Rules-based programming is a confusing departure from traditional programming; there's more "magic" involved, similar to convention-over-configutation in other languages/frameworks. The benefits outweigh the upfront learning cost, though.

Here is a recent post on HN that recently got some traction and has some pretty good discussions: Tour of CLIPS (2022) - https://news.ycombinator.com/item?id=40201729

If anyone is working directly with CLIPS, let me know! I'm actively working on a low level networking library called CLIPSockets, and would like to work with the language full time some day.

I just ran into this this week implementing a socket library in CLIPS. I used Berkley sockets, and before that I had only worked with higher-level languages/frameworks that abstracts a lot of these concerns away. I was quite confused when Firefox would show a "connection reset by peer." It didn't occur to me it could be an issue "lower" in the stack. `tcpdump` helped me to observe the port and I saw that the server never sent anything before my application closed the connection.

Here's an article: https://magic.wizards.com/en/news/mtg-arena/on-whiteboards-n...

So first, a quick summary of how the rules engine works. When a game of Magic is in progress on MTG Arena, the program that is tracking the state of the game and enforcing all the rules-correct card interactions is called the Game Rules Engine (GRE). It's one of the two main programs that we work on. It's written in a combination of C++ and a language called CLIPS, which is a variant of LISP.

Holy moly. I had my suspicions Magic would be a good candidate for something like CLIPS when it comes to software implementation. Do you have a source for that info? What an amazing bug.

That sounds like an excellent use case.

You bring up something awesome about CLIPS: it's easy to tailor it to your needs. Once you have your CLIPS code, you can trim out the parts you don't need using compiler flags. Once you have a compiled `clips` binary with only the constructs you need (defrules and deffacts, maybe?), you can execute it, load your rules/facts into the engine, and then generate C code for your specific rules engine. This compiles into an even smaller/faster binary. You can do all of this from within CLIPS proper. Check out the Advanced Progamming Guide section 11: Creating a CLIPS Run-time Program https://www.clipsrules.net/documentation/v641/apg641.pdf