We are talking to a beginner here. One of the important things for a beginner to understand is the idea of hiding stuff and thinking in terms of asking objects to do things for you. For example, in Java you historically did final int n = aString.length(); for (int i = 0; i < n; i++) { final char c = aString.charAt(i); ... }
Here all the loop control is *outside* the string, and if you wanted to use some other data structure you would have to change the code. But in Smalltalk, you ask the *object* to manage the iteration. For collections in general, we have aCollection do: [:anElement | ... ] For sequences we also have aSequence withIndexDo: [:anElement :itsIndex | ...] where the sequence need not be a stored sequence and need not be efficiently indexable. (And indeed, in Java these days, Strings *aren't* efficiently indexable, thanks to using UTF-16 internally.) Using enumeration methods (a) makes your code easier to read (b) makes your code easier to write (as there is lots of fiddly detail you don't write at all, it's there once and for all in the class) (c) makes your code more adaptable (the object needs to support #withIndexDo: and that is *all* you demand of it). indexWhereBasementFirstReached: input "The input is a sequence in which the character ( means to go up a floor and the character ) means to go down a floor. Answer the index of the character where the floor below the initial floor is first reached. If that floor is not reached, e.g., if the input is empty, answer 0. This is the same convention as #indexOf:." |floor| floor := 0. input withIndexDo: [:char :index | char = $( ifTrue: [floor := floor + 1]. char = $) ifTrue: [floor := floor - 1]. floor = -1 ifTrue: [^index]]. ^0 For example, we could add the #withIndexDo: method to Stream, which already has #do: withIndexDo: elementAndIndexBlock "Iterate over the 'future values' remaining in this stream, passing each in turn to the block argument, together with an index starting at 1 for the first value passed to the block." |index| index := 0. self do: [:each | elementAndIndexBlock value: each value: (index := index + 1)]. Now the #indexWhereBasementFirstReached: method will work on input streams as well as strings, so it could, for example, handle a terabyte long sequence held in a file. On Sat, 10 Nov 2018 at 06:17, Roelof Wobben <r.wob...@home.nl> wrote: > hmm. > > When I try this on P7 > > |input stepChanges floor| > input := '((('. > floor := 0. > stepChanges := input collect: [ :c | > floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). > floor > ]. > > stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input > yo' ]. > > then I see this error message : Improper store to indexable object. > > Roelof > > > Op 9-11-2018 om 17:39 schreef Roelof Wobben: > > stepChanges := input collect: [ :c | > floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). > floor > ]. > > stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input > yo' ]. > > >