Recent posts

#1
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by itistoday - Today at 09:04:59 PM
That's a lovely story thanks for sharing oofoe!
#2
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by oofoe - Today at 08:32:15 PM
Hi! I'm glad this forum is being revived, and I hope that NewLisp finds alternate hosting and maintainers.

With respect to Janet -- for what it's worth, I did successfully make the jump from NewLisp. So, if you'll indulge, a few notes about why and what I found.

I got re-interested in Lisp about the time Paul Graham started writing about his Viaweb experience (e-commerce server, written in Common Lisp). I couldn't make Common Lisp click for me though... Too many exceptions, nutcase documentation (CLHS, need I say more?), every kind of data structure was handled a different way, etc. After a long walk through the desert, I stumbled on NewLisp. It was a long drink of cool water! Many times, things worked exactly the way I expected them to. Often I could just guess at what the appropriate function would be and it was. Combine that with excellent documentation and quick interpreter and I was off to the races. I did a number of things with it, both for work and for fun (current link to my weight+balance calculator: https://hg.sr.ht/~oofoe/wb, and an implementation of Jef Raskin's FLOW language: https://hg.sr.ht/~oofoe/flow)

However, I started finding the need to distribute compiled executables and with the Oracle legal stuff, I wasn't too keen on continuing to use Java for the GUI parts. I dabbled for a bit in Dr. Racket, it at least seemed simpler than Common Lisp, and had the GUI/graphics built in. I tried other things, including ill-advised flirtations with Python compilers. And then... One day I stumbled across Janet.

The initial experience was positive; it had some of the most important features of NewLisp like implicit data access. It does do some strange things, like "#" for comments, but once you see what they're doing with the semicolon for the splice operator, you forgive it. However, for me, the three absolute killer features of Janet are PEGs, multitasking and compiling.

Parsing Expression Grammars (PEG) are something I got used to in REBOL and will never voluntarily give up. They turn parsing from mysterious incantations at midnight (yacc or PCRE) into clear, documented rules that can stand the light of day. I even wrote an PEG that transpiles Janet formatted source code into JavaScript. Absolutely indispensable for correct, reliable parsing. Janet's implementation is clean and flexible.

With multiple network connections, GUIs and long running processes, multitasking of some sort is a must. Janet provides several flavours. The simplest is a "fiber", which is a kind of in-process green thread. Then, threads (of course), and finally actual multiple process synchronization. So far, I've only needed fibers, but it's been more than enough to handle multiple data streams for simulating and controlling scientific instruments.

And compiling. If you're on Linux (or Mac, I think), it works like falling off a log. If you're on Windows it's annoying (thanks Micro$oft), but still doable. It uses a two stage compilation that allows you to control what gets compiled in your source (like C macros, but much nicer). Compared to Racket (or even other scripting language compilers, e.g. Nuitka?), it produces a tiny result (1.7MB for a commercial product where I compiled in all the resources and even the user manual to a single executable).

There are other things that I've discovered, but those are the big three for me. I think if any of that whets your appetite, you should definitely give Janet a look-see.

However! I would never have gotten to Janet without NewLisp. Its simplicity, complete documentation and friendliness to an uninitiated seeker are what brought me into the Lisp fold to stay. I hope it will always remain available for others to discover.

P.S. A really nice book-length tutorial for Janet: https://janet.guide/
#3
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by itistoday - June 12, 2026, 09:36:43 AM
One of the things that I really appreciate about newLISP is the design of the function names themselves. The API just makes sense, English-wise, more so than any other Lisp. I think it has to do with Lutz's background in psychology.

That said, I personally like Janet's use of square brackets, braces, etc. for distinguishing different data structures. It helps break up what otherwise would be a very monotonous looking syntax. I definitely am not a fan of "lots of syntax", but having nothing but parenthesis everywhere can make it hard to notice the datastructures vs functions vs whatever else. I think Janet picked a fairly good sweet spot.

And the lack of lists is interesting, true. However, for all intents an purposes arrays are sufficient and performance-wise faster. Same with real hashtables, which newLISP doesn't have.
#4
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by boris - June 11, 2026, 12:22:50 AM
Having tried it for a while I came to the same conclusion as you.
The thing about newlisp is that it hits that sweet spot of being a lisp for the rest of us.
#5
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by hapco - June 05, 2026, 06:02:28 PM
Still, we have the source code, and people who appreciate newlisp, so it's not really gone because the site is. I briefly tried Janet, and may again, but at the time it just didn't do it for me. Too many dots, square brackets, and random punctuation. And what's wrong with lists? Not a list to be found...
#6
newLISP newS / Re: Janet: newLISP's spiritual...
Last post by boris - May 27, 2026, 09:55:56 AM
Thanks for that, I had kind of given up on newlisp.

Good to see something being actively maintained and not calling itself "xxxlisp" to inflame the haters....

Janet looks like it could be an interesting replacement for newlisp.
#7
newLISP newS / Janet: newLISP's spiritual suc...
Last post by itistoday - May 14, 2026, 05:47:32 PM
Hey folks, as you might've noticed, it appears newLISP is, unfortunately, no longer with us.

The main website has been down for many months now. I haven't heard anything from Lutz. I'm not sure if he's with us either.

What Lutz created will always have a special place in my heart. I've loved this language so much, and I've used it for so many personal projects.

It's such a simple, beautiful language, that it saddens me to see its story come to what appears to be an end.

However, all is not lost.

Lately, I've been exploring Janet.

This lisp-like language is also incredibly well designed. Like newLISP, it too is batteries-included in a tiny single-binary.

However, the similarities end there. Janet is a significantly more sophisticated language. In many ways it is better designed than newLISP and much more modern. It has real garbage collection, lexical closures, special syntax for non-list data structures, a sophisticated fibers-based runtime with support for real threads, a real module system, and more!

Yes, it is a bit more complicated than newLISP, and newLISP's simplicity is a significant part of its appeal. However, there really are no better options AFAICT, and we small-language communities need to stick together!

I encourage newLISPers to have a look at Janet, and consider migrating their code over using LLMs as helpful assistants. That's what I've been doing and it excites me once again to learn a new language.

newLISP, we love you, we're sad to see you go.

Thank you for all of your work, Lutz!

You've forever set an example of the power of simplicity, and the power of Lisp.

EDIT: some docs for learning Janet:

#8
Whither newLISP? / Re: Parametrized access to con...
Last post by pda - April 04, 2026, 03:39:26 PM
There's a workaround to avoid context machinery inside the funcion body when defining functions, the idea is to use the dictionary facility of contexts.

If we accept to use variables in the context as dictionary values we can easy use them without worrying about context issue, the prize to pay is to treat variables as strings in the context dictionary.

To do this we redefine our mk-ctx function this way:

(define (mk-ctx c f b) (context c f (expand b '((MY (context)))) ) (context c))

The idea is to use (MY "var") everywhere we refer to a context variable var (you can use MY or whatever word you prefer providing it is capitalized) and to expand that expression inside function body to get the value stored in the context dictionary.

The use is so simple:

(setq the-ctx (mk-ctx OO 'x2 (lambda () (* 2 (MY "x")))
(the-ctx "x" 33)
(the-ctx:x2)     --->  66

(setq the-ctx (mk-ctx OO 'f (lambda () 1) ))
(the-ctx:f)   --> 1

#9
Whither newLISP? / Re: Searching on array
Last post by pda - April 04, 2026, 07:42:46 AM
Using a search algorithm like binary search, probabbly you will need to sort the array previously. Converting the array to a list is not a general solution, I doubt you can convert any array to a list.
#10
Whither newLISP? / Parametrized access to context
Last post by pda - April 03, 2026, 05:57:13 AM

I'd like to know if there's some way to access to context symbols in a parametrized way, that is, passing the context or the full qualified path to context symbols.

Let's clarify the question with some examples.

If I want to create a symbol in a context (or access to it) I can just prefix the symbol with the context:

(define CTX:s 7)
(print CTX:s)

This way I can create any kind of symbol, including functions:

(define CTX:f (lambda (a) (+ 1 a)))

The problem appears with free symbols inside the function, if I use a free symbol its is resolving depending on the context prefix and assuming MAIN if no prefix:

(define CTX:g (lambda (a) (+ n a)))

What n inside CTX:g referes to?  it refers to context MAIN since it is not prefixed at all :

(setq CTX:n 66)
(setq n 1)
(CTX:g 2)   --->   3 

so, what if I want n to refer to context CTX inside CTX:g function?  I have to prefix it with CTX symbol:

(define CTX:g (lambda (a) (+ CTX:n a)))
(CTX:g 2)   --->   68 

The problem arise when I don't know the context, i.e. I don't know the context symbol so I cannot use a context prefix ,  let's say I have a function g in several contexts and I want to execute the right one depending on the context.

Fortunately newlisp allow to pass a variable as a context prefix and doing so it uses the variable value as prefix:

(define C:n 1)
(define C:g (lambda (a) (+ C:n a)))

(setq cn CTX)
(cn:g 2)      ->   68

(setq cn C)
(cn:g 2)      ->   3

And so you can define the same symbols in differente contexts provided you set previously the context, i.e. the prefix:

(setq cn C)
(define cn:X 8)
(define cn:X2 (lambda () (* cn:X 2)))

(cn:X2)    ->   16

(setq cn CTX)
(define cn:X 1)
(define cn:X2 (lambda () (* cn:X 2)))

(cn:X2)    ->   2

What to do in order to avoid setting the prefix previously each time, well you can pass it to the function:
   
(define X2 (lambda (cn) (* cn:X 2))

(X2 C)        -> 16
(X2 CTX)    -> 2

Pretty good, know I have a general function in context MAIN that use symbols in context passed as parameter.

But I want to have the function defined in the context I'm passing as parameter, not in MAIN

The obvious solution is to create a function with a context as parameter, that creates a contex with th X2 function inside:

(define (mk-ctx c) (define c:X2 (lambda (cn) (* cn:X 2))))

Now if I want the function created in context OO I call mk-ctx with that context:

(context 'OO)
(context MAIN)
(mk-ctx OO)
(OO:X2 C)       --->   16
(OO:X2 CTX)   --->   2

Pretty good, but I still have to pass the evaluation context to X2, I want X2 to use the context in which it is defined, here OO, so easy:

(define (mk-ctx c) (define c:X2 (lambda () (* c:X 2))))

But this fails, because now c:X in lambda's body uses a free variable c which is evaluated in context MAIN (where it can even be unbind)

This is better seen with this alternative definition of mk-ctx showing the value of c symbol inside the lambda:

(define (mk-ctx c) (define c:X2 (lambda () (print c) (* c:X 2))))

if I set c in MAIN context to be 9382, I can see the problem:


(setq OO:X 10)
(setq c 9382)
(mk-ctx OO)
(OO:X2)
9382
ERR: context expected in function * : MAIN:c
called from user function OO:(X2)

If I set c to a valid context in MAIN, everything is ok:

(setq c OO)
(mk-ctx OO)
(OO:X2)       --->   20
OO

So the problem is how to use in the body of lambda X2 a parametrized context WITHOUT passing it as parameter,
that is, I want that body of lambda evaluates the free variables in the context it is defined and not in main (or a passed prefix):

(define (mk-ctx c) (define c:X2 (lambda () (let (cn (context)) (* cn:X 2)))) c)

Now I can create a "autoreferenced" X2 function, and also mk-ctx returns the context in which it is defined:

(setq the-ctx (mk-ctx OO))
(the-ctx:X2)     -->  20

That is so good, but I have to take care of all that context stuff inside the body, it would be better if I can forget about context machinery
What I want is something like this:

(define (mk-ctx c) (define c:X2 (lambda () (* (my 'X) 2))) c)

But the problem is to define that my funcion, it's tempted to define it as:

(define (my v) (eval (sym v (context))))

But again the problem is the evaluation of (my 'X) is done in context MAIN and so (my v) returns the value of symbol V in MAIN, not in context of X2

Of course you can solve it by passing the context to function my, but this get us back to the begining

Another problem is to define any function in the context not just X2, but this is easy just changing the mk-ctx to:

(define (mk-ctx c f b) (define c:f b) c)

Now I can define any  function in the context:

(setq the-ctx (mk-ctx OO 'f (lambda () (let (cn (context)) (* cn:X 2))) ))
(the-ctx:f)   --> 20

(setq the-ctx (mk-ctx OO 'f (lambda () 1) ))
(the-ctx:f)   --> 1

So the problem is to define a proper my function in order to skip context machinery when defining the function body,
that is function "my" has to return the value of symbol passed in the current context when invoking the funcion f (in the previous example)
which is the contex in which function f is define (OO in the previous example)
ideally this my function not only have to get the current value of the symbol in context but also should be able to set it using setf :

(my 'v)               --->  returns the value of symbol v in context defined using mk-ctx  (current context, OO, when invoking the function f)
(setf (my 'v) 4)   --->  set the value of symbol v to 4 in context defined using mk-ctx

Any idea to define this my function or a schema to resolve symbols in current schema avoid to deal with it inside function body?