diff --git a/src/parser/__tests__/expression.spec.ts b/src/parser/__tests__/expression.spec.ts index 5210e7ed..2388bb59 100644 --- a/src/parser/__tests__/expression.spec.ts +++ b/src/parser/__tests__/expression.spec.ts @@ -2133,6 +2133,11 @@ describe('SonicWeave expression evaluator', () => { const {fraction} = parseSingle('2 -1'); expect(fraction).toBe('1'); }); + + it('keeps unique strings', () => { + const strings = evaluate('keepUnique(["hello", "world", "hello"])'); + expect(strings).toEqual(['hello', 'world']); + }); }); describe('Poor grammar / Fun with "<"', () => { @@ -2170,6 +2175,7 @@ describe('Poor grammar / Fun with "<"', () => { expect(fraction).toBe('9'); }); + // TODO: Move under the correct heading. it('multiplies a monzo from the left', () => { const {fraction} = parseSingle('2 [2 -1>'); expect(fraction).toBe('16/9'); diff --git a/src/parser/__tests__/stdlib.spec.ts b/src/parser/__tests__/stdlib.spec.ts index 16a3056a..a67a9eb5 100644 --- a/src/parser/__tests__/stdlib.spec.ts +++ b/src/parser/__tests__/stdlib.spec.ts @@ -1594,4 +1594,9 @@ describe('SonicWeave standard library', () => { '2/1', ]); }); + + it('preserves equave formatting in organize()', () => { + const scale = expand('1;2/1;organize()'); + expect(scale).toEqual(['2/1']); + }); }); diff --git a/src/stdlib/builtin.ts b/src/stdlib/builtin.ts index 74a4fb8f..3fa5b073 100644 --- a/src/stdlib/builtin.ts +++ b/src/stdlib/builtin.ts @@ -1947,7 +1947,16 @@ function keepUnique(this: ExpressionVisitor, scale?: SonicWeaveValue) { if (!Array.isArray(scale)) { throw new Error('An array is required.'); } + if (!scale.length) { + return []; + } const seen = new Set(); + const equave = scale.pop()!; + if (equave instanceof Interval) { + seen.add(equave.valueOf()); + } else { + scale.push(equave); + } const result: SonicWeavePrimitive[] = []; for (const interval of scale) { const value = interval ? interval.valueOf() : interval; @@ -1957,6 +1966,9 @@ function keepUnique(this: ExpressionVisitor, scale?: SonicWeaveValue) { result.push(interval); seen.add(value); } + if (equave instanceof Interval) { + result.push(equave); + } return result; } keepUnique.__doc__ =