NewLisp for VisualNEO Win. Part 5.
This fifth tutorial covers four newLISP topics that could improve your VisualNEO application.
A. Test data again
In Tutorial 2 we put attention to predicates. Predicates are used to test data. Two functions are not categorized under Predicates (www.newlisp.org/downloads/manual_frame.html), but they are very useful: exists and for-all.
1. exists
(setq mc-list ‘(2 “reinier” 1 “hello” 3 8 -1750))
→ (2 “reinier” 1 “hello” 3 8 -1750)
(list? mc-list)
→ true
(exists string? mc-list)
→ “reinier”
(exists number? mc-list)
→ 2
To check if the number 0 or 0.0 is part of the list:
(exists zero? mc-list)
→ nil
To check if a number of the list is negative:
(exists < mc-list)
→ -1750
Very interesting is the option to add a custom function to ‘exists’. The function
(fn (x) (> x 3))
in the next example checks if a number of the list is greater than 3. The number 8 is the first one.
(setq mc-list ‘(2 1 3 8 -1750))
(exists (fn (x) (> x 3)) mc-list)
→ 8
To check if a number is part of the list:
(exists (fn (x) (= x 10)) mc-list)
→ nil
or a bit easier
(member 10 mc-list)
→ nil
2. for-all
The function ‘for-all’ checks if all elements in a list, meet the condition of a function. The result is true or nil.
(for-all number? ‘(2 1 3 8 -1750))
→ true
(for-all number? ‘(“Bach” 2 1 3 8 1750))
→ nil
(for-all (fn (x) (= x 1750)) ‘(1750 1750 1750 1750))
→ true
(for-all (fn (x) (= x 1750)) ‘(1685 1750))
→ nil
The command (fn (x) (= x 1750)) is a so called anonymous function (see the next section B).
B. Custom functions
You can define a function. As example, the function sum:
(define (sum x y) (add x y))
You can invoke the function as follows:
(sum 2 3)
→ 5
More interesting is the anonymous function which you can use in iteration situation (see next section C)
(fn (x y) (add x y))
This function can be called e.g. in the for-all function, as you saw in the previous section. More examples:
(define double (fn (x) (+ x x)))
(double 2)
→ 4
(apply (fn (x) (+ x x)) ‘(123))
→ 246
(set ‘db ‘((a 3) (g 2) (c 5)))
(sort db (fn (x y) (>= (last x) (last y))))
→ ((c 5) (a 3) (g 2))
(setq mc-list ‘(“Maeve” “Olivia” “Aurora” “Ada” “Charlotte” “Amara”))
(find “Isla” mc-list (fn (x y) (> (length x) (length y))))
→ 3 ; “Isla” is longer than element 3, “Ada”
(map (fn (x) (pow 2 x)) (sequence 1 10))
→ (2 4 8 16 32 64 128 256 512 1024)
To make your code more readable, you could assign the function to a variable:
(setq mc-pow2 ‘(fn (x) (pow 2 x)))
(map mc-pow2 (sequence 1 10))
→ (2 4 8 16 32 64 128 256 512 1024)
This demonstrates what you can read in newLISP and Lisp texts: source code and data are interchangeable. Really, a wonderful feature!
C. Iteration
NewLISP has several interation functions. The functions do-until, do-while, doargs, dolist, dostring and dotimes can be useful for you. But let’s have a short look at the function ‘for’.
Its normal use is:
(for (x 1 10 1) (print x))
→ 12345678910
or with now step 2
(for (x 1 10 2) (print x))
→ 13579
or with now step 0.5
(for (x 3 2 0.5) (print ” – ” x))
→ 3 – 2.5 – 2
But very nice is the option to add some break condition to the ‘for’ command:
(for (x 1 100 2 (> (* x x) 30)) (print ” – ” x))
→ 1 – 3 – 5
D. Processing power
Sometimes you need to speed up your VisualNEO application, e.g. in case of nested loops. Well, newLISP is your friend. What I did not tell you is that VisualNEO can easily communicate with extensive newLISP scripts. The idea is: pass variables to the newLISP script.
Suppose, you have an application with a text entry object ‘User’. The contents of this text entry object are stored in the VisualNeo variable [mcText]. Users enter their long text. You want to process that text with newLISP. Readable newLISP oneliners are now not possible. How to manage this? Solution: you have only to pass [mcText] to the newLISP code. In a few steps, I’ll explain this to you.
Step 1
Make a second text entry object ‘Code’ with your newLISP source code (position it outside your application window).
The contents of this text entry object are stored in the variable [mcNewLISP-code].
Step 2
Determine the length of user’s text with StrLen:
StrLen “[mcText]” “[mcTextLen]”
Step 3
Add to the a second text entry object ‘Code’ the following commands:
(setq mcStringLen (nbget “[mcTextLen]” 255))
(setq size (int mcStringLen))
(setq mcString (nbget “[mcText]” size))
or in one string:
(setq mcString (nbget “[mcText]” (int (nbget “[mcTextLen]” 255))))
Step 4
Invoke hpwNewLISPCall in your VisualNEO application:
hpwNewLISPCall “[mcNewLISP-code]” “[DllRetvar]”
[DllRetvar] will return the result.
You could also store the result in a separate file. Add to the newLISP code the following at the end:
(setq mcOutputFile (replace “\\” (nbget “[Outputfile]” 255) “/”))
(write-file mcOutputFile mcString)
The VisualNeo variable [Outputfile] could be defined as:
SetVar “[Outputfile]” “[PubDir]temp.txt”
newLISP code will run very fast which enhances your VisualNEO application.
Debugging
It can be handy in case of debugging to set a VisualNEO variable with some newLISP values, i.e. an intermediate result:
(nbset “[CheckVar]” (string mcString ))
E. Conclusion
This was my last tutorial on newLISP and VisualNEO. I hope that it was helpful for you. I think that you will have enough information to continue the newLISP-VisualNEO journey by yourself. Thank you for reading my tutorials.
Reinier Maliepaard
(last update: 08-12-2019)
Comments