6.15 Functions Defined with Blocks

You need not restrict yourself to functions that only fit on one line or are written in a piece-wise manner. The body of the function can be a block, as discussed in ugLangBlocks .

Here is a short function that swaps two elements of a list, array or vector.

swap(m,i,j) ==
  temp := m.i
  m.i := m.j
  m.j := temp

Type: Void

The significance of swap is that it has a destructive effect on its first argument.

k := [1,2,3,4,5]
\[\]
[1,2,3,4,5]

Type: List PositiveInteger

swap(k,2,4)
Compiling function swap with type (List PositiveInteger,
   PositiveInteger,PositiveInteger) -> PositiveInteger
\[\]
2

Type: PositiveInteger

You see that the second and fourth elements are interchanged.

k
\[\]
[1,4,3,2,5]

Type: List PositiveInteger

Using this, we write a couple of different sort functions. First, a simple bubble sort. sort:bubble The operation # returns the number of elements in an aggregate.

bubbleSort(m) ==
  n := #m
  for i in 1..(n-1) repeat
    for j in n..(i+1) by -1 repeat
      if m.j < m.(j-1) then swap(m,j,j-1)
  m

Type: Void

Let this be the list we want to sort.

m := [8,4,-3,9]
\[\]
[8,4,-3,9]

Type: List Integer

This is the result of sorting.

bubbleSort(m)
   Compiling function swap with type (List Integer,Integer,Integer) ->
      Integer
+++ |*3;swap;1;G82322| redefined
   Compiling function bubbleSort with type List Integer -> List Integer
\[\]
[-3,4,8,9]

Type: List Integer

Moreover, m is destructively changed to be the sorted version.

m
\[\]
[-3,4,8,9]

Type: List Integer

This function implements an insertion sort. sort:insertion The basic idea is to traverse the list and insert the i-th element in its correct position among the i-1 previous elements. Since we start at the beginning of the list, the list elements before the i-th element have already been placed in ascending order.

insertionSort(m) ==
  for i in 2..#m repeat
    j := i
    while j > 1 and m.j < m.(j-1) repeat
      swap(m,j,j-1)
      j := j - 1
  m

Type: Void

As with our bubble sort, this is a destructive function.

m := [8,4,-3,9]
\[\]
[8,4,-3,9]

Type: List Integer

insertionSort(m)
Compiling function insertionSort with type List Integer -> List
   Integer
\[\]
[-3,4,8,9]

Type: List Integer

m
\[\]
[-3,4,8,9]

Type: List Integer

Neither of the above functions is efficient for sorting large lists since they reference elements by asking for the j-th element of the structure m.

Here is a more efficient bubble sort for lists.

bubbleSort2(m: List Integer): List Integer ==
  null m => m
  l := m
  while not null (r := l.rest) repeat
     r := bubbleSort2 r
     x := l.first
     if x < r.first then
       l.first := r.first
       r.first := x
     l.rest := r
     l := l.rest
  m
   Function declaration bubbleSort2 : List Integer -> List Integer has
      been added to workspace.

Type: Void

Try it out.

bubbleSort2 [3,7,2]
\[\]
[7,3,2]

Type: List Integer

This definition is both recursive and iterative, and is tricky! Unless you are really curious about this definition, we suggest you skip immediately to the next section.

Here are the key points in the definition. First notice that if you are sorting a list with less than two elements, there is nothing to do: just return the list. This definition returns immediately if there are zero elements, and skips the entire while loop if there is just one element.

The second point to realize is that on each outer iteration, the bubble sort ensures that the minimum element is propagated leftmost. Each iteration of the while loop calls bubbleSort2 recursively to sort all but the first element. When finished, the minimum element is either in the first or second position. The conditional expression ensures that it comes first. If it is in the second, then a swap occurs. In any case, the rest of the original list must be updated to hold the result of the recursive call.