Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dictionary.blendUni is identical with Dictionary.blend and both seem redundant in SC 3.10+ #15

Open
eleses opened this issue Mar 31, 2020 · 1 comment

Comments

@eleses
Copy link

eleses commented Mar 31, 2020

I don't understand what is the point of Dictionary.blendUni in extDictBlend.sc. It has the exact same implementation as blend in the same file.

Furthermore, looking at the default implementation of Dictionary.blend in SC 3.10+ (and might be true even in some earlier versions), the whole functionality of extDictBlend has apparently been merged in the SC mainline classlib. The Dictionary.blend implementation in classlib is somewhat different as it relies on merge, but I don't see any big differences in functionality now between what extDictBlend provides and what classlib provides for Dictionary.blend.

Actually, on closer look, there is one difference that I found, which is might be considered a bug in extDictBlend that's been removed in classlib (or a feature added in the latter). extDictBlend does:

			commonKeys.do { |key|
				var spec = specs[key], val;

which bombs with error for the (2nd) example from the current SC help page, copied below:

d = (a: 500, b: 0.001);
e = (a: 300, b: 0.1);
blend(d, e, 0.3, specs: (a: \freq, b: \rq));

but this example works ok with the classlib blend implementation because the latter adds/does an asSpec

			var spec = if (specs.notNil) { specs[key].asSpec };

And there's one semantic difference too, extDictBlend does:

		if (blend == 0.0) { ^this };
		if (blend == 1.0) { ^that };

so regardless of fill value at the extreme ends uncommon keys are added unconditionally but directionally. In contrast, with blend from classlib

blend ( (foo: 1), (bar: 2), 1, false) // -> ( ) with classlib
blendUni ( (foo: 1), (bar: 2), 1, false) // -> ( 'bar': 2 )
blend ( (foo: 1), (bar: 2), 1, true) // -> ( 'bar': 2, 'foo': 1 ) with classlib
blendUni ( (foo: 1), (bar: 2), 1, true) // -> ( 'bar': 2 )

The classilib implementation is more consistent, but it only does inner (fill=false) and outer joins (fill=true) in database terms. extDictBlend does left- and right- joins at the extremes.

@eleses eleses changed the title Dictionary.blendUni is identical with Dictionary.blend Dictionary.blendUni is identical with Dictionary.blend and both seem redundant in SC 3.10+ Apr 1, 2020
@adcxyz
Copy link
Contributor

adcxyz commented Aug 16, 2021

@eleses - thanks for spotting that, and you are right, they are obsolete and can actually be removed now.

For curiosity, I made a blend2 method which has left, right, sect, union merge modes,
and runs ca 5x faster than blend does at the moment.
Curious to hear your opinion on this one :-)

/*
\freq.asSpec.blend(20, 2000); // 200

a = (freq: 20, amp: 0.5, dist: 23);
b = (freq: 2000, pan: 0.2, dist: 12);

bench { 10000.do { a.blend2(b, 0.5, \left, nil, false) } }
bench { 10000.do { a.blend(b, 0.5) } };

a.blend2(b, 0.5, \sect)
a.blend2(b, 0.5, \right)
a.blend2(b, 0.5, \union)

*/

  • ControlSpec {
    blend { |val1, val2, blend = 0.5|
    ^this.map(
    this.unmap(val1).blend(
    this.unmap(val2),
    blend
    )
    );
    }
    }

  • Dictionary {
    // mode is one of [ \left, \right, \sect, \union ]
    blend2 { |dict2, blend = 0.5, mode = \left, specs, warnIfSpecMissing = true|
    var res;

      // if right, swap left <-> right
      if (mode == \right) {
      	^dict2.blend2(this, blend, \left, specs, warnIfSpecMissing);
      };
    
      res = this.class.new;
    
      this.keysValuesDo { |key, lval|
      	var newval;
      	var rval = dict2[key];
      	var spec = specs ? Spec.specs[key];
      	if (rval.isNil) {
      		if (mode != \sect) {
      			res.put(key, lval)
      		};
      	} {
      		// we have both values
      		newval = if (spec.notNil) {
      			spec.blend(lval, rval, blend)
      		} {
      			if (warnIfSpecMissing) {
      				"%: no spec for key % - blending linear.\n".postf(
      					thisMethod, key.cs);
      			};
      			lval.blend(rval, blend);
      		};
      		res.put(key, newval)
      	}
      };
      if (mode == \union) {
      	dict2.keysValuesDo { |key, rval|
      		if (res[key].isNil) {
      			res[key] = rval
      		}
      	}
      };
      ^res
    

    }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants