File lists.icn

Summary

###########################################################################

	File:     lists.icn

	Subject:  Procedures to manipulate lists

	Author:   Ralph E. Griswold

	Date:     June 11, 2001

###########################################################################

   This file is in the public domain.

###########################################################################

	Contributor:  Richard L. Goerwitz

###########################################################################

	file2lst(s)	create list from lines in file

	imag2lst(s)	convert limage() output to list

	l_Bscan(e1)	begin list scanning

	l_Escan(l_OuterEnvir, e2)
			end list scanning

	l_any(l1,l2,i,j)
			any() for list scanning

	l_bal(l1,l2,l3,l,i,j
			bal() for list scanning

	l_find(l1,l2,i,j)
			find() for list scanning

	l_many(l1,l2,i,j)
			many() for list scanning

	l_match(l1,l2,i,j)
			match() for list scanning

	l_move(i)	move() for list scanning

	l_pos(i)	pos() for list scanning

	l_tab(i)	tab() for list scanning

	l_upto(l1,l2,i,j)
			upto() for list scanning

	lclose(L)	close open palindrome

	lcomb(L,i)	list combinations

	lcompact(L)	compact list, mapping out missing values

	ldecollate(I, L)
			list decollation

	ldelete(L, spec)
			list deletion

	ldupl(L, i)	list term duplication

	lequiv(L1, L2)	list equivalence

	levate(L, m, n)	list elevation

	lextend(L, i)	list extension

	lfliph(L)	list horizontal flip (reversal)

	lflipv(L)	list vertical flip

	limage(L)	unadorned list image

	lcollate(L1, L2, ...)
			list collation; like linterl() except stops on
			short list

	lconstant(L)	succeeds and returns element if all are the same

	linterl(L1, L2)	list interleaving

	llayer(L1, L2, ...)
			layer and interleave L1, L2, ... 

	llpad(L, i, x)	list padding at left

	lltrim(L, S)	list left trimming

	lmap(L1,L2,L3)	list mapping

	lpalin(L, x)	list palindrome

	lpermute(L)	list permutations

	lreflect(L, i)  returns L concatenated with its reversal to produce
			palindrome; the values of i determine "end
			conditions" for the reversal:

				0	omit first and last elements; default
				1	omit first element
				2	omit last element
				3	don't omit element

	lremvals(L, x1, x2, ...)
			remove values from list

	lrepl(L, i)	list replication

	lresidue(L, m, i)
			list residue

	lreverse(L)	list reverse

	lrotate(L, i)	list rotation

	lrpad(L, i, x)	list right padding

	lrundown(L1, L2, L3)
			list run down

	lrunup(L1, L2, L3)
			list run up

	lrtrim(L, S)	list right trimming

	lshift(L, i)	shift list terms

	lswap(L)	list element swap

	lunique(L)	keep only unique list elements

	lmaxlen(L, p)	returns the size of the largest value in L.
			If p is given, it is applied to each string as
			as a "length" procedure.  The default for p is
			proc("*", 1).

	lminlen(L, p)	returns the size of the smallest value in L.
			If p is given, it is applied to each string as
			as a "length" procedure.  The default for p is
			proc("*", 1).

	sortkeys(L)	returns list of keys from L, where L is the
			result of sorting a table with option 3 or 4.

	sortvalues(L)	return list of values from L, where L is the
			result of sorting a table with option 3 or 4.

	str2lst(s, i)	creates list with i-character lines from s.  The
			default for i is 1.

###########################################################################

		About List Mapping

  The procedure lmap(L1,L2,L3) maps elements of L1 according to L2
  and L3.  This procedure is the analog for lists of the built-in
  string-mapping function map(s1,s2,s3). Elements in L1 that are
  the same as elements in L2 are mapped into the corresponding ele-
  ments of L3. For example, given the lists
  
     L1 := [1,2,3,4]
     L2 := [4,3,2,1]
     L3 := ["a","b","c","d"]
  
  then
  
     lmap(L1,L2,L3)
  
  produces a new list
  
     ["d","c","b","a"]
  
     Lists that are mapped can have any kinds of elements. The
  operation
  
     x === y
  
  is used to determine if elements x and y are equivalent.
  
     All cases in lmap are handled as they are in map, except that
  no defaults are provided for omitted arguments. As with map, lmap
  can be used for transposition as well as substitution.
  
  Warning:

     If lmap is called with the same lists L2 and L3 as in
  the immediately preceding call, the same mapping is performed,
  even if the values in L2 and L3 have been changed. This improves
  performance, but it may cause unexpected effects.
  
     This ``caching'' of the mapping table based on L2 and L3
  can be easily removed to avoid this potential problem.
  
###########################################################################

	About List Scanning by Richard L. Goerwitz

  PURPOSE: String scanning is terrific, but often I am forced to
  tokenize and work with lists.  So as to make operations on these
  lists as close to corresponding string operations as possible, I've
  implemented a series of list analogues to any(), bal(), find(),
  many(), match(), move(), pos(), tab(), and upto().  Their names are
  just like corresponding string functions, except with a prepended
  "l_" (e.g. l_any()).  Functionally, the list routines parallel the
  string ones closely, except that in place of strings, l_find and
  l_match accept lists as their first argument.  L_any(), l_many(),
  and l_upto() all take either sets of lists or lists of lists (e.g.
  l_tab(l_upto([["a"],["b"],["j","u","n","k"]])).  Note that l_bal(),
  unlike the builtin bal(), has no defaults for the first four
  arguments.  This just seemed appropriate, given that no precise
  list analogue to &cset, etc. occurs.

  The default subject for list scans (analogous to &subject) is
  l_SUBJ.  The equivalent of &pos is l_POS.  Naturally, these
  variables are both global.  They are used pretty much like &subject
  and &pos, except that they are null until a list scanning
  expression has been encountered containing a call to l_Bscan() (on
  which, see below).

  Note that environments cannot be maintained quite as elegantly as
  they can be for the builtin string-scanning functions.  One must
  use instead a set of nested procedure calls, as explained in the
  _Icon Analyst_ 1:6 (June, 1991), p. 1-2.  In particular, one cannot
  suspend, return, or otherwise break out of the nested procedure
  calls.  They can only be exited via failure.  The names of these
  procedures, at least in this implementation, are l_Escan and
  l_Bscan.  Here is one example of how they might be invoked:

      suspend l_Escan(l_Bscan(some_list_or_other), {
          l_tab(10 to *l_SUBJ) & {
              if l_any(l1) | l_match(l2) then
                  old_l_POS + (l_POS-1)
          }
      })

  Note that you cannot do this:

      l_Escan(l_Bscan(some_list_or_other), {
          l_tab(10 to *l_SUBJ) & {
              if l_any(l1) | l_match(l2) then
                  suspend old_l_POS + (l_POS-1)
          }
      })

  Remember, it's no fair to use suspend within the list scanning
  expression.  l_Escan must do all the suspending.  It is perfectly OK,
  though, to nest well-behaved list scanning expressions.  And they can
  be reliably used to generate a series of results as well.

###########################################################################

  Here's another simple example of how one might invoke the l_scan
  routines:

  procedure main()

      l := ["h","e","l","l","o"," ","t","t","t","h","e","r","e"]

      l_Escan(l_Bscan(l), {
          hello_list := l_tab(l_match(["h","e","l","l","o"]))
          every writes(!hello_list)
          write()

          # Note the nested list-scanning expressions.
	   l_Escan(l_Bscan(l_tab(0)), {
	       l_tab(l_many([[" "],["t"]]) - 1)
              every writes(!l_tab(0))
	       write()
          })
      })
  
  end

  The above program simply writes "hello" and "there" on successive
  lines to the standard output.

###########################################################################

  PITFALLS: In general, note that we are comparing lists here instead
  of strings, so l_find("h", l), for instance, will yield an error
  message (use l_find(["h"], l) instead).  The point at which I
  expect this nuance will be most confusing will be in cases where
  one is looking for lists within lists.  Suppose we have a list,

      l1 := ["junk",[["hello"]," ",["there"]],"!","m","o","r","e","junk"]

  and suppose, moreover, that we wish to find the position in l1 at
  which the list

      [["hello"]," ",["there"]]

  occurs.  If, say, we assign [["hello"]," ",["there"]] to the
  variable l2, then our l_find() expression will need to look like

      l_find([l2],l1)

###########################################################################

  Extending scanning to lists is really very difficult.  What I think
  (at least tonight) is that scanning should never have been
  restricted to strings.  It should have been designed to operate on
  all homogenous one-dimensional arrays (vectors, for you LISPers).
  You should be able, in other words, to scan vectors of ints, longs,
  characters - any data type that seems useful.  The only question in
  my mind is how to represent vectors as literals.  Extending strings
  to lists goes beyond the bounds of scanning per-se.  This library is
  therefore something of a stab in the dark.

###########################################################################

  Links:  equiv, indices, numbers

###########################################################################
Procedures:
file2lst, imag2lst, l_Bscan, l_Escan, l_any, l_bal, l_comp, l_find, l_many, l_match, l_move, l_pos, l_tab, l_upto, lblock, lclose, lcollate, lcomb, lcompact, lconstant, ldecollate, ldelete, ldupl, lequiv, levate, lextend, lfliph, lflipv, limage, linterl, llayer, llpad, lltrim, lmap, lmaxlen, lminlen, lpalin, lpermute, lreflect, lremvals, lrepl, lresidue, lreverse, lrotate, lrpad, lrtrim, lrundown, lrunup, lshift, lswap, lunique, sortkeys, sortvalues, str2lst

Records:
l_ScanEnvir

Global variables:
l_POS, l_SUBJ

Links:
equiv.icn, indices.icn, numbers.icn

This file is part of the (main) package.

Source code.

Details
Procedures:

file2lst(s)

: create list from lines in file


imag2lst(seqimage)

: convert limage() output to list


l_Bscan(e1)

: begin list scanning


l_Escan(l_OuterEnvir, e2)

: end list scanning


l_any(l1, l2, i, j)

: any() for list scanning


l_bal(l1, l2, l3, l, i, j)

: bal() for list scanning


l_comp(l1, l2)

 list comparison


l_find(l1, l2, i, j)

: find() for list scanning


l_many(l1, l2, i, j)

: many() for list scanning


l_match(l1, l2, i, j)

: match() for list scanning


l_move(i)

: move() for list scanning


l_pos(i)

: pos() for list scanning


l_tab(i)

: tab() for list scanning


l_upto(l1, l2, i, j)

: upto() for list scanning


lblock(L1, L2)


lclose(L)

: close open palindrome


lcollate(args)

: generalized list collation


lcomb(L, i)

: list combinations


lcompact(seq)

: compact sequence


lconstant(L)

: test list for all terms equal


ldecollate(indices, L)

: list decollation


ldelete(L, spec)

: delete specified list elements


ldupl(L1, L2)

: list term duplication


lequiv(x, y)

: compare lists for equivalence


levate(seq, m, n)

: elevate values


lextend(L, i)

: list extension


lfliph(L)

: list horizontal flip (reversal)


lflipv(L)

: list vertical flip


limage(L)

: list image


linterl(L1, L2)

: list interleaving


llayer(args)

: interleave lists with layering


llpad(L, i, x)

: list padding at left


lltrim(L, S)

: list left trimming


lmap(L1, L2, L3)

: list mapping


lmaxlen(L, p)

: size of largest list entry


lminlen(L, p)

: size of smallest list entry


lpalin(L, x)

: list palindrome


lpermute(L)

: list permutations


lreflect(L, i)

: list reflection


lremvals(L, x)

: remove values from list


lrepl(L, i)

: list replication


lresidue(L, m, i)

: list residue


lreverse(L)

: list reverse


lrotate(L, i)

: list rotation


lrpad(L, i, x)

: list right padding


lrtrim(L, S)

: list right trimming


lrundown(L1, L2, L3)

: list run up


lrunup(L1, L2, L3)

: list run up


lshift(L, i)

: shift list terms


lswap(L)

: list element swap


lunique(L)

: keep only unique list elements


sortkeys(L)

: extract keys from sorted list


sortvalues(L)

: extract values from sorted list


str2lst(s, i)

: list from string


Records:

l_ScanEnvir(subject, pos)


Global variables:
l_POS

l_SUBJ


This page produced by UniDoc on 2021/04/15 @ 23:59:54.