what is wrong with this code setting a nested record? FOLLOW UP

Håkan Stenholm <>
Thu Jul 21 23:23:39 CEST 2005


MEENA SELVAM wrote:

>I have a function display_login2(A) where A is
>follows:
>(The  arg and header record definitions are  given at
>the end.)
>
>
>
>A= {arg,#Port<16338.534>,
>
>>                       {headers,undefined,
>>                                "image/gif,
>>image/x-xbitmap, image/jpeg, image/
>>pjpeg, */*",
>>                                "www.msn.com",
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                "Mozilla/4.0
>>(compatible; MSIE 6.0; Windows NT
>>5.1)",
>>                                undefined,
>>                                [],
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                undefined,
>>                                [{http_header,
>>                                     0,
>>                                    
>>"X-Yaws-Had-Clicert",
>>                                     undefined,
>>                                     "false"},
>>                                 {http_header,
>>                                     49,
>>                                    
>>'X-Forwarded-For',
>>                                     undefined,
>>                                     "11.10.1.107"},
>>                                 {http_header,
>>                                     7,
>>                                     'Via',
>>                                     undefined,
>>                                     "1.1
>>
>www.msn.com
>
>>(Alteon iSD-SSL/5.5)"},
>>                                 {http_header,
>>                                     0,
>>                                    
>>"X-Forwarded-By",
>>                                     undefined,
>>                                     "47.80.18.95"},
>>                                 {http_header,
>>                                     10,
>>                                    
>>'Accept-Encoding',
>>                                     undefined,
>>                                     "gzip,
>>deflate"},
>>                                 {http_header,
>>                                     11,
>>                                    
>>'Accept-Language',
>>                                     undefined,
>>                                     "en-us"}]},
>>                      
>>{http_request,'GET',{abs_path,"/"},{1,1}},
>>                       undefined,
>>                       "/",
>>                       [],
>>                       undefined,
>>
>                         ....
>
>>                       .... and much more
>>
>>
>-record(arg, {
>          clisock,        %% the socket leading to the
>peer client
>          headers,        %% headers
>          req,            %% request
>          .....
>          .....
>           .....
>         }).
>
>-record(headers, {
>          connection,
>          accept,
>          host,       %% host header
>          if_modified_since,
>          ...
>          ...
>          ...
>          other = []   %% misc other headers
>         }).
>
>I need to replace the host header (which is
>www.msn.com) by the redirected ip 47.80.18.95(which is
>part of the Other Header)
>
>Is this the only way to do this:
>Create a new record of type headers, with www.msn.com
>replaced by the 47.80.18.95
>
Yes

>
> NewHeader =
> (A#arg.headers)#headers{host="47.80.18.95"},
>
>[ typically i will make host as extracted from 3rd
>element of other header]
>
>Create  9 other new records of the 9 different types
>of   the sub records of arg record. (Totally I have 10
>including headers)
>
>Newclisock = A#arg.clisock
>Newreq = A#arg.req
>...
>..
>
>
>Now create a new record of type Arg , by using the
>newly created 10 records like this:
>ANew = #arg{clisock = NewClisock,
>            headers = NewHeader,
>            req = NewReq
>            ...
>            ...},
>
There is no need to extract all the field values (sub records), it is 
sufficient to only set the fields that need to be updated e.g.:

%% possibly get some sub records from A
...
%% do some code that creates new values for some fields (sub records)
NewReq = ...
NewVal = ...
%% update record (or rather creat a new one based on the old one)
%% with only the affected fields changed
ANew = A#arg{clisock = NewVal, req = NewReq},
...

>
>and use Anew instead of A from now on.
>
Use ANew when the updated version is needed and A when the old version 
is needed - both are available in the current function clause scoop, 
from the point that they are declared until the end of the clause.
No variable in a function clause can change its content after it has 
been given a value in that scoop - updating values in each iteration 
step is achived by passing updated values as arguments to the next 
recursive call, so variables in the current scoop never change.

%% a simple list length calculation function, a accumulator is used to
%% make the function tail recursive (and to show how data is passed between
%% each iteration / recursive call)
length(List) ->
    length(List, 0).

length([], Length) -> Length;   %% base case - end of list found,
                                %% return the length value that has been 
accumulated
length([_|R], Length) -> length(R,Lenght+1). %% pass new length and list 
remainder
                                                %% to next call of length/2



 

>
>Will this work? Also, is the syntax right while I am
>creating ANew?
>
>
>
>--- Håkan Stenholm <>
>wrote:
>
>
>>MEENA SELVAM wrote:
>>
>>
>>>Hi,
>>>
>>>the parameter A is of record type arg, which
>>>
>>contains
>>
>>>a subrecord of type, headers and which has a field
>>>host:
>>>
>>>The host field initially contains www.msn.com, and
>>>
>>I
>>
>>>am trying to overwrite with 47.80.18.95, but the
>>>following code doesnt work.. it still has
>>>
>>www.msn.com
>>
>>>itself.
>>>
>>>display_login2(A, ReplyMsgs, URL, IP, FromLogout)
>>>
>>->
>>
>>>   (A#arg.headers)#headers{host="47.80.18.95"},
>>>
>>>am i doing anything wrong here?
>>> 
>>>
>>>
>>It should work (see my test code below), but may
>>have forgotten to do:
>>
>>          NewHeader =
>>(A#arg.headers)#headers{host="47.80.18.95"},
>>          ...
>>          xxx(NewHeader, ...)  %% use the new
>>(updated) Header rather 
>>than the old one in A
>>          ...
>>
>>It would be helpful to see a bit more of your code,
>>I get the feeling 
>>that your trying to do a destructive update on a
>>record in a single 
>>assignment language, this won't work - data elements
>>in Erlang can only 
>>be created but never modified[1] (with the exception
>>for 
>>ets/mnesia/process dictionaries which can
>>conceptually be viewed as 
>>processes storing data in some regular Erlang data
>>type like a binary 
>>tree - which is updated by creating new nodes and
>>leaves to replace the 
>>old ones - rather than overwriting old ones).
>>
>>[1] : deletion is done by the GC.
>>
>>================== test.erl =====================
>>
>>-module(test).
>>
>>-export([test/0]).
>>
>>-record(foo, {
>>         bar
>>         }).
>>
>>-record(bar, {
>>          a,
>>          b
>>         }).
>>
>>test() ->
>>    Bar = #bar{a = 1, b = 2},
>>    Foo = #foo{bar = Bar},
>>
>>    io:format("Foo = ~p~n", [Foo]),
>>
>>    %% create new bar record
>>    %% access foo record and create new bar record
>>based on foo.bar
>>    Bar2 = (Foo#foo.bar)#bar{b = new_val},
>>    io:format("Bar2 = ~p~n", [Bar2]),
>>
>>    %% create new foo record
>>    %% create new foo record containing the new Bar2
>>bar record
>>    Foo2 = Foo#foo{bar = Bar2},
>>    io:format("Foo2 = ~p~n", [Foo2]),
>>
>>    ok.
>>
>>================== test.erl =====================
>>
>>2> c(test).
>>{ok,test}
>>3> test:test().
>>Foo = {foo,{bar,1,2}}
>>Bar2 = {bar,1,new_val}
>>Foo2 = {foo,{bar,1,new_val}}
>>ok
>>
>>
>>>meena
>>>
>>>
>>>__________________________________________________
>>>Do You Yahoo!?
>>>Tired of spam?  Yahoo! Mail has the best spam
>>>
>>protection around 
>>
>>>http://mail.yahoo.com 
>>>
>>> 
>>>
>>>
>>
>
>
>
>		
>__________________________________ 
>Do you Yahoo!? 
>Yahoo! Mail - Find what you need with new enhanced search. 
>http://info.mail.yahoo.com/mail_250
>
>




More information about the erlang-questions mailing list