[erlang-questions] http:request
Klas Johansson
klas.johansson@REDACTED
Fri Apr 22 10:17:53 CEST 2011
On Fri, Apr 22, 2011 at 9:49 AM, Kostis Sagonas <kostis@REDACTED> wrote:
> Carlo Bertoldi wrote:
>>
>> Il 21/04/2011 17:10, Carlo Bertoldi ha scritto:
>>>
>>> Good afternoon,
>>> I have a problem with http:request.
>>>
>> <snip>
>>>
>>> Result = http:request(get, {CompleteUrl, [{"User-Agent", "Erl-bot"}]},
>>> [], []),
>>> io:format("Result = ~p~n", [Result]).
>>>
>>> Occasionally I don't see Result printed, but a nice error:
>>> ** Reason for termination ==
>>> ** {{badmatch,{16,6,18}},
>>
>> Hello, I discovered the cause of the badmatch: it was due to the debug
>> macro I've defined.
>> Here it is:
>>
>> -define(DBG(Str, Args),
>> {Year, Month, Day} = date(),
>> {Hour, Min, Sec} = time(),
>> io:format("~2.10.0B/~2.10.0B/~4B ~2.10.0B:~2.10.0B:~2.10.0B [~p:~p] - ",
>> [Day, Month,
>> Year, Hour, Min, Sec, ?MODULE, ?LINE]), io:format(Str, Args)).
>>
>> Can someone explain me what I did wrong here? Why should I obtain a
>> badmatch on {Hour, Min, Sec} = time() ?
>
> A typical reason for this is if you used the macro in some context where
> variables named Hour, Min, and Sec already existed. This is called name
> capture and is a typical problem of macros. You should carefully examine all
> places in the code where this macro is used. Alternatively, you can try to
> minimize the risk of name capture by changing the macro to e.g.:
>
> -define(DBG(Str, Args),
> {Year__, Month__, Day__} = date(),
> {Hour__, Min__, Sec__} = time(),
> io:format("~2.10.0B/~2.10.0B/~4B ~2.10.0B:~2.10.0B:~2.10.0B [~p:~p] - ",
> [Day__, Month__, Year__, Hour__, Min__, Sec__, ?MODULE, ?LINE]),
> io:format(Str, Args)).
Perhaps you're using the same macro in multiple places in the same
scope (for example on two consecutive lines)? Like this:
some_function(...) ->
...
?DBG("foo ~p", [SomeVal1]),
...
?DBG("bar ~p", [SomeVal2]),
...
Now, the macro will be expanded during preprocessing:
some_function(...) ->
...
{Year__, Month__, Day__} = date(),
{Hour__, Min__, Sec__} = time(),
...
{Year__, Month__, Day__} = date(),
{Hour__, Min__, Sec__} = time(),
...
Since time flies, seconds etc. change and will no longer match ==> badmatch.
I guess you could either write a function which prints the timestamp
(and takes ?LINE as a parameter) or use a trick like eunit uses for
its assert macros to bind variables in a new scope (it looks a bit
funny and you still need to take care to use unique variable names
like Kostis suggested):
(fun() -> {Year__, Month__, Day__} = date(), ... end)()
https://github.com/erlang/otp/blob/dev/lib/eunit/include/eunit.hrl#L141
Cheers,
Klas
More information about the erlang-questions
mailing list