[erlang-questions] Dialyzer "no local return" warning for anonymous functions

Hynek Vychodil hynek@REDACTED
Thu Dec 16 00:42:41 CET 2010


I'm afraid it is not what you are looking for.

-module(funky).

-export([my_funky_mnesia_test/2, test/2, transaction/1]).

test(A, B) ->
  try
    ?MODULE:transaction((fun my_funky_mnesia_test/2)(A,B))
  catch
    exit:{aborted, all_valid} ->  ok;
    exit:{aborted, Error} ->  {error, Error}
  end.

transaction(T) ->
  io:format("Start transaction.~n", []),
  T(),
  io:format("End transaction.~n", []).

my_funky_mnesia_test(A, B) ->
  io:format("Inside Transaction (~p,~p)~n", [A, B]),
  mnesia:abort(all_valid).

---8<-------------------->8---

1> c(funky).
{ok,funky}
2> funky:test(foo, bar).
Inside Transaction (foo,bar)
ok

What happen? Execution not even reach calling ?MODULE:transaction/1
because exception is raised when evaluating ?MODULE:transaction/1
parameter. (fun my_funky_mnesia_test/2)(A,B) calls
my_funky_mnesia_test/2 and don't return fun/0 which should be passed
into ?MODULE:transaction/1
Unfortunately correct fun() -> (fun my_funky_mnesia_test/2)(A,B) end
is same as fun() -> my_funky_mnesia_test(A,B) end which obviously
doesn't make Dialyzer happy again. You have to make something like

-spec my_funky_mnesia_test_maker(some_t(), another_t()) ->  fun(()->
no_return()).

my_funky_mnesia_test_maker(A,B) ->
  fun() -> my_funky_mnesia_test(A,B) end.



On Wed, Dec 15, 2010 at 11:53 PM, Bernard Duggan <bernie@REDACTED> wrote:
> On 15/12/10 20:08, Kostis Sagonas wrote:
>>
>> Bernard Duggan wrote:
>>>
>>> As far as I
>>> know, though, there's no way to -spec an anonymous function, nor is
>>> there any obvious way to make that particular function not anonymous.
>>
>> It's too early in the morning for me, but doesn't the following do it?
>> (Warning: untested -- I also think the parentheses aroung the fun object
>> are not really needed, but perhaps the code is clearer with them)
>>
>>    validate(A, B) ->
>>        try
>>            mnesia:transaction((fun my_funky_mnesia_test/2)(A,B))
>>        catch
>>            exit:{aborted, all_valid} ->  ok;
>>            exit:{aborted, Error} ->  {error, Error}
>>        end.
>>
>>    -spec my_funky_mnesia_test(some_t(), another_t()) ->  no_return().
>>
>>    my_funky_mnesia_test(A, B) ->
>>        some_test_db_operations(A, B),
>>        mnesia:abort(all_valid).
>
> Indeed that does do it - thank you very much.  It had never occurred to me
> that you could call fun objects directly like that.  Of course in hindsight
> it's obvious, but then hindsight usually is :)
>
> Cheers,
>
> Beranrd
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
>



-- 
--Hynek (Pichi) Vychodil

Analyze your data in minutes. Share your insights instantly. Thrill
your boss.  Be a data hero!
Try GoodData now for free: www.gooddata.com


More information about the erlang-questions mailing list