Archive

Archive for the ‘Basic’ Category

Record introspection at compile time

October 8th, 2009

For AMF implementation, I have to define the mapping between Actionscript classes with something equivalent in Erlang. First thing came into my mind is record. However, I immediately encountered some of the difficulties when using records in Erlang

  1. Read: can’t use reflection easily after parsing AMF, I received the object with properties/values and I need to map to the corresponding record
  2. Write: Need to introspect the record and write its properties into binaries

I found this post from trapexit. However, I need specifically more than that.

Normally records are defined in a header file “.hrl”. And the idea is to generate utility codes (getter, setter, record meta data ….) at compile time. The heart of it is epp:parse_file/3 function. The generator (or the helper) reads header files, parses all records and create a compilable .erl file which contains all functions you need to do all magic with records:

  1. set(Obj, PropertyName, Value) -> {ok, NewObj, {PropertyName, Value}}
  2. get(Obj, PropertyName) -> {ok, Value}
  3. fields(record_name) -> Fields = [string()]
  4. fields_atom(record_name) -> Fields = [term()]
  5. type(Obj) -> record_name

messages.hrl – the source

record_helper.erl – the generator

record_utils.erl – the generated source

Below is the demonstration of how to generate and use the record utils

1> c(record_helper.erl).
{ok,record_helper}
2> record_helper:make(["messages.hrl"], ".").
ok
3> ls().
messages.hrl            record_helper.beam
record_helper.erl      record_utils.erl
ok
6> c(record_utils).
{ok,record_utils}
7> rr("messages.hrl").
[abstract_message,async_message]
8> Obj = #async_message{}.
#async_message{
    parent =
        #abstract_message{
            clientId = undefined,destination = undefined,
            messageId = undefined,timestamp = undefined,
            timeToLive = undefined,headers = undefined,body = undefined},
    correlationId = undefined,correlationIdBytes = undefined}
9> record_utils:set(Obj, correlationId, "ADF-123-DDF-543").
{ok,#async_message{
        parent =
            #abstract_message{
                clientId = undefined,destination = undefined,
                messageId = undefined,timestamp = undefined,
                timeToLive = undefined,headers = undefined,body = undefined},
        correlationId = "ADF-123-DDF-543",
        correlationIdBytes = undefined},
    {correlationId,"ADF-123-DDF-543"}}
10> {ok,NewObj, _} = record_utils:set(Obj, correlationId, "ADF-123-DDF-543").
{ok,#async_message{
        parent =
            #abstract_message{
                clientId = undefined,destination = undefined,
                messageId = undefined,timestamp = undefined,
                timeToLive = undefined,headers = undefined,body = undefined},
        correlationId = "ADF-123-DDF-543",
        correlationIdBytes = undefined},
    {correlationId,"ADF-123-DDF-543"}}
11> record_utils:get(NewObj, correlationId).
{ok,"ADF-123-DDF-543"}
12> record_utils:type(NewObj).
async_message

record_helper.erl is not so clean as there’re all string concatenations … further improvements can be:

  1. Using template language like ErlyDTL or ErlTL
  2. Clean up code to have more friendly arguments
  3. You add ….

AMF, Basic, Record , ,

Date time manipulation howtos

September 6th, 2009

Erlang offers calendar module which provides computation of date, time and number of date time conversion functions. For more details, please refer to documentation for this module
Here are some examples:

Data types


Date = {Year, Month, Day}
Time = {Hour, Minute, Second}

where

Year = an integer and cannot be abbreviated. E.g.: 93 denotes year 93, not 1993
Month = 1..12
Day = 1..31
Hour = 0..23
Minute = 0..59
Second = 0..59

How to obtain local date time

{Date, Time} = calendar:local_time()

1> Current = calendar:local_time().
{{2009,9,7},{12,32,22}}
2> {{Current_Year, Current_Month, Current_Day}, _ } = Current.
{{2009,9,7},{12,32,22}}
3> Current_Year.
2009
4> Current_Month.
9
5> Current_Day.
7
6> { _, {Current_Hour, Current_Min, Current_Second}} = Current. 
{{2009,9,7},{12,32,22}}
7> Current_Hour.
12
8> Current_Min.
32
9> Current_Second.
22

How to obtain current UTC time

{Date, Time} = calendar:universal_time()

How to convert time to seconds since midnight and via versa

Seconds = calendar:time_to_seconds(Time)
Time = calendar:seconds_to_time(Seconds)

10> Time1 = {10, 6, 30}.
{10,6,30}
11> Seconds = calendar:time_to_seconds(Time1).
36390
12> calendar:seconds_to_time(Seconds).
{10,6,30}

How to verify if a year is leap year

Bool = calendar:is_leap_year(Year)

14> calendar:is_leap_year(2008).
true
15> calendar:is_leap_year(2009).
false

How to check if a date is valid

Bool = calendar:valid_date(Date)
Bool = calendar:valid_date(Year, Month, Day)

16> calendar:valid_date({2009,12,12}).
true
17> calendar:valid_date({2009,13,12}).
false
18> calendar:valid_date(2009, 12, 31).
true
19> calendar:valid_date(2008, 2, 29).
true

How to find out day of the week

DayNumber = calendar:day_of_the_week(Date)
DayNumber = calendar:day_of_the_week(Year, Month, Day)
1 = Monday, 2 = Tuesday, ….and 7 = Sunday

20> calendar:day_of_the_week({2009,9,7}).
1
21> calendar:day_of_the_week(2009, 9, 9).
3

How to find out last day of a month

LastDay = calendar:last_day_of_the_month(Year, Month)

22> calendar:last_day_of_the_month(2008, 2).   
29
23> calendar:last_day_of_the_month(2009, 8).
31

How to calculate date time difference

{Days, Time} = calendar:time_difference(DT1, DT2)
DT1 = {Date1, Time1}
DT2 = {Date2, Time2}
Logically equivalent to DT2 – DT1

7> Date1={{2009,8,30}, {23,0,0}}.
{{2009,8,30},{23,0,0}}
8> Date2={{2009,9,30}, {23,0,0}}.
{{2009,9,30},{23,0,0}}
9> calendar:time_difference(Date2, Date1).
{-31,{0,0,0}}
10> calendar:time_difference(Date1, Date2).
{31,{0,0,0}}
11> Date3={{2008,8,30},{23,0,0}}.
{{2008,8,30},{23,0,0}}
12> calendar:time_difference(Date1, Date3).
{-365,{0,0,0}}

Basic, DateTime , , , ,

Recursion in Erlang

August 28th, 2009

Quick Sort

I took this example from Joe Armstrong’s book: Programming Erlang to show the beauty Erlang in recursion. Classic example of quick sort implementation

Can’t believe it, 6 simple and very elegant!!! I remembered roughly 10 years ago, how hard to write quick sort implementation in Pascal.

Tail Recursion

The quick sort implementation above is not tail recursive way. As the function call doesn’t return the whole results at once (look at the list concatenation). Here are few examples of tail recursion in Erlang

Basic , , , , ,

How to spawn a process

May 15th, 2009

Erlang is all about processes and their communications. To create a process, we use BIF spawn/3 which returns the new process PID

-module(spawn_process).
-export([do_spawn/0, call/2]).

call(Arg1, Arg2) ->
    io:format("~p ~p~n", [Arg1, Arg2]).

do_spawn() ->
    %% Equivalent to SpawnProcess:call("hello", "process"),
    Pid = spawn(?MODULE, call, ["hello", "process"]),
    Pid.

Output of the call spawn_process:do_spawn/0 is the Pid of the newly created process. ?MODULE is the macro refers to the current module

1> spawn_process:do_spawn().
"hello" "process"
<0.33.0>
2>

Basic , , ,

How to create and manipulate records

March 9th, 2009

As I remember the first time I was tought about Object-Oriented paradigm, my teacher told me “everything around you is an object” … Damn, since then I couldn’t get rid of that even when programming with Erlang.

People say Records concept in Erlang is very similar to struct in C. That’s true, but for me, it looks rather like an Object

Normally, records are defined in a separate file with extension .hrl and included in the main module file.

person.hrl

%% person.hrl
-record(person, {name, age}).

Here I define a record, named person, which has 2 attributes name and age. I’ll use erl console to do some manipulation with record person

1> rr("person.hrl").
[person]
2> X = #person{name="Jonny", age="18"}.
#person{name = "Jonny",age = "18"}
3> X#person.name.
"Jonny"
4> X#person.age.
"18"
5> #person{name=Name} = X.
#person{name = "Jonny",age = "18"}
6> Name.
"Jonny"

1> I read record person defined in person.hrl
2> I created a new “object” of type person and assigned to variable X
3> I printed value of the attribute name from “object” X
4> I printed value of the attribute age from “object” X
5> I used pattern matching to extract value of the attribute name out of “object” X and assigned to variable Name
6> I printed value of variable Name

Basic ,

String concatenation

February 25th, 2009

As we all know, Erlang treats String as the array of integers, hence operations on list are applicable on String. 

String concatenation can be done in different ways in Erlang

1> X="I love ".
"I love "
2> Y="Erlang".
"Erlang"
3> string:concat(X, Y).
"I love Erlang"
4> string:join([X, Y], "").
"I love Erlang"
5> X ++ Y.
"I love Erlang"
6> lists:append(X, Y).
"I love Erlang"
7> lists:concat([X, Y]).
"I love Erlang"

Basic ,