list convert to pid function list_to_pid/1 restriction - erlang

When test open source project 'gproc' function,
I found list_to_pid is ok for local pid, and not ok for remote pid. My erlang runtime is R15B.
(dist_test_n2#yus-iMac.local)29> D = list_to_pid("<0.239.0>").
<0.239.0>
(dist_test_n2#yus-iMac.local)30> D == self(). %% equal here
true
(dist_test_n2#yus-iMac.local)31> f(E).
ok
(dist_test_n2#yus-iMac.local)32> E = gproc:where(Name).
<8969.239.0>
(dist_test_n2#yus-iMac.local)33> F = list_to_pid("<8969.239.0>").
<8969.239.0>
(dist_test_n2#yus-iMac.local)34> F == E. %% not equal here
false
From user guide about this function, there is no such restriction. Is it bug?

as you can confirm here it's not possible to use list_to_pid/1 with external pids.
If you check on google I think you can also find the original thread started by Ulf Wiger.
Hope this helps!

Related

How to close a programm in Erlang with WxWidgets?

I have a problem to close a program in Erlang. I use wxWidgets.
-module(g).
-compile(export_all).
-define(height, 500).
-define(width, 500).
-include_lib("wx/include/wx.hrl").
-define(EXIT,?wxID_EXIT).
init() ->
start().
start() ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, -1, "Line", [{size, {?height, ?width}}]),
setup(Frame),
wxFrame:show(Frame),
loop(Frame).
setup(Frame) ->
menuBar(Frame),
wxFrame:connect(Frame, close_window).
menuBar(Frame) ->
MenuBar = wxMenuBar:new(),
File = wxMenu:new(),
wxMenuBar:append(MenuBar,File,"&Fichier"),
wxFrame:setMenuBar(Frame,MenuBar),
Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxMenu:append (File, Quit).
loop(Frame) ->
receive
#wx{event=#wxCommand{type=close_window}} ->
io:format("quit icon"),
wxWindow:close(Frame,[]);
#wx{id=?EXIT, event=#wxCommand{type=command_menu_selected}} ->
io:format("quit file menu"),
wxWindow:close(Frame,[])
end.
But the program doesn't close; neither the quit icon or Quit from the menu do anything.
You're almost there, but there's a few mistakes.
First, there's never any event being generated for your quit selection on your mention, you need to use connect again, like this:
Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxFrame:connect(Frame, command_menu_selected),
Now you have an event for each of the quit methods, but neither of them is working still.
The event for your quit icon isn't matching because you have the wrong event type in your pattern match, and the event for the menu quit selection isn't matching because you're looking for an ID of ?EXIT, which is defined as ?wxID_EDIT, which is defined as.. well clearly not 400, the ID you used when you created your quit menu item. So your receive clause needs to be changed to something like this:
receive
#wx{event=#wxClose{type=close_window}} ->
io:format("quit icon"),
wxFrame:destroy(Frame);
#wx{id=400, event=#wxCommand{type=command_menu_selected}} ->
io:format("quit file menu"),
wxFrame:destroy(Frame)
end.
In addition to Michael's answer regarding using connect/3 to listen for menu commands, nearly any frame will require a few standard event connections to behave the way you expect them to on closing in addition to whatever specific things you have going on. Note that this is connecting to the close_window event and using the option {skip, true}. This is so the signal doesn't stop propagating before it hits the part of Wx that will handle it the way you expect (one click to close) instead of requiring two clicks to close the frame on some platforms.
The basic skeleton often looks like this:
init(Args) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, ""),
% Generate whatever state the process represents
State = some_state_initializer(Args),
% Go through the steps to create your widget layout, etc.
WidgetReferences = make_ui(Frame),
% The standardish connects nearly any frame will need.
ok = wxFrame:connect(Frame, close_window, [{skip, true}]),
ok = wxFrame:connect(Frame, command_button_clicked),
ok = wxFrame:connect(Frame, command_menu_selected),
% Add more connects here depending on what you need.
% Adjust the frame size and location, if necessary
Pos = initial_position(Args),
Size = initial_size(Args),
ok = wxFrame:move(Frame, Pos),
ok = wxFrame:setSize(Frame, Size),
wxFrame:show(Frame),
% Optional step to add this frame to a UI state manager if you're
% writing a multi-window application.
ok = gui_manager:add_live(self()),
% Required return for wx_object behavior
{Frame, State}.
Digressing a bit from the original, but strongly related...
Many wxWidgets application have something very similar to this, customized as necessary not by writing all that out again, but by defining your own callback module and passing it in as an argument:
init({Mod, Args}) ->
% ...
PartialState = blank_state([{mod, Mod}, {frame, Frame}, {wx, Wx}]),
State = Mod:finalize(PartialState, Args),
Where blank_state/1 accepts a proplist and returns whatever the actual data structure will be later (usually a record at this level, that looks something like #s{mod, frame, wx, widgets, data}), and Mod:finalize/2 takes the incomplete state and the initial args and returns a completed GUI frame plus whatever program state it is supposed to manage -- in particular the widgets data structure that carries references to any GUI elements you will need to listen for, match on, or manipulate later.
Later on you have some very basic generic handlers all frames might need to deal with, and pass any other messages through to the specific Mod:
handle_call(Message, From, State = #s{mod = Mod}) ->
Mod:handle_call(Message, From, State).
handle_cast(blit, State) ->
{ok, NewState} = do_blit(State),
{noreply, NewState};
handle_cast(show, State) ->
ok = do_show(State),
{noreply, State};
handle_cast(Message, State = #s{mod = Mod}) ->
Mod:handle_cast(Message, State).
In this case do_blit/1 winds up calling Mod:blit/1 in the callback module which rebuilds and refreshes the GUI, rebuilding it from zero by calling a function that does that within wx:batch/1 to make it appear instant to the user:
blit(State) ->
wx:batch(fun() -> freshen_ui(State) end).
If you have a lot of elements to change in the GUI at once, blitting is far smoother and faster from the user's perspective than incrementally shuffling things around or hiding/showing elements as you go -- and is much more certain to feel the same across platforms and various computer speeds and userland loads (some Wx backends give a lot of flicker or intermediate display weirdness otherwise).
The do_show/1 function usually looks something like
do_show(#s{frame = Frame}) ->
ok = wxFrame:raise(Frame),
wxFrame:requestUserAttention(Frame).
(I have been meaning to write a basic "here is one way to structure a multi-window wxErlang application" tutorial/example but just haven't gotten around to it, so a lot of details are missing here but you'll stumble on them on your own after writing a couple of programs.)

How can I get when the button is clicked?

I use wxwidget with erlang.
init() ->
Wx=wx:new(),
F=wxFrame:new(Wx, -1, "Hello, World!"),
Panel = wxPanel:new(F),
wxButton:new(Panel, 12, [{label,"Default"}]),
wxFrame:show(F).
If I click on the button nothing is doing, I want to do something, execute a function for example. How can I do that?
Thanks
Best regards
Here's an example in the shell.
First, create a window with a button, which you have already:
1> Wx = wx:new().
{wx_ref,0,wx,[]}
2> Frame = wxFrame:new(wx:null(), -1, "Hello, World!").
{wx_ref,35,wxFrame,[]}
3>
3> Panel = wxPanel:new(Frame).
{wx_ref,36,wxPanel,[]}
4>
4> Button = wxButton:new(Panel, 12, [{label,"Default"}]).
{wx_ref,37,wxButton,[]}
Now you can register a callback. In this case I am just printing out the data passed to the callback:
5> wxButton:connect(Button, command_button_clicked, [{callback,
5> fun(Evt, Obj) ->
5> io:format("click~n event = ~p~n obj = ~p~n", [Evt, Obj])
5> end
5> }]).
ok
Display the window:
6> wxFrame:show(Frame).
true
7>
Now, when you click the button, you should see:
click
event = {wx,12,
{wx_ref,37,wxButton,[]},
[],
{wxCommand,command_button_clicked,[],0,0}}
obj = {wx_ref,39,wxCommandEvent,[]}
7>
Edit (notes concerning OTP):
When you implement a more fully OTP style application with wx you may want to do something slightly different, because you don't want that fun hanging around. Instead you can have a message sent to you when the button is clicked. If you omit the 'callback' option to connect then the event will be delivered to the process that calls connect instead. So you could have done:
5> wxButton:connect(Button, command_button_clicked, []).
ok
If you do that, and click the button, your (shell in this case) process will receive a message:
7> receive Msg -> Msg after 0 -> timeout end.
{wx,12,
{wx_ref,37,wxButton,[]},
[],
{wxCommand,command_button_clicked,[],0,0}}
8>
The attached link explains how to handle events in general with wxWidgets but it also discusses wxbutton and its click event. There is some sample code there as well. Hope this helps.
wxWidget Event Handling

Logging in using libCurl

I was trying to log in using LibCurl. Actually I am using LuaCurl the binding of libCurl in Lua. I am referring to this web page: http://www.hackthissite.org/articles/read/1078
I tried this:
> require("libcurl")
> c=curl.new()
> c:setopt(curl.OPT_USERAGENT,"Mozilla/4.0")
> c:setopt(curl.OPT_AUTOREFERER,true)
> c:setopt(curl.OPT_FOLLOWLOCATION,true)
> c:setopt(curl.OPT_COOKIEFILE,"")
> c:setopt(curl.OPT_URL,"https://www.chase.com")
> res=c:perform()
But after this last operation the program is stuck as if waiting for something. What am I doing wrong here?
Thanks
I tried your program and it seems to work fine. What I get is the content of the given site pumped to stdout. It seems you are just having networking issues...
If you want to capture the whole output as a string and process it later, you have to provide a callback using OPT_WRITEFUNCTION which will be called with more data which you can save. Here is a simplified version of how I implemented the GET method in my simple web-mining toolbox WDM.
local c = curl.new()
...
function get(url)
c:setopt(curl.OPT_URL,url)
local t = {} -- output will be stored here
c:setopt(curl.OPT_WRITEFUNCTION, function (a, b)
local s
-- luacurl and Lua-cURL friendly way
if type(a) == "string" then s = a else s = b end
table.insert(t, s) -- store this piece of data
return #s
end)
assert(c:perform())
return table.concat(t) -- return the whole content
end

Cassandra thrift Erlang insert

I'm currently trying to get my head wrap around Cassandra/thrift with Erlang...
I have a Column Family named "mq" (as in message queue)...
I would like to have a row per user (with an user_id), each message would be a new column with timestamp for name and the message as the value.
Here's in Cassandra-cli what I'm doing :
create keyspace my_keyspace;
use my_keyspace;
create column family mq with comparator=UTF8Type and key_validation_class=UTF8Type;
%% Adding to user_id (00000001) the message "Hello World!"
set mq['00000001']['1336499385041308'] = 'Hello Wold';
Everything works great with Cassandra-cli
However, When I'm trying to insert from Erlang, I'm running into some issue :
1>rr(cassandra_types).
2>{ok, C}=thrift_client_util:new("localhost", 9160, cassandra_thrift,[{framed, true}]).
3>thrift_client:call(C, 'set_keyspace', ["peeem"]).
4>thrift_client:call(C,'insert',["00000001",
#columnPath{column_family="mq"},
#column{name="1336499385041308", value="Hello World!"},
1
]
).
Here's the error :
{error,{bad_args,insert,
["00000001",
#columnPath{column_family = "mq",super_column = undefined,
column = undefined},
#column{name = "1336499385041308",value = "Hello World!",
timestamp = undefined,ttl = undefined},1]}}}
Any help would be appreciated...
EDIT 1 :
I have found out that it should be (as it works for someone else) :
thrift_client:call(C,'insert', ["00000001", #columnParent{column_family="mq"}, #column{name="123456",value="Hello World!"}, 2]).
Here's the related error message :
** exception error: no match of right hand side value {{protocol,thrift_binary_protocol,
{binary_protocol,{transport,thrift_framed_transport,
{framed_transport,{transport,thrift_socket_transport,
{data,#Port<0.730>,infinity}},
[],[]}},
true,true}},
{error,closed}}
in function thrift_client:send_function_call/3 (src/thrift_client.erl, line 83)
in call from thrift_client:call/3 (src/thrift_client.erl, line 40)
Ok I have found out what was the issue, or issues to be correct...
Here's my code in order to connect and insert...
rr(cassandra_types).
{ok, C}=thrift_client_util:new("localhost", 9160, cassandra_thrift,[{framed, true}]).
{C1, _} = thrift_client:call(C, 'set_keyspace', ["my_keyspace"]).
thrift_client:call(C1,'insert', ["00000001", #columnParent{column_family="mq"}, #column{name="1234567",value="Hello World !", timestamp=0}, 2]).
In fact We should insert into the new thrift_client that 'set_keyspace' returns... apparently for every call done through thrift a new thrift_client is generated and should be used.
Further more, We should use columnParent instead of columnPath (not sure why yet, it just works). And timestamp in the #column is mandatory...
I hope this helps someone else.
I recommend checking out https://github.com/ostinelli/erlcassa instead of reinventing the Thrift-wrestling wheel.

How do you accept a string in Erlang?

I'm writing a program where the user must enter a 'yes' or 'no' value. The following is the code that will be executed when the message {createPatient,PatientName} is received.
{createPatient, PatientName} ->
Pid = spawn(patient,newPatient,[PatientName]),
register(PatientName,Pid),
io:format("*--- New Patient with name - ~w~n", [PatientName]),
Result = io:read("Yes/No> "),
{_,Input} = Result,
if(Input==yes) ->
io:format("OK")
end,
loop(PatientRecords, DoctorPatientLinks, DoctorsOnline, CurrentPatientRequests, WaitingOfflineDoctorRequests);
When executed ,the line "New Patient with name..." is displayed however the line Yes/No is not displayed and the program sort of crashes because if another message is sent, then the execution of that message will not occur. Is there a different way to solve this problem please?
There are a number of points I would like to make here:
The io:read/1 function reads a term, not just a line, so you have to terminate input with a '.' (like in the shell).
io:read/1 returns {ok,Term} or {error,Reason} or eof so you code should check for these values, for example with a case.
As #AlexeyRomanov mentioned, io:get_line/1 might be a better choice for input.
The if expression must handle all cases even the ones in which you don't want to do anything, otherwise you will get an error. This can be combined with the case testing the read value.
You spawn the function patient:newPatient/1 before you ask if the name is a new patient, this seems a little strange. What does the newpatient function do? Is it in anyway also doing io to the user which might be interfering with functions here?
The main problem seems to be work out what is being done where, and when.
This is very artificial problem. In erlang any communication is usually inter-process and exchanging strings wouldn't make any sense - you ask question in context of process A and you would like to post answer in context of process B (shell probably).
Anyways, consider asking question and waiting in receive block in order to get an answer.
When question pops out in shell, call a function which will send the answer to 'asking' process with your answer.
So:
io:format("*--- New Patient with name - ~w~n", [PatientName]),
receive
{answer, yes} -> do_something();
{answer, no} -> do_something()
end
The 'answering' function would look like that:
answer(PatientName, Answer) ->
PatientName ! {answer, Answer}.
And shell action:
$> *--- New Patient with name - User1036032
$> somemodule:answer('User1036032', yes).
It is possible to create some dialog with shell (even unix shell), but to be honest it is used so rare that I do not remember those I/O tricks with read and write. http://trapexit.com/ used to have cookbook with this stuff.
Use io:get_line("Yes/No> ") instead.

Resources