Tips and tricks
From newLISP on Noodles
Contents |
dolist conditional
Suppose you want to iterate through a list and do something on the first match and then break out.
As of newLISP 8.9 this can be done as follows
(dolist (e l (if (find "foo" e) (push e result -1))))
This will iterate through list l and if it finds "foo" in element e it will push the element onto result and exit.
> (set 'l '("baz" "bar" "foo" "moo" "boo"))
("baz" "bar" "foo" "moo" "boo")
> (dolist (e l (if (find "foo" e) (push e result -1))) (println e))
baz
bar
"foo"
> result
("foo")
Evaluating over net-eval
Suppose you want to execute (Foo bar) on a remote box and bar is a string.
Be sure to escape any nested double-quotes in bar like so
(net-eval (list (list host port (append "(Foo \"" (replace "\"" (string bar) "\\\"") "\" )"))))
you can also do it like
(net-eval (list (list host port (append {(Foo "} (replace {"} (string bar) {\"}) {" )}))))
since version 9.0 newLISP will evaluate terms in the node spec lists, making it simpler
(net-eval '((host port (append {(Foo "} (replace {"} (string bar) {\"}) {" )}))))
Non-destructive string replace
newLISP's replace command is destructive
> (set 'foo "Voldemort") "Voldemort" > (replace "o" foo "0") "V0ldem0rt" > foo "V0ldem0rt"
Foo is changed and the replace function evaluates to itself.
To avoid the destruction, wrap foo in string
> (set 'foo "Voldemort") "Voldemort" > (replace "o" (string foo) "0") "V0ldem0rt" > foo "Voldemort"
Setting multiple variables
Set allows multiple assignments, evaluating to the final one
> (set 'a 1 'b 2) 2
Map can also be used with set
> (map set '(x y) '(1 2)) (1 2) > x 1 > y 2
Setq is useful for multiple assignments without quotes.
> (setq a 1 b 2) 2 > a 1 > b 2
Grabbing Regex Patterns from a String
Performing a Single Match
Often you want to extract a substring that matches a regex pattern from a longer string. newLISP offers full regex support. For example.
> (silent (set 'googlehomepage (get-url "http://www.google.com" 5000))) > (regex "http://(.*\.com)" googlehomepage 512) ("http://www.google.com" 538 21 "www.google.com" 545 14)
Set googlehomepage to the content of google.com (and allow 5000 milliseconds to get the page before timing out). silent merely suppresses the evaluated output from appearing on the command line, which would have been the value of googlehomepage.
The regex command that follows searches for the first example of the text string within googlehomepage. The 512 parameter makes the search non-greedy. regex evaluates to a list containing the pattern and possible sub-pattern matches as well as their respective positions and lengths (see above). Certain system variables are also set.
> $0 "http://www.google.com" > $1 "www.google.com" > $2 nil
$0 is the full pattern match; $1 is the sub-pattern match; and $2 ($3, etc.) would have values for additional sub-patterns.
Performing Multiple Matches
To get all the .com links from googlehomepage we can use newLISP's replace command:
> (replace "http://(.*\.com)" (string googlehomepage) (push $1 links) 512) [snip] > links ("groups.google.com" "froogle.google.com" "books.google.com" "news.google.com" "video.google.com" "www.google.com" "www.google.com")
- googlehomepage is wrapped in string to keep it from being changed by the command.
- $1 pushes the subpattern results onto links. $0 would push the entire pattern onto the variable.
- The results are in reverse because they were pushed onto the front of the list.
Since version 9.0 we also have find-all, which can make the task of collecting regex pattern in a text even easier:
> (find-all "http://(.*\.com)" googlehomepage $1 512) ("www.google.com" "www.google.com" "images.google.com" "video.google.com" "news.google.com" "books.google.com" "froogle.google.com" "groups.google.com")
- find-all will not change the contents of the text it is searching, so we don't need to protect it with string.
The non-greedy flag specified with 512 could also be incorporated into the regular espression itself:
(find-all "http://(.*?\.com)" googlehomepage $1)
- the ? makes the .* operation scanning the least possible amount of characters.
