views:

135

answers:

3

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#
+4  A: 

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
bjnortier
+2  A: 

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)

Alan Moore
Even though you had a fit-for-purpose disclaimer: "end" is a keyword and must be single-quoted if you want it as an atom.
Christian
Yes, I had null in my example and thought end would be better in the output. Do'h I've changed it now
Alan Moore
(Thanks for correcting me)
Alan Moore
A: 

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 ...

ja