# How can I compare a dynamic variable with a literal in Mathematica?

I'm doing a Mathematica Notebook and I want to make an alarm clock. Something like this:

SetAttributes[Horas, HoldRest]

(* Get System Hour *)
Hours = Dynamic[Refresh[DateList[][[4]], UpdateInterval -> 1]];

SetAttributes[Mins, HoldRest]

(* Get System Mins *)
Mins = Dynamic[Refresh[DateList[][[5]], UpdateInterval -> 1]];

If[
SameQ[ToString[Hours], ToString[alarmh]]
&& SameQ[ToString[Mins],ToString[alarmm]],
Quiet@EmitSound[Sound[SoundNote["D", 1,"Tinklebell"]]]
];


alarmm and alarmh are variables that the user select from a listbox When the variables from the listbox are the same with the system hour I want to sound a bell.

The problem is that if I make Dynamic variable I can't compare them, but if I do this:

Refresh[DateList[][[5]], UpdateInterval -> 1];


I can compare between them, but the time doesn't update...

How can I make it update?

-

## migrated from stackoverflow.comMar 14 '12 at 19:57

This question came from our site for professional and enthusiast programmers.

Hey ... 2012 questions tagged Mma on 2012 ... this will never going to happen again ... –  belisarius Mar 13 '12 at 14:47
Anyone knows how can i do this? –  GRiPHuS Mar 13 '12 at 19:12
I´m trying to build an alarm clock, I think the problem is when I make a dynamic variable, this variable has not a format like String, int..., for this reason I cant compare a dynamic variable with another literal variable... Thanks! –  GRiPHuS Mar 14 '12 at 8:58
Welcome user1266140 to Mathematica.SE! As to your question: Dynamic for a a background task is generally not a good idea as it only executes as long as the cell containing it is visible in the frontend. I feel what you're looking for can be achieved with timed evaluations. –  Sjoerd C. de Vries Mar 14 '12 at 9:29
Thank you for your comment. But I have a question, if I use timed evaluations, could I compare the values between the hour system and a literal variable? –  GRiPHuS Mar 14 '12 at 10:01

## 3 Answers

Manipulate will work. This simple alarm will sound for 1 minute or shorter period if you hit reset:

Manipulate[If[Refresh[DateList[], UpdateInterval -> 1][[4 ;; 5]] ==
{hours, minutes} && oo, EmitSound[Sound[SoundNote["C", 1]]]];
Text@Style[DateString[], 20], {{hours, 0}, Range[25] - 1}, {{minutes, 0},
Range[61] - 1}, {{oo, True, "alarm"}, {True -> "ON", False -> "OFF"}}]


-

### Dynamic doesn't work the way you think it does. See this answer for a full explanation.

In short, Dynamic doesn't do anything until it is actually displayed on screen. Therefore you only make a (string) copy of your code when you do:

hours = Dynamic[Refresh[DateList[][[4]], UpdateInterval -> 1]];

ToString[hours]

"Dynamic[Refresh[DateList[][[4]], UpdateInterval -> 1]]"   (* output *)


### ToString is apparently extraneous

The format returned by DateList[] is list of numerical values. As far as I can tell you should not be using ToString here at all.

### You probably want something else anyway

I don't really understand what you are trying to do. My closest guess is this:

PopupMenu[Dynamic[alarmh], Range[0, 23]]
PopupMenu[Dynamic[alarmm], Range[0, 59]]

DynamicModule[{hours, mins},
Dynamic[
{hours, mins} = DateList[][[{4, 5}]];
If[
alarmh == hours && alarmm == mins,
Quiet@EmitSound[Sound[SoundNote["D", 1, "Tinklebell"]]]
];
"This must be displayed!",
UpdateInterval -> 1
]
]


The hours and minutes are selected from the menus. Observe that the output of Dynamic, here arbitrarily "This must be displayed!" must remain visible for the alarm to work. As soon as you delete that output expression, the alarm will cease.

I suspect that you probably want a background alarm process.
If that is the case you should look at Timed Evaluations.
If you use Mathematica version 7 you should find this of interest.

-
+1 But your sentence "Dynamic doesn't work the way you think it does" is quite weak. Actually, Dynamic doesn't work the way almost everybody think it does. –  belisarius Mar 15 '12 at 1:51
@belisarius that's why I immediately followed the sentence with a link. How would you write this differently? I wanted to concisely yet firmly convey that the reader needs to reexamine the behavior of Dynamic. (thanks for +1) –  Mr.Wizard Mar 15 '12 at 8:18
Mine was not a critique. Just an observation about the mind setting needed to use Dynamic. It follows an unusual paradigm. Perhaps someone versed on CS could come up with a name for it. –  belisarius Mar 15 '12 at 14:08

Setting the alarm one minute from now:

{alarmh, alarmm} = Date[][[{4, 5}]] + {0, 1};


Defining a timed task. It executes once every second:

myTask =
CreateScheduledTask[
If[
Date[][[{4, 5}]] == {alarmh, alarmm},
EmitSound[Sound[SoundNote[]]]
];,
1];


Note that this rings for a whole minute once the set time is reached since the task is executed 60 times in the minute you have set. It's easy to update the code to change this behaviour.

Start the task:

StartScheduledTask[myTask];


Remove it if no longer useful. Either this task:

RemoveScheduledTask[myTask];


...or all tasks that may be running:

RemoveScheduledTask[ScheduledTasks[]];


Based on your comments it seems that the problem you really have is using the dynamic values of the Hours and Minutes variables. You assigned these variables to the rather complex but mostly invisible output of Dynamic. If you move the assignments to within Dynamic it works OK. See the difference here:

s1 = Dynamic[Date[][[6]], UpdateInterval -> 1]
Dynamic[s2 = Date[][[6]], UpdateInterval -> 1]
Dynamic[{s1, Head[s1], s2, Head[s2]}]


-