PLEAC examples - 4. Arrays
4.0. Introduction
If you are asked about the contents of your pockets, or the names of the last three presidents, or how to get to the highway, you recite a list: you name one thing after another in a particular order.Lists are part of your conception of the world.
PicoLisp doesn't support arrays as contiguous pieces of memory. Instead, the standard Lisp linked lists are used.
4.0.1. Example
: (setq Nested '(this that the other))
-> (this that the other)
: (setq Nested '(this that (the other)))
-> (this that (the other))
: (setq Tune '("The" "Star-Spangled" "Banner"))
-> ("The" "Star-Spangled" "Banner")
References
setq
4.1. Specifying a List In Your Program
You want to include a list in your program. This is how you initialize arrays.4.1.1. Example
: (setq A '("quick" "brown" "fox"))
-> ("quick" "brown" "fox")
: (setq A '(Why are you teasing me?))
-> (Why are you teasing me?)
# Lines are (here) read from STDIN.
# Just press a single ENTER to quit.
: (setq Lines (make (char) (while (line T) (link @))))
The boy stood on the burning deck,
It was as hot as glass.
-> ("he boy stood on the burning deck," "It was as hot as glass.")
References
char
line
link
make
setq
while
4.1.2. Example
Create the file 'mydatafile' containing:This is the first line. And this the second. A third line. This is the very last line!Now start PicoLisp and run this code:
: (setq Bigarray
(in "mydatafile"
(make
(until (eof)
(link (line T)) ) ) ) )
-> ("This is the first line." "And this the second." "A third line." "This is the very last line! ")
References
eof
in
line
link
make
setq
until
4.1.3. Example
: (setq
PerlHost "www.perl.com"
HostInfo (in (list 'nslookup PerlHost) (till NIL T)) )
-> "Server:^I^I192.168.178.1^JAddress:^I192.168.178.1#53^J^JNon-authoritative answer:^Jwww.perl.com^Icanonical name = klb.develooper.com.^JName:^Iklb.develooper.com^JAddress: 207.171.7.45^JName:^Iklb.develooper.com^JAddress: 207.171.7.55^JName:^Iklb.develooper.com^JAddress: 2607:f238:3::1:45^JName:^Iklb.develooper.com^JAddress: 2607:f238:3::1:55^J^J"
: (split (chop "Costs only $4.95") " ")
-> (("C" "o" "s" "t" "s") ("o" "n" "l" "y") ("$" "4" "." "9" "5"))
: (mapcar pack (split (chop "Costs only $4.95") " "))
-> ("Costs" "only" "$4.95")
: (setq Ships '("Niña" "Pinta" "Santa María"))
-> ("Niña" "Pinta" "Santa María")
References
chop
mapcar
pack
setq
split
4.2. Printing a List with Commas
You'd like to print out a list with an unknown number of elements with an "and" before the last element, and with commas between each element if there are more than two.4.2.1. Example
: (pack "The " (glue ", " '(big brown dirty hungry)) " fox")
-> "The big, brown, dirty, hungry fox"
: (setq Array '(red yellow green))
-> (red yellow green)
: (prinl "I have " Array " marbles.")
I have redyellowgreen marbles.
-> " marbles."
: (prinl "I have " (glue " " Array) " marbles.")
I have red yellow green marbles.
-> " marbles."
References
glue
pack
prinl
setq
4.2.2. Example
: (de Lists
("just one thing")
("Mutt" "Jeff")
("Peter" "Paul" "Mary")
("To our parents" "Mother Theresa" "God")
("pastrami" "ham and cheese" "peanut butter and jelly" "tuna")
("recycle tired, old phrases" "ponder big, happy thoughts")
("recycle tired, old phrases"
"ponder big, happy thoughts"
"sleep and dream peacefully") )
-> Lists
: (de commifySeries (Lst)
(ifn (cddr Lst)
(glue " and " Lst)
(glue (if (find '((S) (sub? "," S)) Lst) "; " ", ")
(conc
(head -1 Lst)
(cons (pack "and " (last Lst))) ) ) ) )
-> commifySeries
: (for L Lists
(prinl "The list is: " (commifySeries L) ".") )
The list is: just one thing.
The list is: Mutt and Jeff.
The list is: Peter, Paul, and Mary.
The list is: To our parents, Mother Theresa, and God.
The list is: pastrami, ham and cheese, peanut butter and jelly, and tuna.
The list is: recycle tired, old phrases and ponder big, happy thoughts.
The list is: recycle tired, old phrases; ponder big, happy thoughts; and sleep and dream peacefully.
-> "."
References
cddr
conc
cons
de
find
for
glue
head
if
ifn
last
pack
prinl
sub?
4.3. Changing Array Size
You want to enlarge or truncate an array. For example, you might truncate an array of employees that's already sorted by salary to list the five highest-paid employees.Or, if you know how big your array will get and that it will grow piecemeal, it's more efficient to get memory for it in one step by enlarging it just once than it is to keep pushing values onto the end.
4.3.1. Example
: (de whatAboutThatArray ()
(prinl "The array now has " (length People) " elements.")
(prinl "Element #4 is `" (get People 4) "'.") )
-> whatAboutThatArray
: (de People
Crosby Stills Nash Young )
-> People
: (whatAboutThatArray)
The array now has 4 elements.
Element #4 is `Young'.
-> "'."
: (con (tail 2 People))
-> NIL
: (whatAboutThatArray)
The array now has 3 elements.
Element #4 is `'.
-> "'."
: (setq People (need -10000 People))
-> (Crosby Stills Nash NIL NIL NIL NIL ... NIL)
: (whatAboutThatArray)
The array now has 10000 elements.
Element #4 is `'.
-> "'."
References
con
de
get
length
need
prinl
setq
tail
4.4. Doing Something with Every Element in a List
You want to repeat a procedure for every element in a list.Often you use an array to collect information you're interested in; for instance, login names of users who have exceeded their disk quota.
When you finish collecting the information, you want to process it by doing something with every element in the array.
In the disk quota example, you might send each user a stern mail message.
4.3.1. Iterate over a list
: (setq Mylist '( a b c))
-> (a b c)
: (for item Mylist
(println item))
a
b
c
-> c
: (mapc println Mylist)
a
b
c
-> c
References
for
println
setq
4.3.2. Filter records in a file
First create a small file called 'mydata':red light green apples color red traffic light green meadowsThen run this PicoLisp code:
: (in "mydata"
(while (line T)
(and (sub? "green" @) (prinl @)) ) )
green apples
green meadows
-> "green meadows"
References
and
in
line
prinl
sub?
while
4.3.3. Reverse words in lines typed as input
First create a file named 'testflip':this is a line and this is another the birds are swimming with their motherThen run the following PicoLisp code:
: (in "testflip"
(until (eof)
(prinl (glue " " (flip (split (line) " "))))))
line a is this
another is this and
swimming are birds the
mother their with
-> "mother their with"
References
eof
flip
glue
in
line
prinl
split
until
4.3.4. Update all array elements
: (setq Array (1 2 3)) -> (1 2 3) : (map dec Array) -> 2 : Array -> (0 1 2)References dec map setq
4.5. Iterating over an Array by Reference
You have a reference to an array, and you want to use foreach to work with the array's elements.4.5.1. Example
: (setq Lst '(a b c))
-> (a b c)
: (map
'((L)
(println (car L)) # Show the element
(set L 'busted) ) # Modify the element destructively
lst)
a
b
c
-> busted
: Lst
-> (busted busted busted)
: (setq Lst '(a b c))
-> (a b c)
: (for I (length Lst)
(println I (get Lst I)) )
1 a
2 b
3 c
-> c
# Or even better ...
: (for (I . X) Lst
(println I X) )
1 a
2 b
3 c
-> c
: (setq
Fruits '(Apple Blackberry)
FruitRef 'Fruits )
-> Fruits
: (for Fruit (val FruitRef)
(prinl Fruit " tastes good in a pie.") )
Apple tastes good in a pie.
Blackberry tastes good in a pie.
-> " tastes good in a pie."
References
car
for
get
length
map
prinl
println
set
setq
val
4.6. Extracting Unique Elements from a List
You want to eliminate duplicate values from a list, such as when you build the list from a file or from the output of another command.This recipe is equally applicable to removing duplicates as they occur in input and to removing duplicates from an array you've already populated.
4.6.1. Example
: (let Uniq NIL
(for Item '(a b c b c d c d e d e f)
(unless (memq Item Uniq)
(push 'Uniq Item) ) )
Uniq )
-> (f e d c b a)
: (let Seen NIL
(for Item '(a b c b c d c d e d e f)
(accu 'Seen Item 1) )
Seen )
-> ((f . 1) (e . 2) (d . 3) (c . 3) (b . 2) (a . 1))
: (uniq '(a b c b c d c d e d e f))
-> (a b c d e f)
References
accu
for
let
memq
push
uniq
unless
4.6.2. Get list of unique users in system
First create the list of users in the Linux shell:
awk -F':' '{ print $1}' /etc/passwd >users
Then run this code in PicoLisp:
: (in "users"
(uniq
(make
(while (split (line) " ")
(link (pack (car @))) ) ) ) )
-> ("root" "daemon" "bin" "sys" "sync" "games" "man" "lp" "mail" "news" "uucp" "proxy" "www-data" "backup" "list" "irc" "gnats" "nobody" "systemd-network" "systemd-resolve" "syslog" "messagebus" "_apt" "lxd" "uuidd" "dnsmasq" "landscape" "sshd" "pollinate" "arie")
# Print the list sorted alphabetically
: (println 'Users 'logged 'in: (sort @))
Users logged in: ("_apt" "arie" "backup" "bin" "daemon" "dnsmasq" "games" "gnats" "irc" "landscape" "list" "lp" "lxd" "mail" "man" "messagebus" "news" "nobody" "pollinate" "proxy" "root" "sshd" "sync" "sys" "syslog" "systemd-network" "systemd-resolve" "uucp" "uuidd" "www-data")
-> ("_apt" "arie" "backup" "bin" "daemon" "dnsmasq" "games" "gnats" "irc" "landscape" "list" "lp" "lxd" "mail" "man" "messagebus" "news" "nobody" "pollinate" "proxy" "root" "sshd" "sync" "sys" "syslog" "systemd-network" "systemd-resolve" "uucp" "uuidd" "www-data")
References
car
in
line
link
make
pack
split
uniq
while
4.7. Finding Elements in One Array but Not Another
You want to eliminate duplicate values from a list, such as when you build the list from a file or from the output of another command.This recipe is equally applicable to removing duplicates as they occur in input and to removing duplicates from an array you've already populated.
4.7.1. Example
# Intersection (common elements) of two lists : (sect '(a b c d e f) '(a c f h)) -> (a c f) # Use symbols for unique keys : (setq key1 1 key2 2) -> 2 : key1 -> 1 : key2 -> 2 # Using properties : (put 'Hash 'key1 1) -> 1 : (put 'Hash 'key2 2) -> 2 : (get 'Hash 'key1) -> 1 : (get 'Hash 'key2) -> 2 # Using association Lists : (de Hash (key1 . 1) (key2 . 2)) -> Hash : (assoc 'key1 Hash) -> (key1 . 1) : (asoq 'key1 Hash) -> (key1 . 1) : (get Hash 'key1) -> 1 # Using an index tree : (idx 'Hash '(key1 . 1) T) -> ((key1 . 1) (key2 . 2)) : (idx 'Hash '(key2 . 2) T) -> NIL : (lup Hash 'key1) -> (key1 . 1)References asoq assoc de get idx lup put sect setq
4.8. Union, Intersection and Difference of Unique Lists
You have a pair of lists, each having unduplicated items. You'd like to find out which items are in both lists (intersection), one but not the other (difference), or either (union).4.8.1. Example
# Create two sets
: (setq
A (1 3 5 6 7 8)
B (2 3 5 7 9) )
-> (2 3 5 7 9)
# Union of the sets
: (uniq (append A B))
-> (1 3 5 6 7 8 2 9)
# Intersection of the sets
: (sect A B)
-> (3 5 7)
# Difference of the sets
: (diff A B)
-> (1 6 8)
References
append
diff
sect
setq
uniq
4.9. Appending One Array to Another
You want to join two arrays by appending all the elements of one to the end of the other.4.9.1. Example
# Initialize two Lists
: (setq
Members '(Time Flies)
Initiates '(An Arrow) )
-> (An Arrow)
: Members
-> (Time Flies)
: Initiates
-> (An Arrow)
# Non destructive append of the lists
: (append Members Initiates)
-> (Time Flies An Arrow)
: Members
-> (Time Flies)
: Initiates
-> (An Arrow)
# Destructive append of the lists
: (conc Members Initiates)
-> (Time Flies An Arrow)
: Members
-> (Time Flies An Arrow) # Members is overwritten
: Initiates
-> (An Arrow)
# Non destructive insert of an element at some position
: (insert 3 Members 'Like)
-> (Time Flies Like An Arrow)
: Members
-> (Time Flies An Arrow)
# Destructively change the first element of a list
: (set Members 'Fruit)
-> Fruit
: Members
-> (Fruit Flies An Arrow)
# Destructively change the last element of a list
: (set (tail 1 Members) 'Banana)
-> Banana
: Members
-> (Fruit Flies An Banana)
References
append
conc
insert
set
setq
tail
4.10. Reversing an Array
You want to reverse an array.4.10.1. Example
# Note that a destructive function changes one or more of its # actual parameter destructively, but returns the desired result. # Create an example list : (setq List (5 2 8 1 7 9 3 4 6)) -> (5 2 8 1 7 9 3 4 6) # Reverse the element non destructively : (reverse List) -> (6 4 3 9 7 1 8 2 5) : List -> (5 2 8 1 7 9 3 4 6) # Reverse the element destructively : (flip List) -> (6 4 3 9 7 1 8 2 5) : List -> (5) # Reset the example list : (setq List (5 2 8 1 7 9 3 4 6)) -> (5 2 8 1 7 9 3 4 6) # Sort the list destructively ASCENDING : (sort List) -> (1 2 3 4 5 6 7 8 9) : List -> (5 6 7 8 9) # Reset the example list : (setq List (5 2 8 1 7 9 3 4 6)) -> (5 2 8 1 7 9 3 4 6) # Sort the list destructively DESCENDING : (by - sort List) -> (9 8 7 6 5 4 3 2 1) : List -> (5 2 8 1 7 9 3 4 6) # Showing that PicoLisp can sort lists of mixed type elements : (flip (sort '(a 3 1 (1 2 3) d b 4 T NIL (a b c) (x y z) c 2))) -> (T (x y z) (a b c) (1 2 3) d c b a 4 3 2 1 NIL)References by flip reverse setq sort
4.11. Processing Multiple Elements of an Array
You want to pop or shift multiple elements at a time.4.11.1. Example
# Destructively cut a number of elements off of the front of a list
: (setq List '(a b c d e f g))
-> (a b c d e f g)
: (cut 3 'List)
-> (a b c)
: List
-> (d e f g)
# Alters the list; chop off the last 3 elements
: (setq List '(a b c d e f g))
-> (a b c d e f g)
: (tail 3 List) # Non destructive
-> (e f g)
: List
-> (a b c d e f g)
: (con (nth List 4)) # Destructive
-> NIL
: List
-> (a b c d)
# Pop elements off a list
: (setq
Friends '(Peter Paul Mary Jim Tim)
This (pop 'Friends)
That (pop 'Friends) )
-> Paul
: This
-> Peter
: That
-> Paul
: Friends
-> (Mary Jim Tim)
# Another example
: (setq
Beverages '(Dew Jolt Cola Sprite Fresca)
Pair (tail 2 Beverages) # Non destructive
Beverages (head 3 Beverages) ) # Destructive
-> (Dew Jolt Cola)
: Pair
-> (Sprite Fresca)
: Beverages
-> (Dew Jolt Cola)
References
con
cut
head
nth
pop
setq
tail
4.12. Find First Element that passes a Test
You want the first element in the list (or its index) that passes a test.Alternatively, you want to know whether any element passes the test.
The test can be simple identity ("Is this element in the list?")[1] or more complex ("I have a list of Employee objects, sorted from highest salary to lowest. Which manager has the highest salary?").
Simple cases normally only require the value of the element, but when the array itself will be altered. You probably need to know the index number of the first matching element.
4.12.1. Example
# Initialize array of employees
: (setq Employees '(emp1 emp2 emp3 emp4 emp5))
-> (emp1 emp2 emp3 emp4 emp5)
# Give all employees a name property
: (mapc put
Employees
'(name .)
'("Abel" "Jones" "Millner" "Noles" "Zaphod") )
-> "Zaphod"
# Give all employees a category property
: (mapc put
Employees
'(category .)
'(engineer cook teacher engineer vicar) )
-> vicar
# Now show the employees with all their properties
: (mapc show Employees)
emp1 NIL
category engineer
name "Abel"
emp2 NIL
category cook
name "Jones"
emp3 NIL
category teacher
name "Millner"
emp4 NIL
category engineer
name "Noles"
emp5 NIL
category vicar
name "Zaphod"
-> emp5
# ------------------------------------------------------------------
# Find first employee with a 'category of 'engineer
# ------------------------------------------------------------------
# This example deserves a bit of extra explanation.
#
# The syntax of 'with' is (with 'sym . prg) -> any
#
# In this case 'sym' is the result of the 'find' operation,
# being one of the employees in the list.
#
# The function 'with' first saves the current 'This' object and
# then sets this special variable 'This' to the result of the
# 'find' function. When 'prg' is finished 'with' resets 'This'
# to its original value (from before the 'with' call) which
# is totally irrelevant in this case.
#
# So, when 'prg' (the 'prinl') is being executed, 'This' points
# to the employee just found. Hence the function calls to ':'
# will work properly.
# ------------------------------------------------------------------
# Another gem in this code:
# ------------------------------------------------------------------
# The first argument of the 'find' function is an anonymous function
# (lambda expression). Such a function always starts with a list of
# the formal parameters, but in this case the one formal parameter
# is named 'This'.
#
# When using lexical scoping that name would be totally insignificant
# but PicoLisp is dynamically scoped!
#
# This implies that 'This' which is a valid formal parameter actually
# corresponds to the global special variable 'This'.
#
# And that in turn makes it useful, because we now can use the ':'
# function, which refers to a property of the current object, which
# thus happens to be stored in the variable 'This'.
#
# Nice huh?
: (with
(find # sym
'((This) (== 'engineer (: category)))
Employees )
(prinl "First engineer found is: " (: name)) ) # prg
First engineer found is: Abel
-> "Abel"
References
:
==
find
mapc
prinl
put
setq
show
This
with
4.13. Find All Elements that Match Certain Criteria
From a list, you want only the elements that match certain criteria.This notion of extracting a subset of a larger list is common.
It's how you find all engineers in a list of employees, all users in the "staff " group, and all the filenames you're interested in.
4.13.1. Example
: (de Nums 84598 4439223 248749 2488711 233716 3375644 211118) -> Nums : (filter '((N) (> N 1000000)) Nums) -> (4439223 2488711 3375644) : (filter > Nums (1000000 .)) -> (4439223 2488711 3375644)References > de filter
4.13.2. Employees revisited...
: (setq Employees '(emp1 emp2 emp3 emp4 emp5))
-> (emp1 emp2 emp3 emp4 emp5)
: (mapc put
Employees
'(name .)
'("Abel" "Jones" "Millner" "Noles" "Zaphod") )
-> "Zaphod"
: (mapc put
Employees
'(position .)
'(engineer cook teacher engineer vicar) )
-> vicar
: (mapc show Employees)
emp1 NIL
position engineer
name "Abel"
emp2 NIL
position cook
name "Jones"
emp3 NIL
position teacher
name "Millner"
emp4 NIL
position engineer
name "Noles"
emp5 NIL
position vicar
name "Zaphod"
-> emp5
# See 4.12.1. for better explanation
: (filter '((This) (== 'engineer (: position))) Employees)
-> (emp1 emp4)
References
:
==
filter
mapc
put
setq
show
This
4.14. Sorting an Array Numerically
You want to sort a list of numbers.Note: PicoLisp 'sort' destructively alters the input list!
4.14.1. Example
# Standard ASCENDING sort : (setq Lst (23 12 54 11 19 1 4 47)) -> (23 12 54 11 19 1 4 47) : (sort Lst) -> (1 4 11 12 19 23 47 54) : Lst -> (23 47 54) # 'sort' is destructive! # Use 'flip' to reverse the outcome of the 'sort' : (setq Lst (23 12 54 11 19 1 4 47)) -> (23 12 54 11 19 1 4 47) : (flip (sort Lst)) -> (54 47 23 19 12 11 4 1) : Lst -> (23 19 12 11 4 1) # 'sort' is destructive! # Use a helper function (like '>') to determine # the desired sort order. : (setq Lst (23 12 54 11 19 1 4 47)) -> (23 12 54 11 19 1 4 47) : (sort Lst >) -> (54 47 23 19 12 11 4 1) : Lst -> (23 19 12 11 4 1) # 'sort' is destructive! # Standard DESCENDING sort : (setq Lst (23 12 54 11 19 1 4 47)) -> (23 12 54 11 19 1 4 47) : (by - sort Lst) -> (54 47 23 19 12 11 4 1) : Lst -> (23 12 54 11 19 1 4 47) # 'sort' is destructive!References - > by flip setq sort
4.15. Sorting a List by Computable Field
You want to sort a list by something more complex than a simple string or numeric comparison.This is common when working with objects ("sort by the employee's salary") or complex data structures ("sort by the third element in the array that this is a reference to").
It's also applicable when you want to sort by more than one key, for instance, sorting by birthday and then by name when multiple people have the same birthday.
4.15.1. Sort using a helper function
# Same as 14.4.1. where we did (by - sort Lst)
# In this case we sort on the 'cdr' part.
# The cdrs before are: (7 3 1 2)
: (by cdr sort '((4 . 7) (19 . 3) (8 . 1) (4 . 2)))
-> ((8 . 1) (4 . 2) (19 . 3) (4 . 7))
# The cdrs after are now in sorted order: (1 2 3 7)
# But, most important, this sorts ON the cdr, but
# orders the pairs!
# Although the next code fragment does exacly the same,
# it is not recommended, because it is slower and needs
# more code to do the same.
: (sort
'((4 . 7) (19 . 3) (8 . 1) (4 . 2))
'((X Y) (> (cdr Y) (cdr X))) )
-> ((8 . 1) (4 . 2) (19 . 3) (4 . 7))
References
>
cdr
by
sort
4.15.2. Employees revisited again ...
# Create Employees and their properties
: (setq Employees '(emp1 emp2 emp3 emp4 emp5))
-> (emp1 emp2 emp3 emp4 emp5)
: (mapc put
Employees
'(name .)
'("Jones" "Zaphod" "Millner" "Abel" "Noles") )
-> "Noles"
: (mapc put
Employees
'(salary .)
'(50000 40000 60000 30000 45000) )
-> 45000
: (mapc put
Employees
'(age .)
'(50 30 28 54 45) )
-> 45
: (mapc show Employees)
emp1 NIL
age 50
salary 50000
name "Jones"
emp2 NIL
age 30
salary 40000
name "Zaphod"
emp3 NIL
age 28
salary 60000
name "Millner"
emp4 NIL
age 54
salary 30000
name "Abel"
emp5 NIL
age 45
salary 45000
name "Noles"
-> emp5
: (for This (by '((This) (: name)) sort Employees)
(prinl (: name) " earns $" (: salary)) )
Abel earns $30000
Jones earns $50000
Millner earns $60000
Noles earns $45000
Zaphod earns $40000
-> 40000
# Sort using an anonymous function.
# In this case this function creates pairs of the name and age properties,
# and 'sort' sorts on them. The ultimate order is the same as when we
# would have sorted only on the 'name'.
: (by '((This) (cons (: name) (: age))) sort Employees)
-> (emp4 emp1 emp3 emp5 emp2)
References
:
by
cons
for
mapc
prinl
put
setq
show
sort
This
4.15.3. Other examples of sorting using helper functions
# Sort on the second position of the names
: (setq Names '(Armstrong McCarthy Iverson Kay Hickey Rakocevic))
-> (Armstrong McCarthy Iverson Kay Hickey Rakocevic)
: (by '((S) (cadr (chop S))) sort Names)
-> (Kay Rakocevic McCarthy Hickey Armstrong Iverson)
# Sort on the length of the names
: (by length sort Names)
-> (Kay Hickey Iverson McCarthy Armstrong Rakocevic)
# A bit complicated example.
# It creates a new list, containing in order:
# 1. the 4th elemnt of the input line
# 2. the 3rd element of the input line
# 3. the first element of the input line
# where elements are split at ':' characters,
# and the 3 new elements in the output list are split
# into lists of single characters.
: (sort
(in "passwd"
(make
(while (split (line) ":")
(link (mix @ 4 3 1)) ) ) ) )
-> ((("0") ("0") ("r" "o" "o" "t")) (("1") ("1") ("d" "a" "e" "m" "o" "n")) (("1") ("2" "0" "1") ("p" "a" "u" "l")) (("1" "1") ("1" "1") ("l" "p")))
References
by
cadr
chop
in
length
line
link
make
mix
setq
sort
split
while
4.16. Implementing a Circular List
You want to create and manipulate a circular list.4.16.1. Example
: (circ 'a) -> (a .) : (circ 'a 'b 'c) -> (a b c .) : (rot @) -> (c a b .)References circ rot
4.17. Randomizing the order in an Array
You want to shuffle the elements of an array randomly.The obvious application is writing a card game, where you must shuffle a deck of cards, but it is equally applicable to any situation where you want to deal with elements of an array in a random order.
4.17.1. Example
: (setq Lst (12 5 2 9 4 20 101 3 12)) -> (12 5 2 9 4 20 101 3 12) : (by '(NIL (rand)) sort Lst) -> (4 2 5 12 101 20 12 3 9)References by rand setq sort
4.18. Show words column by column on a page
Have you ever wondered how programs like ls generate columns of sorted output that you read down the columns instead of across the rows?For example:
awk cp ed login mount rmdir sum basename csh egrep ls mt sed sync cat date fgrep mail mv sh tar chgrp dd grep mkdir ps sort touch chmod df kill mknod pwd stty vi chown echo ln more rm su
4.18.1. Example
Fist create the input file called 'colwords' containing:awk basename cat chgrp chmod chown cp csh date dd df echo ed egrep fgrep grep kill ln login ls mail mkdir mknod more mount mt mv ps pwd rm rmdir sed sh sort stty su sum sync tar touch vithen create a PicoLisp script named 'colshow':
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
# words - gather lines, present in columns
(setq
Data (in "colwords"
(make
(until (eof)
(link (line T)) ) ) )
Maxlen (inc (length (maxi length Data)))
Cols (max (/ (or (format (sys "COLUMNS")) 80) Maxlen) 1)
Rows (/ (+ (length Data) Cols) Cols)
Data (make (while Data (link (cut Rows 'Data)))) )
(while (find bool Data)
(map
'((D) (space (- Maxlen (length (prin (pop D))))))
Data )
(prinl) )
(bye)
and then execute those Linux commands:
chmod 777 colshow ./colshowwhich shows the following:
awk cp ed login mount rmdir sum basename csh egrep ls mt sed sync cat date fgrep mail mv sh tar chgrp dd grep mkdir ps sort touch chmod df kill mknod pwd stty vi chown echo ln more rm suReferences - / + bool bye cut eof find format in inc length line link make map max maxi or pop prin prinl setq space sys until while
4.19. Program: permute
Have you ever wanted to generate all possible permutations of an array or to execute some code for every possible permutation? Example: permutate (1 2 3 ) -> (1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)4.19.1. Example
: (de permute (Lst)
(ifn (cdr Lst)
(cons Lst)
(mapcan
'((X)
(mapcar
'((Y) (cons X Y))
(permute (delete X Lst)) ) )
Lst ) ) )
-> permute
: (mapc println (permute '(man bites dog)))
(man bites dog)
(man dog bites)
(bites man dog)
(bites dog man)
(dog man bites)
(dog bites man)
-> (dog bites man)
References
cdr
cons
de
delete
ifn
mapc
mapcan
mapcar
printlnhttp://picolisp.com/wiki/?pcepleacarrays
| 23jun18 | ArievW |
