Non-numerical targets

Sonority scales

We hear words - of at least word of moderate length, such a as phonology - as a series of peaks of sonority separated by intervening troughs. The peaks correspond, by and large, to what you would think of as the centre of the syllables of the word and the troughs to the syllable margins. Here, for example, is a rough and ready sonority 'trace' of the four syllable word phonology with an equally rough and ready 'phonetic' transcription beneath:

The peaks and troughs of sonority derive, of course, from the individual sonority characteristics of the sounds which are strung together to make up the word. In general, vowels are relatively high in sonority and make up the centres of syllables, while consonants are relatively low in sonority and occur in the margins. But, not surprisingly, when we look more closely, we can make finer disinctions. Of the vowels, /a/ is more sonorous than /i/ and amongst the consonants /l/ and /n/ are more sonorous than /b/ and /d/. In other words, the sounds of speech can be arrayed along a scale of sonority. Within a syllable, as we move from the margin to the centre and then back to the margin again, we typically find that the constituent sounds are arranged, in accord with their individual characteristics, in a regularly ascending then descending pattern of sonority. A detailed 'trace' of blend would, therefore, look like this:

Automatic syllable counting

It follows from such an account of words structure that, if we are provided with a sonority scale which provides a detailed sonority ranking for the sounds of a particular language, we should be able to automate the counting of syllables and maybe even the isolation and analysis of syllables in that language.

For now, suppose that we plan only to build a syllable counter. Suppose too that we are prepared to accept, without dissent, the proposal that the sonority ranking of English sounds is - in part - as follows:

(p, t, k) (b, d, j, g) (f, s) (v, z ) (m, n) (l, r) (h) (y, w) ( i, u) (e, o, 3) (a )

The 11-point scale goes (left to right) from lower to higher, with equally ranked sounds enclosed in the same set of parentheses. A number of sounds have been omitted to avoid the problems of dealing with phonetic sysmbols at this stage. (The number 3 is included, however, to stand for the vowel in the first syllable of phonology.

A Logo syllable counter

We can imagine a Logo syllable counter as a device which scans through a word from beginning to end performing two basic tasks: On this page we are will look just at the first of these tasks, but you can click here to see a simple implementation which does both jobs and provides a syllable count.

Determining segment sonority

Given a sonority ranking of segments with a finite number of levels, it is a simple enough matter to treat the sonority of an individual segment as an integer representing its rank level. Putting it differently, we can reasonably expect a procedure sonority, which accepts a segment name (:segment) as input, to provide a number representing the segment's sonority value as its output.

The sonority scale presented above has almost already the appearance of a Logo object. Suppose we make that ressemblance explicit and treat the scale directly as a list of lists:

make "sonority.scale [ [p t k] [b d j g] [f s] [v z] [m n] [l r] [h] [y w] [ i u] [e o 3] [a ] ]

The members of the first sub-list of scale can be taken to have sonority value 1, the members of the second, sonority value 2 and so on.

The connection between this discussion and the notions of non-numerical targets and input modification in recursive procedures should now be emerging clearly enough. Suppose that the procedure sonority is provided with 3 inputs - not only with :segment but also with an input called :scale (initially the full :sonority.scale) and a 'counter' called :value (initially 1). The first incarnation of sonority will look to see if :segment is a member of first :scale. If it is, it outputs :value, i.e. it outputs 1. If :segment is not a member of first :scale, then a recursive wind through :scale begins. As many recursive calls as necessary are made, with each clone being given a be-headed version of the preceding clone's :scale and a new version of :value (incremented by 1), until some clone somewhere along the line finds a sublist containing :segment in first :scale. At that point, the value of :value will correspond to the sonority of :segment and can be immediately output.

to sonority :segment :scale :value
if member? :segment first :scale [op :value] 
op sonority :segment bf :scale :value + 1 
This technique of nibbling away at list from the head (or indeed from the tail) is one of the most characteristic features of recursive list processing. Notice, however, an inherent danger in this tactic which needs to be guarded against.

First set up :sonority.scale, and copy and define sonority. Now run sonority offering "q as the value for :segment. Clearly, there is no way that the procedure's terminating condition can be met since "q is not a member of any sub-list of :scale. Instead you end up with an error message. At level 12 of the recursion - remember that there are only 11 points in the scale - the poor sonority clone who is trying to find first :scale, tries first on an empty list. Unfortunately, in Logo there is no such thing as the first element of an empty list. What is needed, then, is a fall-back target which can always be achieved. A test for an empty list, right up front, is more often than not the safety net you need to provide. If we suppose that, in the case of sonority, the appropriate value to be output when a segment is not found is zero, then this modification will fix the problem:

to sonority :segment :scale :value
if empty? :scale [op 0] 
if member? :segment first :scale [op :value] 
op sonority :segment bf :scale :value + 1 

Two words of warning

We have been using the word target in a rather special way in these pages. You may feel that the target (= goal) of sonority is to provide a sonority value. From the user's point of view, that is fair enough - and, indeed, it is a sonority value that sonority in the end outputs. We have been more concerned so far, however, with how the recursion is controlled. From this point of view, the target of any self respecting recursive procedure is to come to a satisfactory halt. A target is reached when any one of the terminating conditions is met and the procedure either simply stops (if it is a command) or outputs and stops (if it is an operation). Seen in this light, the fact that sonority outputs a particular sonority value is only the side effect of a successful journey.

We have also tied together the ideas of input modification and target, choosing examples in which the target (the terminating condition) is eventually met as the result of an input being modified on the recursive call. This is perhaps normally the case, but not necessarily so. In sonority the variation in one input has nothing to do with the terminating conditions. True, there is no contradiciton in that. But you may also find procedures in which a target is met independently of whatever happens to the procedure inputs. Outside events - like movements of the hands of a clock in the following familiar scenario - may assume control. If the first terminating condition is met, it matters little how many questions been answered.

to sit :examination.questions
if time.up? [stop.writing]
if empty? :examination.questions [go.home]
answer first :examination.questions
sit bf :examination.questions

Ron Brasington
Department of Linguistic Science
The University of Reading