-
Notifications
You must be signed in to change notification settings - Fork 8
5.4 A la Haskell
Important: The methods: map, filter, take, repeat, cycle, takewhile, drop, dropwhile, fold, scan are automatically composed one with the others.
(map '+ (map '* '(1 2 3)))
; is actually transformed into one single loop,
; which takes the following form:
(setq #recipient1 ())
(loop #i1 (quote (1 2 3))
(setq #accu1 (+ (* #i1 #i1) (* #i1 #i1)))
(push #recipient1 #accu1)
)
Hence, when a sequence of calls to these methods is made, the system automatically factorizes them into one single loop.
Hence, thanks to that implementation, it is possible to perform lazy evaluations
If you want to know how your different functions have been composed, the easiest way is to store them in a function and to display the content of that function.
(defun tst(x) (map '* (map '+ x)))
; Displaying the content of 'tst'
(prettify tst)
(defun tst (x)
(block
(setq %content0 ())
(loop %i0 x
(setq %v0 (* (+ %i0 %i0) (+ %i0 %i0)))
(push %content0 %v0)
)
%content0
)
)
Applies action to each element from list and yields a list out of the results.
(for i '(1 2 3 4) (* i i)) ; (1 4 9 16)
Applies an operation to each item in a list
(map '+ '(1 2 3)) returns (2 4 6)
(map '(+ 1) '(1 2 3)) returns (2 3 4)
; important, we interpret (1 -) as (- x 1)
(map '(1 -) '(1 2 3)) returns (0 1 2)
; Important, we interpret (- 1) as (- 1 x)
(map '(- 1) '(1 2 3)) returns (0 -1 -2)
(map (lambda (x) (+ x 1)) '(1 2 3)) returns (2 3 4)
;An amusing example, we execute a shell command
!v=ls
; But 'v' contains strings ending in carriage return.
; This is how you can initialize all the strings at once.
(setq v (map 'trim v))
Filters the items in a list. The condition can be a lambda.
(filter '(< 10) '(1 4 5 10 11 20)) returns (1 4 5)
(filter (lambda (x) (< x 10)) '(1 4 5 10 11 20)) returns (1 4 5)
Drops nb elements from a list and returns the remainder.
Skips all items meeting the condition, then returns the rest.
(dropwhile '( < 10) '(1 3 5 9 10 3 4 12)) returns (10 3 4 12)
Take nb elements from a list.
Create a list, in which value is repeated nb times.
(replicate 4 '(1 2)) ; yields ((1 2) (1 2) (1 2) (1 2))
Create a list, in which value is stored over and over again. It should be associated with a take for instance.
(take 10 (repeat 5)) ; yields: (5 5 5 5 5 5 5 5 5 5)
Create a list, in which we cycle through liste to store in. It should be associated with a take for instance.
(take 10 (cycle '(1 2 3)) ; yields: (1 2 3 1 2 3 1 2 3 1)
Keeps all the elements satisfying the condition and then removes the rest.
(takewhile '( < 10) '(1 3 5 9 10 3 4 12))) ; returns (1 3 5 9)
Infinite range, starting at initial by increment step.
(takewhile '(< 10) (irange 1 2)) ; yields: (1 3 5 7 9)
(takewhile '(< 100) (map '* (irange 1 2))) ; yields: (1 9 25 49 81)
This specific irange is used to avoid creating a list of integers beforehand in a loop with range. It implements an increment-based loop.
(loop i (irange 0 100 1)
(println i)
)
This specific irangein is used to avoid creating a list of integers beforehand in a loop with range. It implements an increment-based loop. The difference with irange is that the bound is part of the values.
(loop i (irangein 0 5 1)
(println i)
)
;0
;1
;2
;3
;4
;5
applies an operation on a list, providing an initial value from the beginning of the list
(foldl '- 10 '(1 2 3)) ; gives 4
Same as foldl but takes the first item in the list as first value
(foldl1 '- '(1 2 3)) ; gives -4
as foldl but starts from the end of the list
as foldl1 but starts from the end of the list
Keeps the list of intermediate items in a list
(scanl '- 10 '(20 30 40)) ; gives (10 -10 -40 -80)
Same thing, but we use the first element of the list for the calculation.
(scanl1 '- '(20 30 40)) ; gives (20 -10 -50)
We start from the end of the list for the accumulation
(scanr '+ 0 '(3 5 2 1)) ; gives (11 8 3 1 0)
We start from the end of the list for the accumulation and use the last item for the operations
Allows to make a list from the list elements given as arguments.
(zip '(1 2 3) '(4 5 6) '(7 8 9)) ; gives ((1 4 7) (2 5 8) (3 6 9))
Allows to apply an operator between list items.
(zipwith '+ '(1 2 3) '(4 5 6) '(7 8 9)) ; yields (12 15 18)
zipwith creates a list based on the type of the first element that is returned by the lambda or the operation. For instance, in the above example, zipwith will return a list of integers: integers.
zipwith can take a last parameter, which can be true or false to force the output to be a regular list:
(type (zipwith '+ '(1 2 3) '(4 5 6) '(7 8 9))) ; yields integers_
(type (zipwith '+ '(1 2 3) '(4 5 6) '(7 8 9) false)) ; yields list_
The non composition operator: !
prevents LispE from combining two structures:
; We let LispE compose the following expression.
; At each step it processes both the scanl1 and the map
(map '* (scanl1 '+ '(10 20 30))) ; result is (10 900 864900)
; We prevent LispE from composing in the following expression:
(!map '* (scanl1 '+ '(10 20 30))) ; result is (100 900 3600)
There are two different sorts of scan/fold functions:
- from the left (indicated with an
l
at the end of the function name) - from the right (indicated with an
r
at the end of the function name)
These two sorts of function not only process lists in a reverse order, they also compute their values in a reverse order.
Compare for instance:
(foldl1 '- '(1 2 3)) ; yields -4
(foldr1 '- '(1 2 3)) ; yields 2
If you use a lambda function then this lambda must take two arguments, but the order of the arguments depends on the type of functions.
- left function, the accumulator is the first argument
- right function, the accumulator is the second argument
; left function, the accumulator is the first argument
(scanl1 (lambda (accu x) (+ accu x 1)) '(1 2 3))
; right function, the accumulator is the second argument
(scanr1 (lambda (x accu) (+ accu x 1)) '(1 2 3))