From f3e2d020d05634cd55e63d119191c8a1d96b97b34a36d6d6538b5698e26cbbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= Date: Thu, 1 Oct 2026 20:56:30 +0200 Subject: [PATCH] used bjoweb html --- index.sz | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/index.sz b/index.sz index 686a3e3..1c91cfd 100644 --- a/index.sz +++ b/index.sz @@ -5,11 +5,11 @@ Bjolang is a Lisp for .NET. It has types that are inferred, unions that are matched exhaustively, traits, hygienic macros, and bjoroutines, and it -compiles to C#. +compiles to C#. It is a small experiment in what I would like in a programming language, and in api design. + +I built it with liberal use of ai, so beware. @codeblock[#:lang "bjolang"]|{ -(import (std prelude)) - (type (: Shape (Union (: Circle double) (: Rect double double)))) @@ -27,3 +27,56 @@ compiles to C#. @link["manual/"]{Read the manual}, or go straight to the @link["manual/modules/"]{library reference}. + +@section{more examples} + +ConcurrentML brings the multithreading story for bjolang into the 1990s. The function within cannot be written in go, because select is a statement. + +@codeblock[#:lang "bjolang"]{ +(: within (-> int (Event %a) (Event (Option %a)))) +(defun (within ms ev) + (choose (wrap ev #(Some &)) + (wrap (timeout ms) (fun (u) None)))) + +(sync (within 20 (chan-recv kitchen))) ;; => None, and nothing is consumed +(sync (within 500 (chan-recv kitchen))) ;; => (Some "dinner") +(sync (within 20 (spawn-evt (count-to 1000)))) ;; works on fibers too +} + +This sums every line and every char read from stdin. When the port is closed, the result is printed using the show function from (std fmt). +@codeblock[#:lang "bjolang"]{ +(import (only (std ports) port->seq)) +(import (std fmt)) + +(defun (main args) + (def line-seq (port->seq read-line (deref current-input-port))) + (loop (:for line line-seq) + (:acc lines (summing 1)) + ;; Any :for after a non-:for clause opens a new subloop + ;; so this loops over ever char in the line. + (:for ch line) + (:acc chars (summing 1) :when (not (char-whitespace? ch))) + => (show [(tabular [["Lines:" nl "Chars:" nl] + [lines nl chars nl]])])) + 0) +} + +Here is a small example showing off bjoroutine use together with process pipelines + +@codeblock[#:lang "bjolang"]{ +(import (std run)) + +;; this is an asynchronous filter that suspends if the read-char/opt or +;; write-char has to wait. A filter is a function type declared in (std run) +;; this particular filter upcases every letter. +(: shout Filter) +(defbjo (shout in out) + (loop (:for ch (in-port in read-char/opt)) + (:do (write-char out (char-upcase ch))))) + +;; the run/xyz functions uses type elaboration to allow for +;; simple DSLs using quoted lists. This runs cat (the linux binary) +;; pipes it's output to the shout method and pipes that to a grep after +;; the word BOMB. +(run/string '(pipe (cat "notes.txt") ,shout (grep "BOMB"))) +}