Fixing behavior of Array.flat when it contains strings

Hello,

Sending the message flat to an Array that contains strings, results in the Strings being decomposed to their characters. For example:

["hello", [1, 2, "there"]].flat;

returns:

[ h, e, l, l, o, 1, 2, t, h, e, r, e ]

In my view, this is not the intended behavior, because a String is usually treate as a single object, not an array. I would expect the above to return this instead:

 [ "hello", 1, 2, "there" ]

The fix for this is to add the following method to String:

prFlat { | list |
	^list add: this
}

I committed a pull request for this. Hopefully my thought is correct, but if not, please explain the current behavior of flat in the case of arrays containing Strings.

Best,
Iannis Zannos

ran into the same issue with reshapeLike

["asd",1,2].reshapeLike([[1],[2,3]]) // -> [ [ a, [ s, d ] ] ]

above fix solves my problem as well

I generally resolve this by using Symbols and not Strings:

[\hello, [1, 2, \there]].flat;

-> [ hello, 1, 2, there ]

Hello, this was discussed recently.
There have been some proposals to fix this.
It is still under discussion.

I have a fix in my library sc-hacks-redux.

  • String {
    prFlat { | list |
    ^list add: this
    }

https://github.com/iani/sc-hacks-redux/blob/master/Classes/Audio_Server_Busses/AudioFiles/plusStringAudioFiles.sc

Please check there.
Hope it helps.

Cheers

Iannis Zannos

There are use cases though for arrays of Strings - when you expect to process them further as file names or if they are livecoding dialect strings that need to be able to be decomposed later for example.

Atm I find myself constantly adding safety .asString and .asSymbol calls but it is an annoyance!

It’s probably relatively safe to do this for JUST the flat method, but I would really recommend against this in general. Strings are arrays of characters, and are built on top of many of the fundamental Array-related operation. If these are disrupted, it’s likely to break strings in very weird ways all over sclang. Again, if you want textual objects that are NOT Arrays, and you don’t need any of this functionality - use Symbol.

Hello,

to respond to Scott who issued concerns about changing fundamental Array-related operations:

The method prFlat which I added to String does not affect any other class.
It does not affect the way that flat behaves in any other class either.
In fact, prFlat is used already in the the current distribution of SCClassLibrary,
The related part is found in SequenceableCollection and goes like this:

flat {
^this.prFlat(this.species.new(this.flatSize))
}

prFlat { |list|
this.do({ arg item, i;
if (item.respondsTo(‘prFlat’), {
list = item.prFlat(list);
},{
list = list.add(item);
});
});
^list
}

By changing prFlat in Srtring, it means that the flat method for all other

SequenceableCollection Classes remains as it is.
Only the behavior of String is affected.

Therefore, again, no other part of the system is affected.

According to the above, my change should be safe, but it needs testing to be sure.
Please do test, that is useful for all interested in the issue I think.

Cheers,

Iannis Zannos