Reputation: 3781
My code for display all days in this year.
I don't understand why if NewSec =< EndSec -> init:stop() end
did not execute the first time in run_calendar?
I expect init:stop() could be executed first time but it is not.
What is wrong?
Code:
-module(cal).
-export([main/0]).
main() ->
StartSec = calendar:datetime_to_gregorian_seconds({{2009,1,1},{0,0,0}}),
EndSec = calendar:datetime_to_gregorian_seconds({{2009,12,31},{0,0,0}}),
run_calendar(StartSec,EndSec).
run_calendar(CurSec, EndSec) ->
{Date,_Time} = calendar:gregorian_seconds_to_datetime(CurSec),
io:format("~p~n", [Date]),
NewSec = CurSec + 60*60*24,
if NewSec =< EndSec -> init:stop() end,
run_calendar(NewSec, EndSec).
Result:
wk# erlc cal.erl
wk# erl -noshell -s cal main
{2009,1,1}
{2009,1,2}
{2009,1,3}
{2009,1,4}
{2009,1,5}
...
{2009,12,22}
{2009,12,23}
{2009,12,24}
{2009,12,25}
{2009,12,26}
{2009,12,27}
{2009,12,28}
{2009,12,29}
{2009,12,30}
{2009,12,31}
wk#
Upvotes: 0
Views: 267
Reputation: 1339
You have a mistake in your if statement
You said
if NewSec =< EndSec -> init:stop() end,
This is incorrect. You have to write something like:
if A =< B -> do something ...; true -> do something else end
The if syntax is
if Condition1 -> Actions1; Condition2 -> Actions2; ... end
One of these conditions must always be true.
Why is this?
Erlang is a functional language, not a statement language. In an functional language every expression must have a value. if is an expression, so it must have a value.
The value of (if 2 > 1 -> 3 end) is 3 but what is the value of (if 1 > 2 -> 3 end) - answer it has no value - but it must have a value everything must have a value.
In a statement language everything is evaluated for its side effect -so this would be a valid construction.
In Erlang you will generate an exception.
So your code generates an exception - which you don't trap so you don't see it and init:stop() never gets called ...
Upvotes: 0
Reputation: 1823
Init:stop is asynchronous and it will take time to quit. An alternate way would be to wrap up the test in the call itself and use pattern matching to terminate the loop:
-module(cal).
-export([main/0]).
main() ->
StartSec = calendar:datetime_to_gregorian_seconds({{2009,1,1},{0,0,0}}),
EndSec = calendar:datetime_to_gregorian_seconds({{2009,12,31},{0,0,0}}),
run_calendar(false, StartSec, EndSec).
run_calendar(true, _StartSec, _EndSec) ->
finished;
run_calendar(false, CurSec, EndSec) ->
{Date,_Time} = calendar:gregorian_seconds_to_datetime(CurSec),
io:format("~p~n", [Date]),
NewSec = CurSec + 60*60*24,
run_calendar(NewSec =< EndSec, NewSec, EndSec).
(or something similar, hopefully you get the idea)
Upvotes: 2
Reputation: 2048
I believe that init:stop() is an asynchronous process that will attempt to shut down the runtime smoothly. According to the docs, "All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system terminates."
It probably takes a while to actually stop, because you have an actively running process. If you change "init:stop()" to "exit(stop)", it will terminate immediately:
3> cal:main().
{2009,1,1}
** exception exit: stop
in function cal:run_calendar/2
Upvotes: 4