Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - pda

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

#2
Whither newLISP? / Re: Searching on array
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.
#3
Whither newLISP? / Parametrized access to context
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?


#4
Anything else we might add? / Re:
September 03, 2022, 03:31:46 PM
Sorry to bring up to life such an older post but I think it's interesting to discuss it a bit further


Quote from: Jeff post_id=13069 time=1212583186 user_id=354


Previously, if I wanted to write in an object-oriented style:


(context 'Point)
(setq x 0 y 0) ; default slot values

(define (print-point)
  (println (format "(%d, %d)" x y)))

(context MAIN)
(new Point 'my-point)
(setq my-point:x 4 my-point:y 12)
(my-point:print-point) ; => prints "(4, 12)"


Now, if something changed in the context Point, it would not change in my-point.  This is prototype-based OO, just as in Javascript.


No, an 'object' defined in such a way is not a prototype-based OO at all.  That my-point 'object' has not a refererence to its class neither its prototype, not only it is not a prototyped object but it is not even an object,  by definition an object knows the class it belongs to and this object doesn't know so it's not an object,  in prototype-based OO there's no class, everyting is an object and you create a new object from another object as prototype, so the new created object has a reference to its prototype, the object used as model for creation,  this my-point 'object' has no reference to its prototype so it is not a protoype-based object.  The only reason to call it an object is by the fact it's a data structure that holds data and behaviour.



By contrast, a FOOP object is a real object since it has a reference to its class and encapsulates data and behaviour.


Quote from: Jeff post_id=13069 time=1212583186 user_id=354
Therefore, if I wanted to implement a counter using a closure, I could do so like this:


(context 'Counter)

(define (Counter:Counter ctx (start-from 0))
  (new (context) ctx)
  (setq ctx (eval ctx))
  (setq ctx:current start-from))

(define (increment (n 1)) (inc 'current n))

(define (decrement (n 1)) (dec 'current n))

(context MAIN)

(Counter 'counter 100)
(counter:increment 10)
(counter:increment 12)
(println counter:current) ; => 122



with this code you are using a context to represent an object, that's ok, the problem is you are pretending the object is also an instance of a class, and that's not the case, you are using context to represent both classes and objects, an pretending Counter is a (class) constructor for instance objects of that class, which is not. With


(Counter 'counter 100)

you're pretending to create a new instance counter of class Counter ,  both (class and instance) represented as contexts.  

Pretending this means instance counter knows about its class, Counter, but this is not the case because context counter is a copy of context Counter (thus including all its symbols, same data and functions) but have no reference to Counter context and no idea about a Counter (i.e. a symbol with its class name).



In other ways, let's suppose we have a function returning the class name:


(define (classname) (context))

this function works for the class:  (Counter:classname)  => Counter  but not for the instance  (counter:classname) => counter  when it should return Counter as well, and there's no way to write a function in the instance (context counter) that returns its classname because it has no way to know what class it was copied from


Quote from: Jeff post_id=13069 time=1212583186 user_id=354
I'm not confusing classes and instances :).


yes I think you are ;-)





Anyway as you sure know, if you want to get a closure you don't need all that structure, simply use the context as is:



(context 'Counter)

(define (start  (n 0))  (set 'current n))
(define (increment (n 1)) (inc current n))
(define (decrement (n 1)) (dec current n))

(context MAIN)
(Counter:start 100)
(Counter:increment 10)
(Counter:increment 12)
(println Counter:current) ; => 122
#5
Anything else we might add? / Re: forum problems?
January 06, 2022, 01:37:47 PM
Quote from: newdep post_id=25081 time=1640386029 user_id=38
pasting code ..works again... ;-)


Hallelujah!   ;-)



Is it known the reason of failure?
#6
Anything else we might add? / Re: forum problems?
December 19, 2021, 02:59:20 PM
it seems it is not allowed to type the sentence:
Quoten having a

with n and a quoted with double quotes ("n" and "a")



it also seems it is not allowed to type and eval application in a code block, not (eval) nor "eval" and even it seems you cannot type any word in parens like (x) in a code block



very strange and weird



I've checked with several browser so I'm pretty sure it's not a matter of web browser used.
#7
Quote from: cameyo post_id=25005 time=1617113250 user_id=732
Function to create a function with name and parameters:
(define (make-add name val)
  (let (f nil)
    (setq f (string "(define (" name " x) (+ " val " x))"))
    (setq name (eval-string f))
  name))

Creating a function
(make-add "sum-10" 10)
out: (lambda (x) (+ 10 x))

Using the created function
(sum-10 3)
out: 13

Do you know of another way (instead of using strings) to create a function with another function?


your example of a made-add function to create a sum-10 function:



(define (make-add n v)
  (evaluate (list 'define (list n 'x) (list '+ v 'x))))


and using it:



(make-add 'sum-10 10)
out: (lambda (x) (+ 10 x))
(sum-10 3)
out: 13


a more general way to create any funcion with name n having parameters a and a body b with minor checking of parameters and function name:



(define (mkf n a b)
    (evaluate (and (symbol? n) (list 'define (if (apply and (map symbol? (cons n a))) (cons n a) n) b))))


and using it:



(mkf 'sum-x-y '(x y) '(+ x y))
out: (lambda (x y) (+ x y))
sum-x-y
out: (lambda (x y) (+ x y))
(sum-x-y 4 5)
out: 9


the function expects name and parameters to be symbols and defaults to a symbol definition if you pass bad parameters, that is paremeters which are not symbols, in this case is defines a symbol with the name passed and the evaluated body as value (or nil if evaluation fails). If the name of the function to be defined is not a symbols it returns nil and doesn't define anything:



x
out: nil
y
out: nil
(mkf 'sum-x-y-with-bad-parameters '(x y 3) '(+ x y))
out: ERR
sum-x-y-with-bad-parameters
out: nil
(define x 3)
out: 3
(define y 34)
out: 34
(mkf 'sum-x-y-with-bad-parameters '(x y 3) '(+ x y))
out: 37
sum-x-y-with-bad-parameters
out: 37
(mkf 4 '(x y 3) '(+ x y))
out: nil
(mkf nil '(x y) '(+ x y))
out: nil


Take this as an example about how to face the question, of course it needs more checking to be robust and correct (variable capture...).



Note: in this post "evaluate" means "eval", because phpBB does not allow me to type it even in code section, so assume this code as the very begining:


(define evaluate eval)
#8
Anything else we might add? / forum problems?
December 19, 2021, 01:46:20 PM
is there any problem with the forum?



every time I try to reply including quote and code I get an internal Server Error
#9
newLISP newS / Re: Happy Birthday newLisp
December 19, 2021, 01:29:06 PM
it seems too old for that a young ! ;-)
#10
newLISP and the O.S. / Re: Not start on Win10
December 14, 2021, 01:11:44 PM
Quote from: First_Spectr post_id=24181 time=1512165777 user_id=1252
I found a solution, in my system used java from "jre-9.0.1" folder, I rewrote the command like C:Program FilesJavajre1.8.0_151binjava.exe" -jar .guiserver.jar 64001 newlisp-edit.lsp and now all work perfect. Unfortunately shortcut still not work: guiserver.jar 64001 newlisp-edit.lsp
Error: Could not find or load main class D:Program Files (x86)newlispguiserver.jar
If somebody know how to fix it - let me know please. The basic problem can be considered solved, thank you very much.


if your problem is to execute jre 1.8.0  rather jre 9.0.1 when executing directly a jar file  you should check the file & program association, in a cmd window type:



C:>assoc .jar
.jar=jarfile

C:>ftype | find "jarfile"
jarfile="C:Program Files (x86)Javajre1.8.0_261binjavaw.exe" -jar "%1" %*


you should get the program is associated to jar files in your windows, in my case it is "C:Program Files (x86)Javajre1.8.0_261binjavaw.exe"



if you want to set another one (jre 9.0.1 or in your case jre 1.8.0) simply type:



C:>ftype jarfile="C:Program Files (x86)Javajre1.8.0_261binjavaw.exe" -jar "%1" %*


supposing your jre 1.8.0 is in path C:Program Files (x86)Javajre1.8.0_261, if not replace as convenient



After doing this you can simply type the name of the jar and it will be run with the right java program like in:


guiserver.jar 64001 newlisp-edit.lsp
#11
newLISP and the O.S. / Re: Not start on Win10
December 14, 2021, 01:01:24 PM
Quote from: First_Spectr post_id=24180 time=1512135864 user_id=1252
Interface looks Снимок2.PNG


I think this is more related to wrong paths when executing newlisp-edit.lsp,  check the path variables.
#12
newLISP and the O.S. / Re: Not start on Win10
December 14, 2021, 12:50:06 PM
I see this thread is a bit older but I would write something related in case being of any help for anybody



I had problems executing guiserver a few days ago, the problem is displayed a  "ERR: cannot find working directory" in the console text-area and guiserver was not able to execute newlisp interpreter so you cannot execute anything.



After investigating under the sources for a while I resolved the issue  hard coding the path in  file newlisp-edit.lsp  in order it search in several places (the hardcode one, the HOME env var , etc)



Another problem I had is newlisp is installed by default in Program Files (x86) and that is a read only folder in windows 10, so is complicated to make changes (you can if editing files as administrator or running a cmd as administrator) but for easy going I ended up copying the whole newlisp folder in a writable path,.  



After doing that sometimes I ran the jar in Program Files while using my writable folder as working dir and doing so I got a lot of alert windows saying it cannot find buttons or other objects, maybe your problem could be related to this, try to run everything in the same folder and check if its readable and maybe also writable.  Hope it helps.



It would be great to use a config file for this stuff (similar to settings but a real file) and also it would be great to reverse the control, it would be great to control java from newlisp repl rather to control newlisp repl from java
#13
newLISP and the O.S. / Re: Not start on Win10
December 14, 2021, 12:38:02 PM
Quote from: First_Spectr post_id=24179 time=1512121754 user_id=1252
I removed /local/newLISPsplash.png and now I have many errors like "Could not create image-button", but lisp up and running, thanks for that. Where can I find newLISPsplash.png?


/local is a valid path, it refers to jar itself, that is files in /local are files stored internally in the guiserver.jar file,  for this reason you can refer to newLISPsplash.png since it's an image stored in the jar file, but you can also provide another image using a diferent path such as /tmp/myScreen.png
#14
Quote from: HPW post_id=24974 time=1607372710 user_id=4
I have no problem with the paranthesis and they belong to every lisp.

For me a good editor solves the problem with paranthesis checker.


I agree but this proposal is a funny one and may be interesting as an option in IDE preferences for pretty printing


Quote from: HPW post_id=24974 time=1607372710 user_id=4
(define (initial-clauses str)
  (set 'start (array rows columns (map int (explode str))))
  (for (row 0 (sub1 rows))
    (for (col 0 (sub1 columns))
      (when (> (start row col) 0)
        (push (string (to-var row col (sub1 (start row col))) " 0")
               problem
        )
      )
    )
  )
)

With the proper indention you see which paranthesis belog to the opening paranthesis.


that indentation is far away from proper indentation,  historically well stablished proper indentation for that code is:

(define (initial-clauses str)
   (set 'start (array rows columns (map int (explode str))))
   (for (row 0 (sub1 rows))
     (for (col 0 (sub1 columns))
       (when (> (start row col) 0)
         (push  (string (to-var row col (sub1 (start row col))) " 0")  problem )))))


with minor variatons as a matter of style
#15
pretty interesting but just for pretty printing newlisp code, it's not a notation for code input because is harder than real one and also clumsy since you have to keep the count of opened parens in your head to write the right upper number.



more interesting would be an editor automatically doing the pretty printing or even better the newlisp REPL with some kind of activation