Skip to content

Commit

Permalink
collect -> map rename
Browse files Browse the repository at this point in the history
  • Loading branch information
emicklei committed Sep 11, 2024
1 parent c623242 commit f3a1661
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 68 deletions.
40 changes: 0 additions & 40 deletions core/collect.go

This file was deleted.

59 changes: 59 additions & 0 deletions core/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package core

import (
"bytes"
"fmt"

"github.com/emicklei/melrose/notify"
)

type Map struct {
Target HasValue
Replaceable HasValue
Each Sequenceable
}

func (c Map) S() Sequence {
return SequenceableList{Target: c.Sequenceables()}.S()
}

func (c Map) Storex() string {
var b bytes.Buffer
fmt.Fprintf(&b, "map(%s,%s)", Storex(c.Target), Storex(c.Replaceable))
return b.String()
}

func (c Map) Sequenceables() []Sequenceable {
tv := c.Target.Value()
t, ok := tv.(HasSequenceables)
if !ok {
notify.Warnf("target does not have sequences")
return []Sequenceable{}
}
rv := c.Replaceable.Value()
r, ok := rv.(Replaceable)
if !ok {
notify.Warnf("function does not allow replacement")
return []Sequenceable{}
}
targets := make([]Sequenceable, len(t.Sequenceables()))
for i, each := range t.Sequenceables() {
targets[i] = r.Replaced(c.Each, each)
}
return targets
}

func (c Map) Replaced(from, to Sequenceable) Sequenceable {
if from == Sequenceable(c) {
return to
}
newTarget := c.Target
if t, ok := c.Target.Value().(Replaceable); ok {
newTarget = On(t.Replaced(from, to))
}
newReplaceable := c.Replaceable
if r, ok := c.Replaceable.Value().(Replaceable); ok {
newReplaceable = On(r.Replaced(from, to))
}
return Map{Target: newTarget, Replaceable: newReplaceable, Each: c.Each}
}
16 changes: 16 additions & 0 deletions core/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,19 @@ func ContainsInt(list []int, value int) bool {
}
return false
}

func ReplacedAll(target []Sequenceable, from, to Sequenceable) []Sequenceable {
newTarget := []Sequenceable{}
for _, each := range target {
if IsIdenticalTo(each, from) {
newTarget = append(newTarget, to)
} else {
if other, ok := each.(Replaceable); ok {
newTarget = append(newTarget, other.Replaced(from, to))
} else {
newTarget = append(newTarget, each)
}
}
}
return newTarget
}
13 changes: 7 additions & 6 deletions dsl/eval_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1290,13 +1290,14 @@ onkey('c4',onoff('e')) // uses default input and default output MIDI device`,
},
})

registerFunction(eval, "collect", Function{
Title: "Collect function",
Description: "collect will map each sequence of a collection using a function that references a replacement",
Template: "collect(${1:collection},${2:function-with-underscore})",
registerFunction(eval, "map", Function{
Title: "Map function",
Description: "map will collect tranformations of each sequence of a collection using a function that references a replacement",
Template: "map(${1:collection},${2:function-with-underscore})",
Alias: "collect",
Samples: `j = join(sequence('C E G'),sequence('D F A'))
// uses the special variable named "_"
c = collect(j, transpose(1, _ ))`,
c = map(j, transpose(1, _ ))`,
Func: func(collection any, function any) any {
if _, ok := getValue(collection).(core.HasSequenceables); !ok {
return notify.Panic(errors.New("collection must have sequenceables"))
Expand All @@ -1305,7 +1306,7 @@ onkey('c4',onoff('e')) // uses default input and default output MIDI device`,
return notify.Panic(errors.New("function must allow replacement"))
}
each, _ := ctx.Variables().Get("_")
return core.Collect{
return core.Map{
Target: core.On(collection),
Replaceable: core.On(function),
Each: each.(core.Sequenceable), // todo check
Expand Down
4 changes: 2 additions & 2 deletions dsl/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ func (e *Evaluator) handleAssignment(varName string, r interface{}) (interface{}
// The result is either FunctionResult or a "raw" Go object.
func (e *Evaluator) EvaluateExpression(entry string) (interface{}, error) {
options := []expr.Option{}
// since 1.14.3
for _, each := range []string{"join", "repeat", "trim", "replace", "duration"} {
// since expr 1.14.3
for _, each := range []string{"join", "repeat", "trim", "replace", "duration", "map"} {
options = append(options, expr.DisableBuiltin(each))
}
env := envMap{}
Expand Down
14 changes: 7 additions & 7 deletions dsl/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,28 +265,28 @@ func TestEuclidean(t *testing.T) {
}
}

func TestCollecFraction(t *testing.T) {
func TestMapFraction(t *testing.T) {
e := newTestEvaluator()
r, err := e.EvaluateProgram(`
c = collect(join(note('e')), fraction(8,_))
c = map(join(note('e')), fraction(8,_))
`)
checkError(t, err)
if got, want := r.(core.Collect).Storex(), "collect(join(note('E')),fraction(8,_))"; got != want {
if got, want := r.(core.Map).Storex(), "map(join(note('E')),fraction(8,_))"; got != want {
t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want)
}
if got, want := r.(core.Collect).S().Storex(), "sequence('8E')"; got != want {
if got, want := r.(core.Map).S().Storex(), "sequence('8E')"; got != want {
t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want)
}
}
func TestCollecTranspose(t *testing.T) {
func TestMapTranspose(t *testing.T) {
e := newTestEvaluator()
r, err := e.EvaluateProgram(`
c = collect(join(note('e')), transpose(1,_))
c = map(join(note('e')), transpose(1,_))
`)
checkError(t, err)
if got, want := r.(core.Collect).S().Storex(), "sequence('F')"; got != want {
if got, want := r.(core.Map).S().Storex(), "sequence('F')"; got != want {
t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want)
}
}
15 changes: 2 additions & 13 deletions op/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,9 @@ func parseIndices(src string) [][]int {
return ii
}

// depreacted: use core.ReplacedAll
func replacedAll(target []core.Sequenceable, from, to core.Sequenceable) []core.Sequenceable {
newTarget := []core.Sequenceable{}
for _, each := range target {
if core.IsIdenticalTo(each, from) {
newTarget = append(newTarget, to)
} else {
if other, ok := each.(core.Replaceable); ok {
newTarget = append(newTarget, other.Replaced(from, to))
} else {
newTarget = append(newTarget, each)
}
}
}
return newTarget
return core.ReplacedAll(target, from, to)
}

// "1 (4 5 6) 2 (4 5 6) 3 (4 5 6) 2 (4 5 6)"
Expand Down

0 comments on commit f3a1661

Please sign in to comment.