Unexpected appearance of "\" when converting string to array

Dear users,

I could not understand why “\” is added irregularly (?) when converting a string to an array. Can anyone help me?

Below the explanation you will see four steps to reproduce the problem:

  1. The code of step 1 is an extract of a code posted in A class or method to convert integer and float to scientific pitch notation? - #52 by prko

  2. The code of step 2 is also an extraction of the same code for musical notation. If you evaluate this code, you will get the following result in the post window, and you will see that there is an unexpected character "" before the second occurrence of “e”:

		@ thisEntry index 1: a4 /e/3/2/e p
		@ thisEntry class: String
		@ thisEntry index 1: [ a4, [ e, 3, 2, \e ], p ]   // <- Why \ is inserted before the second e?
		@ thisEntry class: Array
  1. The code from step 3 is an extraction of the core part dedicated to converting string to array.

  2. The code in step 4 is an extraction of the problematic string from the code in step 2. When evaluated, the output is as expected and “\” is not inserted.

-> [ a4, [ e, 3, 2, e ], p ]

Step to reproduce 1
Evaluate the following function:

(
~test = { |score|
	var partsInTheFirstBar;
	{
		var part1 = [], part2 = [], part3 = [];
		score[1].keys.remove(\bar)
		.do { |partName|
			switch(partName.asString.size,
				2, { part1 = part1.add(partName) },
				3, { part2 = part2.add(partName) },
				4, { part3 = part3.add(partName) }
			);
			partsInTheFirstBar = part1.sort ++ part2.sort ++ part3.sort
		}
	}.();
	
	partsInTheFirstBar.do { |partKey|
		("\n\n\n@ part:" + partKey).postln;
		(1 .. score.size - 1).do { |barIndex|
			var itemsPerBar, partItemsPerBar, voiceIDs;
			itemsPerBar = score[barIndex];
			partItemsPerBar = itemsPerBar[partKey];
			partItemsPerBar.keys.asArray.do { |item|
				if (item.asString[0] == $v) {
					voiceIDs = voiceIDs.add(item)
				}
			};			
			voiceIDs.sort.do { |thisVoiceID, thisVoiceIDIndex|
				var thisVoiceEntries = partItemsPerBar[thisVoiceID];
				thisVoiceEntries.do { |thisEntry, index|
					var stringToArray;
					
					("\n\n\n\t\t@ bar:" + barIndex ++ "\n").postln;
					("\t\t@ thisVoice:" + thisVoiceID).postln;
					("\t\t@ thisEntry index" + index ++ ":" + thisEntry).postln;
					("\t\t@ thisEntry class:" + thisEntry.class).postln;
					
					stringToArray = { |string|
						string.split($ )
						.collect { |string|
							var tupletDetector = { |string|
								if (string[0] != $/) {
									var item = string.replace("/", "_\\").split($_);
									switch (item.size,
										1, {
											item[0].asSymbol }, 
										2, { 
											item.collect { |anItem| anItem.asSymbol }
										},
										4, {
											item.collect { |anItem, index|
												if (index == 1 || (index == 2)) {
													anItem.asString.interpret
												} {
													anItem.asSymbol
												}
											}
										}
									)
								} {
									tupletDetector.(string[1..])
								}
							};
							tupletDetector.(string)
						}
					};
					thisEntry = if (thisEntry.class.asSymbol == \String) {
						stringToArray.(thisEntry)
					} {
						thisEntry
					};
					("\t\t@ thisEntry index" + index ++ ":" + thisEntry).postln;
					("\t\t@ thisEntry class:" + thisEntry.class).postln;
				}
			}
		}
	}
}
)

Step to reproduce 2
Evaluate the following code:

(
~score9 = [
	(   title: 'untitled', composer: 'me', rights: '©'),
	(
		bar: 1,
		p1: (
			v1: [
				// [\t, 120],
				"t 120",
				// [\a4, [\e, 3, 2, \e], \p],
				"a4 /e/3/2/e p"
			]
		)
	)
];

~test.(~score9)
)

Step to reproduce 3
Evaluate the following function:

(
~stringToArray = { |string|
						string.split($ )
						.collect { |string|
							var tupletDetector = { |string|
								if (string[0] != $/) {
									var item = string.replace("/", "_\\").split($_);
									switch (item.size,
										1, {
											item[0].asSymbol }, 
										2, { 
											item.collect { |anItem| anItem.asSymbol }
										},
										4, {
											item.collect { |anItem, index|
												if (index == 1 || (index == 2)) {
													anItem.asString.interpret
												} {
													anItem.asSymbol
												}
											}
										}
									)
								} {
									tupletDetector.(string[1..])
								}
							};
							tupletDetector.(string)
						}
					}
)

Step to reproduce 4
Evaluate the following code:

x = ~stringToArray.("a4 /e_3_2_e p")

but x = ~stringToArray.("a4 /e/3/2/e p") also returns [ a4, [ e, 3, 2, \e ], p ]

OK let’s run it down:

because your string “/e/3/2/e” starts with a $/ you run tupletDetector on string[1..] so “e/2/3/e”

check - let’s evaluate “e/3/2/e”.replace(“/”, "\").split($) // [ e, \3, \2, \e ]

so you are running [ e, \3, \2, \e ].collect _.asString.interpret - the first element is String “e” which interprets also as String “e” - the second is string “\e” which will interpret as Symbol \e

Side note!! have you had a chance to play with scparco? For me this makes this kind of work much easier.

1 Like

Oh, thank you! I am so stupid!

This is weird. On my end it returns [ a4, [ e, 3, 2, e ], p ]. :frowning:
This has caused me to lose my logical thinking because the same code returns incoherent results.

Not yet! I will look at it.