This is a follow-up to my earlier question: Passing an unevaluated part of an association to a function
I'm trying to create a modular dashboard that controls sound volume of an audio system consisting of several speakers.
System settings are given by the following association:
speakers = <|
"speaker1" -> <|"volume" -> 0.5|>,
"speaker2" -> <|"volume" -> 0.7|>
|>
I have a simple widget AdjustOneSpeaker
that takes in a part of the speakers
variable corresponding to one of the speakers, and dynamically adjusts its volume using a slider:
SetAttributes[AdjustOneSpeaker, HoldAll];
AdjustOneSpeaker[speaker_] := {
Slider[Dynamic[speaker["volume"]]],
Dynamic[speaker["volume"]]
};
Passing speakers["speaker1"]
to this widget works fine:
AdjustOneSpeaker[speakers["speaker1"]]
To use AdjustOneSpeaker
function as a building block for a composite dashboard, I must be able to map it over the speakers
association (i.e. over all speakers):
SetAttributes[AdjustAllSpeakers, HoldAll];
AdjustAllSpeakers[speakers_] := AdjustOneSpeaker /@ speakers // Values;
Unfortunately, this operation forces an evaluation of the individual parts of speakers
before they are passed to AdjustOneSpeaker
, making it impossible for the slider to set the volume fields of the global speakers
association (since its argument is no longer a reference to the global field, but an association literal):
AdjustAllSpeakers[speakers]
Association::setps: <|volume->0.5|> in the part assignment is not a symbol. >>
Is there a way to pass an unevaluated part of an unevaluated speakers
association to AdjustOneSpeaker
here?