Beginner question

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Beginner question

Pietro
Hi all,

I have recently started to implement a small academic project in Erlang
and I have bumped into a problem which seems to show to myself I haven't
grasped something important about the technology itself.

That's my code :

-module(test).
-export([start/0, interact/2]).


start() ->
    spawn (fun() -> startloop() end).
   

interact(Pid, Request) ->
    Pid ! {self(), Request},
    receive
        {Pid, Response} -> Response
    end.


startloop() ->
    TableId = ets:new(dictionary, [set]),
    loop(TableId).

loop(Table) ->
    receive
        {From, {insert, key, value}} ->
            From ! ets:insert(Table, {key, value}),
            loop(Table);
        {From, {lookup, key}} ->
            From ! ets:lookup(Table, key),
            loop(Table);
        Any ->
            Any
               
    end.


The problem happens when I try to interact with the server I start using
the command:

Pid = test:start().

Then I run :

test:interact(Pid, {insert, testkey, testvalue}).

My ershell at this point hangs and nothing happens ... what is happening
? Please feel free to redirect me to a more appropriate newsgroup if my
question is not appropriate or if there is a better one.

Thanks in advance.

Pietro.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Siraaj Khandkar-3
On Mar 14, 2016, at 18:53, Pietro <[hidden email]> wrote:

>
> Hi all,
>
> I have recently started to implement a small academic project in Erlang
> and I have bumped into a problem which seems to show to myself I haven't
> grasped something important about the technology itself.
>
> That's my code :
>
> -module(test).
> -export([start/0, interact/2]).
>
>
> start() ->
>    spawn (fun() -> startloop() end).
>
>
> interact(Pid, Request) ->
>    Pid ! {self(), Request},
>    receive
>    {Pid, Response} -> Response
>    end.
>
>
> startloop() ->
>    TableId = ets:new(dictionary, [set]),
>    loop(TableId).
>
> loop(Table) ->
>    receive
>    {From, {insert, key, value}} ->
>        From ! ets:insert(Table, {key, value}),
>        loop(Table);
>    {From, {lookup, key}} ->
>        From ! ets:lookup(Table, key),
>        loop(Table);
>    Any ->
>        Any
>        
>    end.
>
>
> The problem happens when I try to interact with the server I start using
> the command:
>
> Pid = test:start().
>
> Then I run :
>
> test:interact(Pid, {insert, testkey, testvalue}).
>
> My ershell at this point hangs and nothing happens ... what is happening
> ? Please feel free to redirect me to a more appropriate newsgroup if my
> question is not appropriate or if there is a better one.

interact/2 is waiting for a message structured differently from what loop/1 is sending.
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

dmkolesnikov
In reply to this post by Pietro
Hello,

You are using atoms instead of variables in your program. Erlang variables starts with capital letter.

The receive loop cannot match your message:
   {From, {insert, key, value}} ->
It expects one triple of atoms but you send different one.

test:interact(Pid, {insert, testkey, testvalue}).

Dmitry

Sent from my iPhone

On 15 Mar 2016, at 00:53, Pietro <[hidden email]> wrote:

Hi all,

I have recently started to implement a small academic project in Erlang
and I have bumped into a problem which seems to show to myself I haven't
grasped something important about the technology itself.

That's my code :

-module(test).
-export([start/0, interact/2]).


start() ->
   spawn (fun() -> startloop() end).


interact(Pid, Request) ->
   Pid ! {self(), Request},
   receive
   {Pid, Response} -> Response
   end.


startloop() ->
   TableId = ets:new(dictionary, [set]),
   loop(TableId).

loop(Table) ->
   receive
   {From, {insert, key, value}} ->
       From ! ets:insert(Table, {key, value}),
       loop(Table);
   {From, {lookup, key}} ->
       From ! ets:lookup(Table, key),
       loop(Table);
   Any ->
       Any
       
   end.


The problem happens when I try to interact with the server I start using
the command:

Pid = test:start().

Then I run :

test:interact(Pid, {insert, testkey, testvalue}).

My ershell at this point hangs and nothing happens ... what is happening
? Please feel free to redirect me to a more appropriate newsgroup if my
question is not appropriate or if there is a better one.

Thanks in advance.

Pietro.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Pietro
[hidden email] writes:

> Hello,
>
> You are using atoms instead of variables in your program. Erlang
> variables starts with capital letter.
>
> The receive loop cannot match your message:
>
>     {From, {insert, key, value}} ->
>
> It expects one triple of atoms but you send different one.
>
>     test:interact(Pid, {insert, testkey, testvalue}).
>
> Dmitry
>
> Sent from my iPhone
Ouch ! Thank you very much, I knew I were missing something crucial
here, would you help me in my next step ?

loop(Table) ->
    receive
        {From, {insert, Key, Value}} ->
            io:format("Here insert"),
            Return = ets:insert(Table, {Key, Value}),
            From ! Return,
            loop(Table);
        {From, {lookup, Key}} ->
            io:format("Here lookup"),
            Return = ets:lookup(Table, Key),
            From ! Return,
            loop(Table);
        {From, Any} ->
            From ! {self(), {error,Any}},
            loop(Table)
    end.

This code results in :

1> c(test).
{ok,test}
2> Pid = test:start().
<0.40.0>
3> Pid ! {self(), {insert, a, 1}}.
Here insert{<0.33.0>,{insert,a,1}}
4> Pid ! {self(), {lookup, a}}.
Here lookup{<0.33.0>,{lookup,a}}


It does not return the the stored values even though it clearly matches
the patterns, where is the rub here ?


>
> On 15 Mar 2016, at 00:53, Pietro <[hidden email]> wrote:
>
>     Hi all,
>    
>     I have recently started to implement a small academic project in
>     Erlang
>     and I have bumped into a problem which seems to show to myself I
>     haven't
>     grasped something important about the technology itself.
>    
>     That's my code :
>    
>     -module(test).
>     -export([start/0, interact/2]).
>    
>    
>     start() ->
>     spawn (fun() -> startloop() end).
>    
>    
>     interact(Pid, Request) ->
>     Pid ! {self(), Request},
>     receive
>     {Pid, Response} -> Response
>     end.
>    
>    
>     startloop() ->
>     TableId = ets:new(dictionary, [set]),
>     loop(TableId).
>    
>     loop(Table) ->
>     receive
>     {From, {insert, key, value}} ->
>     From ! ets:insert(Table, {key, value}),
>     loop(Table);
>     {From, {lookup, key}} ->
>     From ! ets:lookup(Table, key),
>     loop(Table);
>     Any ->
>     Any
>    
>     end.
>    
>    
>     The problem happens when I try to interact with the server I start
>     using
>     the command:
>    
>     Pid = test:start().
>    
>     Then I run :
>    
>     test:interact(Pid, {insert, testkey, testvalue}).
>    
>     My ershell at this point hangs and nothing happens ... what is
>     happening
>     ? Please feel free to redirect me to a more appropriate newsgroup
>     if my
>     question is not appropriate or if there is a better one.
>    
>     Thanks in advance.
>    
>     Pietro.
>    
>     _______________________________________________
>     erlang-questions mailing list
>     [hidden email]
>     http://erlang.org/mailman/listinfo/erlang-questions
>    

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Pravin Gohite
Hi,

Your receive for interact function is trying to match Pid along with Response:


interact(Pid, Request) ->
    Pid ! {self(), Request},
    receive
        {Pid, Response} -> Response
    end.

loop(Table) ->
    receive
        {From, {insert, key, value}} ->
            From ! ets:insert(Table, {Key, Value}),  %% << you are not sending something to match with Pid
            loop(Table);
        {From, {lookup, key}} ->
            From ! ets:lookup(Table, Key), %% << you are not sending something to match with Pid
            loop(Table);
        Any ->
            Any
    end.

So I think this correct send code should be: 

From ! {self(), ets:insert(Table, {Key, Value})}

and

From ! {self(), ets:lookup(Table, Key)},

Thanks,
Pravin

On Tue, Mar 15, 2016 at 1:28 PM, Pietro <[hidden email]> wrote:
[hidden email] writes:

> Hello,
>
> You are using atoms instead of variables in your program. Erlang
> variables starts with capital letter.
>
> The receive loop cannot match your message:
>
>     {From, {insert, key, value}} ->
>
> It expects one triple of atoms but you send different one.
>
>     test:interact(Pid, {insert, testkey, testvalue}).
>
> Dmitry
>
> Sent from my iPhone
Ouch ! Thank you very much, I knew I were missing something crucial
here, would you help me in my next step ?

loop(Table) ->
    receive
        {From, {insert, Key, Value}} ->
            io:format("Here insert"),
            Return = ets:insert(Table, {Key, Value}),
            From ! Return,
            loop(Table);
        {From, {lookup, Key}} ->
            io:format("Here lookup"),
            Return = ets:lookup(Table, Key),
            From ! Return,
            loop(Table);
        {From, Any} ->
            From ! {self(), {error,Any}},
            loop(Table)
    end.

This code results in :

1> c(test).
{ok,test}
2> Pid = test:start().
<0.40.0>
3> Pid ! {self(), {insert, a, 1}}.
Here insert{<0.33.0>,{insert,a,1}}
4> Pid ! {self(), {lookup, a}}.
Here lookup{<0.33.0>,{lookup,a}}


It does not return the the stored values even though it clearly matches
the patterns, where is the rub here ?


>
> On 15 Mar 2016, at 00:53, Pietro <[hidden email]> wrote:
>
>     Hi all,
>
>     I have recently started to implement a small academic project in
>     Erlang
>     and I have bumped into a problem which seems to show to myself I
>     haven't
>     grasped something important about the technology itself.
>
>     That's my code :
>
>     -module(test).
>     -export([start/0, interact/2]).
>
>
>     start() ->
>     spawn (fun() -> startloop() end).
>
>
>     interact(Pid, Request) ->
>     Pid ! {self(), Request},
>     receive
>     {Pid, Response} -> Response
>     end.
>
>
>     startloop() ->
>     TableId = ets:new(dictionary, [set]),
>     loop(TableId).
>
>     loop(Table) ->
>     receive
>     {From, {insert, key, value}} ->
>     From ! ets:insert(Table, {key, value}),
>     loop(Table);
>     {From, {lookup, key}} ->
>     From ! ets:lookup(Table, key),
>     loop(Table);
>     Any ->
>     Any
>
>     end.
>
>
>     The problem happens when I try to interact with the server I start
>     using
>     the command:
>
>     Pid = test:start().
>
>     Then I run :
>
>     test:interact(Pid, {insert, testkey, testvalue}).
>
>     My ershell at this point hangs and nothing happens ... what is
>     happening
>     ? Please feel free to redirect me to a more appropriate newsgroup
>     if my
>     question is not appropriate or if there is a better one.
>
>     Thanks in advance.
>
>     Pietro.
>
>     _______________________________________________
>     erlang-questions mailing list
>     [hidden email]
>     http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Richard A. O'Keefe-2
In reply to this post by Pietro


On 15/03/16 11:53 am, Pietro wrote:

> -module(test).
> -export([start/0, interact/2]).
>
>
> start() ->
>      spawn (fun() -> startloop() end).
>      
>
> interact(Pid, Request) ->
>      Pid ! {self(), Request},
>      receive
> {Pid, Response} -> Response
>      end.

Here you expect the process you are interacting with to
return {Pid,Response} pairs, where the first element of
the tuple is that process's own Pid.

>
>
> startloop() ->
>      TableId = ets:new(dictionary, [set]),
>      loop(TableId).
>
> loop(Table) ->
>      receive
> {From, {insert, key, value}} ->
>    From ! ets:insert(Table, {key, value}),

Here you do NOT send back what's expected, which is
{self(), ets:insert(Table, {key,value})}

I suspect that this clause should have been
         {From, {insert,Key,Value}} ->
             From ! {self(), ets:insert(Table, {Key,Value})},
             loop(Table)
>    loop(Table);
> {From, {lookup, key}} ->
>    From ! ets:lookup(Table, key),

Here you do NOT send back what's expected, which is
{self(), ets:lookup(Table, key)}

I suspect that this clause should have been
         {From, {lookup,Key}} ->
             From ! {self(), ets:lookup(Table, Key)},
             loop(Table)

>    loop(Table);
> Any ->
>    Any
>
>      end.
>
>
> The problem happens when I try to interact with the server I start using
> the command:
>
> Pid = test:start().
>
> Then I run :
>
> test:interact(Pid, {insert, testkey, testvalue}).

And here my suspicion is confirmed.

Problem 1: Your responses did not conform to your intended protocol.

Problem 2: You had constants (key) where you meant to have variables (Key),

Your question is fine.  These are slips anyone could have made.
One thing would have helped to avoid them both, and that is
describing the protocol of the new process in a comment.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Joe Armstrong-2
In reply to this post by Pietro
Here's a tip

I *always* start writing message processing lops like this:

    loop(State) ->
         receive
               Any ->
                    io:format("***unexpected ~p~n",[Any]),
                    loop(State)
         end.

Then I compile and run this with my problem.

Of course, I'll get a printout
since the program is incomplete. I then let these printouts guide the
order in which I
write the program - I add a pattern for the first unmatched message,
recompile and run again.

When there are no more messages saying things are unmatched I remove the
last pattern (or just leave it in).

In a published program the last part is most often removed, it was necessary
during development but can be removed once you have a correct program.

What you see in published examples is the final result - during development
it's helpful to add print statements so you can see what's happeing and remove
them later.

I think if you'd done this you'd have immediately seen what was wrong.

Cheers

/Joe




On Tue, Mar 15, 2016 at 1:28 PM, Pietro <[hidden email]> wrote:

> [hidden email] writes:
>
>> Hello,
>>
>> You are using atoms instead of variables in your program. Erlang
>> variables starts with capital letter.
>>
>> The receive loop cannot match your message:
>>
>>     {From, {insert, key, value}} ->
>>
>> It expects one triple of atoms but you send different one.
>>
>>     test:interact(Pid, {insert, testkey, testvalue}).
>>
>> Dmitry
>>
>> Sent from my iPhone
> Ouch ! Thank you very much, I knew I were missing something crucial
> here, would you help me in my next step ?
>
> loop(Table) ->
>     receive
>         {From, {insert, Key, Value}} ->
>             io:format("Here insert"),
>             Return = ets:insert(Table, {Key, Value}),
>             From ! Return,
>             loop(Table);
>         {From, {lookup, Key}} ->
>             io:format("Here lookup"),
>             Return = ets:lookup(Table, Key),
>             From ! Return,
>             loop(Table);
>         {From, Any} ->
>             From ! {self(), {error,Any}},
>             loop(Table)
>     end.
>
> This code results in :
>
> 1> c(test).
> {ok,test}
> 2> Pid = test:start().
> <0.40.0>
> 3> Pid ! {self(), {insert, a, 1}}.
> Here insert{<0.33.0>,{insert,a,1}}
> 4> Pid ! {self(), {lookup, a}}.
> Here lookup{<0.33.0>,{lookup,a}}
>
>
> It does not return the the stored values even though it clearly matches
> the patterns, where is the rub here ?
>
>
>>
>> On 15 Mar 2016, at 00:53, Pietro <[hidden email]> wrote:
>>
>>     Hi all,
>>
>>     I have recently started to implement a small academic project in
>>     Erlang
>>     and I have bumped into a problem which seems to show to myself I
>>     haven't
>>     grasped something important about the technology itself.
>>
>>     That's my code :
>>
>>     -module(test).
>>     -export([start/0, interact/2]).
>>
>>
>>     start() ->
>>     spawn (fun() -> startloop() end).
>>
>>
>>     interact(Pid, Request) ->
>>     Pid ! {self(), Request},
>>     receive
>>     {Pid, Response} -> Response
>>     end.
>>
>>
>>     startloop() ->
>>     TableId = ets:new(dictionary, [set]),
>>     loop(TableId).
>>
>>     loop(Table) ->
>>     receive
>>     {From, {insert, key, value}} ->
>>     From ! ets:insert(Table, {key, value}),
>>     loop(Table);
>>     {From, {lookup, key}} ->
>>     From ! ets:lookup(Table, key),
>>     loop(Table);
>>     Any ->
>>     Any
>>
>>     end.
>>
>>
>>     The problem happens when I try to interact with the server I start
>>     using
>>     the command:
>>
>>     Pid = test:start().
>>
>>     Then I run :
>>
>>     test:interact(Pid, {insert, testkey, testvalue}).
>>
>>     My ershell at this point hangs and nothing happens ... what is
>>     happening
>>     ? Please feel free to redirect me to a more appropriate newsgroup
>>     if my
>>     question is not appropriate or if there is a better one.
>>
>>     Thanks in advance.
>>
>>     Pietro.
>>
>>     _______________________________________________
>>     erlang-questions mailing list
>>     [hidden email]
>>     http://erlang.org/mailman/listinfo/erlang-questions
>>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Vance Shipley
In reply to this post by Pietro
On Tue, Mar 15, 2016 at 4:23 AM, Pietro <[hidden email]> wrote:

>
> loop(Table) ->
>     receive
>         {From, {insert, key, value}} ->
>             From ! ets:insert(Table, {key, value}),
>             loop(Table);
>         {From, {lookup, key}} ->
>             From ! ets:lookup(Table, key),
>             loop(Table);
>         Any ->
>             Any
>
>     end.

I recall when beginning with Erlang, many years ago, my first struggle
was with the concept of functional programming.  Where are my global
variables?  Yours is not an example of functional style so I am
compelled to rewrite your loop/1 function in a couple ways to
demonstrate a side effect free functional implementation.

First the simplest case where we have a server manage one value:

     start() ->
         spawn (fun() -> loop(undefined) end).

     loop(Value) ->
         receive
             {From, {set, NewValue}} ->
                 From ! {self(), {ok, NewValue}},
                 loop(NewValue);
             {From, get} ->
                 From ! {self(), {ok, Value}},
                 loop(Value)
         end.

     1> Pid = a:start().
     <0.35.0>
     2> a:interact(Pid, get).
     {ok,undefined}
     3> a:interact(Pid, {set, 42}).
     {ok,42}
     4> a:interact(Pid, get).
     {ok,42}

To handle more values use more arguments (e.g. loop/3):

     start() ->
         spawn (fun() -> loop(undefined, undefined, undefined) end).

     loop(A, B, C) ->
         receive
             {From, {set, a, Value}} ->
                 From ! {self(), {ok, Value}},
                 loop(Value, B, C);
            {From, {set, b, Value}} ->
                 From ! {self(), {ok, Value}},
                 loop(A, Value, C);
            {From, {set, c, Value}} ->
                 From ! {self(), {ok, Value}},
                 loop(A, Value, C);
             {From, {get, a}} ->
                 From ! {self(), {ok, A}},
                 loop(A, B, C);
             {From, {get, b}} ->
                 From ! {self(), {ok, B}},
                 loop(A, B, C);
             {From, {get, c}} ->
                 From ! {self(), {ok, C}},
                 loop(A, B, C);
         end.

To handle many values replace the argument to loop/1 with a data
structure chosen to match our use case:

     start() ->
         spawn (fun() -> loop(dict:new()) end).

     loop(Dict) ->
         receive
             {From, {set, Key, Value}} ->
                 NewDict = dict:store(Key, Value, Dict),
                 From ! {self(), {ok, Value}},
                 loop(NewDict);
             {From, {get, Key}} ->
                 From ! dict:fetch(Key, Dict),
                 loop(Dict)
         end.

... or:

     start() ->
         spawn (fun() -> loop(gb_trees:empty()) end).

     loop(Tree) ->
         receive
             {From, {set, Key, Value}} ->
                 NewTree = gb_trees:enter(Key, Value, Tree),
                 From ! {self(), {ok, Value}},
                 loop(NewTree);
             {From, {get, Key}} ->
                 From ! gb_trees:get(Key, Tree),
                 loop(Tree)
         end.


There's nothing wrong with using the erlang term storage (ets) module.
I just think it's important to understand and embrace the functional
style first or you risk writing terrible imperative code by using ets,
or worse the process dictionary, to accomplish global variables.

--
     -Vance
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Beginner question

Onorio Catenacci
In reply to this post by Pietro
Message: 6
Date: Tue, 15 Mar 2016 21:22:30 -0700
From: Joe Armstrong <[hidden email]>
To: Pietro <[hidden email]>
Cc: Erlang <[hidden email]>
Subject: Re: [erlang-questions] Beginner question
Message-ID:
        <[hidden email]>
Content-Type: text/plain; charset=UTF-8

Here's a tip

I *always* start writing message processing lops like this:

    loop(State) ->
         receive
               Any ->
                    io:format("***unexpected ~p~n",[Any]),
                    loop(State)
         end.

Then I compile and run this with my problem.
 

This is a great idea Joe!  I plan to steal this one!  :)
 
-- 

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions