Recent posts

#1
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?


#2
newLISP in the real world / Re: Question on $idx
Last post by cameyo - March 21, 2026, 12:19:38 PM
The previous code is wrong. Sorry.

Let's write a function that associates each index of a list with a different index of the list itself.
(define (sel-idx lst)
  (let ((out '()) (len (length lst)))
    (dolist (el lst)
      ; select and index of the list different from the current
      (while (= (setq idx (rand len)) $idx))
      ;(println "coppia: " $idx idx)
      (push (list $idx idx) out -1))
    out))

Now if lst has only one value, the function should loop (because it's not possible to select an index other than 0):
(sel-idx '(1))
;-> ((0 0))  --> ERROR

If lst has more than one value, the function should work correctly:
(sel-idx '(1 2))
;-> ((0 1) (1 0))  --> OK
(sel-idx '(1 2))
;-> ((0 1) (1 1))  --> ERROR
Why doesn't the function produce correct results?
Because 'until' (and 'while') also have an internal variable $idx.
So we're not comparing the generated value 'idx' to $idx from 'dolist', but to $idx from 'until'.
To fix this, we need to copy the value '$idx' from 'dolist' into a variable and apply it within the 'until' loop.
(define (sel-idx-ok lst)
  (let ((out '()) (len (length lst)) (tmp 0))
    (dolist (el lst)
      (setq tmp $idx)
      ; select and index of the list different from the current
      (while (= (setq idx (rand len)) tmp))
      ;(println "coppia: " $idx idx)
      (push (list tmp idx) out -1))
    out))

(sel-idx-ok '(1))
;-> ... --> infinite loop
(sel-idx-ok '(1 2))
;-> ((0 1) (1 0)) --> OK
(sel-idx '(0 1 2 3 4 5 6 7 8 9))
;-> ((0 4) (1 9) (2 4) (3 8) (4 8) (5 9) (6 1) (7 1) (8 6) (9 6))
#3
newLISP in the real world / Question on $idx
Last post by cameyo - March 16, 2026, 02:04:23 PM
(define (test lst)
  (let (len (length lst))
    (dolist (el lst)
      ; select and index of the list different from the current
      (while (!= (setq idx (rand len)) $idx)))
    (println "index: " idx)))
Why (test '(1 2 3 4 5)) fall (almost always) into an infinite loop?
Why (test '(1)) return always 0? The function should fall into an infinite loop.

I know the answer...
#4
So, what can you actually DO with newLISP? / Prime Numbers
Last post by cameyo - March 13, 2026, 04:58:46 AM
A fast function to generate all prime numbers less than or equal to a given number

(define (primes-to num)
"Generate all prime numbers less than or equal to a given number"
  (cond ((< num 2) '())
        ((< num 3) '(2))
        (true
          (letn ((m (/ (- num 3) 2))
                 (arr (array (+ m 1)))
                 (lim (/ (- (int (sqrt num)) 3) 2))
                 (lst '(2)))
            (for (i 0 lim)
              (when (nil? (arr i))
                (letn ((p (+ (* 2 i) 3))
                       (j (/ (- (* p p) 3) 2)))
                  (for (k j m p (> k m))
                    (setf (arr k) true)))))
            (for (i 0 m)
              (when (nil? (arr i))
                (push (+ (* 2 i) 3) lst -1)))
            lst))))

(time (println (length (primes-to 1e6))))
;-> 78498
;-> 100.292
(time (println (length (primes-to 1e7))))
;-> 664579
;-> 1396.784
(time (println (length (primes-to 1e8))))
;-> 5761455
;-> 15544.004
(time (println (length (primes-to 1e9))))
;-> 50847534
;-> 178960.989

S.O.: Windows 10
CPU: intel i7
RAM: 32 GB
#5
newLISP newS / Re: newlisp.org down again?
Last post by ufko - January 15, 2026, 06:22:16 AM
It has been down for more than 48 hours. Most likely both DNS and hosting were with the same provider and the service was not paid. The domain itself is fine.
#6
newLISP newS / newlisp.org down again?
Last post by boris - January 15, 2026, 12:35:58 AM
I'm getting "server not found" from www.newlisp.org this morning. Anyone else having the same problem?
#7
newLISP newS / Re: Forked newLISP – Meet Rebe...
Last post by ufko - January 09, 2026, 11:19:09 PM
Turbulent back and forth switching between (set 'sym ...) and (set sym ...) in an attempt
to find the right mental model and the paradigm shift.

set without quoted symbol name is the winner.

Summary:

set
  - Standard way to assign a value to a symbol/place.
    - (set a 1)
    - (set a 1 b 2 c '(3 4))
    - (set (nth 1 lst) exp)
    - (set f (fn (a b) ... ))
    - (set f (fn-macro (a b) ... ))
    - .. etc ...
  - Using a quoted symbol name is an error.
  - Replaces:
    - (set 'x 1) - error
    - (setf x 1) - primitive removed
    - (setq x 1) - primitive removed
    - (define x 1) - primitive removed

Purpose:
  - clear, direct symbol creation
  - no confusion anymore, symbol is never quoted
  - no ambiguity, sugars removed, can be aliased (alias 'setf set) if you want
  - no silent behavior

mut
  - *Opt-in*. You can use set all the time
  - Refers to a mutate operation.
  - Changes the value of an existing mutable symbol (created via set, let*, local).
  - Using a quoted symbol name is an error.
  - It is a visual marker for mutation.
  - It is meant for programmers who want to clearly distinguish in code
    where a symbol is created (using set, local, let*) and where it is later mutated (using mut).
  - It prevents quiet mutation of a symbol that was never created as a variable
    (e.g. due to a typo).
    (local (a b c)
       (mut a 1) ; OK: mutating an existing symbol
       (mut x 2) ; ERROR: symbol was never created in any scope (prevents silent bugs)
       (set x 2)  ; SILENT: creates or overwrites a symbol outside this scope as in newLISP
    )

tie
  - Works like newlisp set '
  - Unlike set, the name tie intentionally does not imply a standard assignment operation.
  - For now, intended for two special cases:

  1. When code generates another code containing at least one symbol assignment.
    - (map tie '(a b) '(1 2)) ... here map generates another code (tie 'a 1) (tie 'b 2)
    - (apply tie '(x 120))
    - macros
      (mac (defun _name _args)
        (tie _name (append '(fn ) (list _args) (args))))

  2. When a symbol points to another symbol, allowing indirect modification
    of the target symbol value.
    - (tie 'a 'b) (tie a 10) ... indirect assignment, b is 10.

  - I am not aware of any other cases where tie (and newlisp set 'sym) would need to be used.

  - Using tie in other cases:
    - is considered redundant/needless, use set instead.
    - will not be promoted in the manual as a standard assignment operation,
    - will be discouraged in the manual,
    - will never appear in Rebel ecosystem
    - is user's responsibility, it is not possible to disallow using tie in this way: (tie 'x 1)


func
  Creates a named function. Replaces define in this case.
  (func (f arg)) - OK
  (func f 1) - error, use set
  (func f (fn (arg) ...) - error, use set

If you want to try Rebel, please check the green checkmarks
in GitHub Actions before cloning. The repo moves fast
and may be temporarily broken.

https://github.com/ufko-org/rebel/actions


Ufko.
#8
newLISP newS / Re: Forked newLISP – Meet Rebe...
Last post by hapco - January 03, 2026, 05:49:31 AM
Ok, I apologize. I did say it was no big deal and I never said anything about losing me a a potential user. I'll continue to follow your project with interest and look forward to seeing what you can make of it.
#9
newLISP newS / Re: Forked newLISP – Meet Rebe...
Last post by ufko - January 02, 2026, 10:56:49 PM
Hi.

Losing users who consider long function
names to be language expressiveness is,
in my view, an extremely drastic change.

Rebel is not a subject of discussion;
my post was only an announcement.

Ufko.
#10
newLISP newS / Re: Forked newLISP – Meet Rebe...
Last post by hapco - January 02, 2026, 04:21:18 PM
Thanks, your post made it seem more drastic.

Just for the sake of discussion, though, I think I prefer write-file and append-file to fwrite and fappend. the latter might be more concise, but they are less expressive and not as natural to type. No biggie though. :-)