I managed to find a minimum:
[1,6,4,7,8].inject {|a,b| if a < b then a else b end}
but I can't still find a way to sort list (functional way and not
with existing sort method)
One difficulty is that vectors are difficult to handle with purely
functional programming: you cannot modify them, not a single slot;
when you want to change just one slot of a vector, in purely
functionnal programming, you have to define a whole new vector,
that contains the same elements as the old vector, but for the one
that is "changed".
But you asked first for lists, and I showed you how to implement
lists. So now it should be easy to implement a functionnal sort
algorithm working on lists.
For an exemple here is a simple merge sort. We need a function to
merge two lists:
(def mergelist(list1,list2,lessp)
(if (endp list1)
list2
elsif (endp list2)
list1
elsif (funcall lessp,(first list1),(first list2))
(cons (first list1),(mergelist (rest list1),list2,lessp))
else
(cons (first list2),(mergelist list1,(rest list2),lessp))
end)
end)
irb(main):545:0>
(begin
(terpri)
(printlist (mergelist (list 1,3,5,7,8,9,11),(list
2,4,6,10,11,12,13),(method :<))) (terpri)
end)
(1 2 3 4 5 6 7 8 9 10 11 11 12 13)
nil
Then a function to split a list into two parts separated by a pivot
(one list containing all the elements smaller-or-equal to the
pivot, and the other all the elements greater than the pivot):
(def values(*values)
values
end)
(def splitlistinternal(list,pivot,lessp,less,more)
(if (endp list)
(values less,more)
elsif (funcall lessp,pivot,(first list))
(splitlistinternal (rest list),pivot,lessp,less,(cons (first
list),more)) else
(splitlistinternal (rest list),pivot,lessp,(cons (first
list),less),more) end)
end)
(def splitlist(list,pivot,lessp)
(splitlistinternal list,pivot,lessp,nil,nil)
end)
(def valuelist(values)
(list *values)
end)
irb(main):604:0>
(begin
(terpri)
(printlist (valuelist (splitlist (list 1,2,3,4,5,6,7),3,(method
:<)))) (terpri)
end)
((3 2 1) (7 6 5 4))
nil
With these two utilities, writting a functional merge sort is
trivial:
(def sortlist(list,lessp)
(if ((endp list) or (endp (rest list)))
list
else
(pivot = (first list))
(less,more = (splitlist (rest list),pivot,lessp))
(mergelist (sortlist less,lessp),(cons pivot,(sortlist
more,lessp)),lessp) end)
end)
irb(main):635:0>
(begin
(terpri)
(printlist (mapcar (lambda{|list|
(sortlist list,(method :<))
}),(list (list),(list 1),(list
5,4,3,2,1),(list 1,2,3,4,5),(list 1,3,5,4,2),(list 5,3,1,2,4))))
(terpri) end)
(nil (1) (1 2 3 4 5) (1 2 3 4 5) (1 2 3 4 5) (1 2 3 4 5))
nil