<div dir="ltr">I think you are missing the point. Let's demonstrate the problem in this way. There is natural but not working way how to do it<div><br></div><div><div>-define(WITH_G(L, Do),</div><div>        begin</div><div>            G = Module:from_edgelist(L),</div><div>            try Do after delete(G)</div><div>            end</div><div>        end</div><div>       ).</div><div><br></div><div>-define(WITH_G(L, DoEmpty, DoOther),</div><div>        ?WITH_G(L,</div><div>                case L of</div><div>                    [] -> DoEmpty;</div><div>                    _ -> DoOther</div><div>                end</div><div>               )</div><div>       ).</div><div><br></div><div><div>prop_vertices(Module) -></div><div>    ?FORALL(</div><div>       L, digraph(),</div><div>       ?WITH_G(</div><div>          L, equals([], vertices(G)),</div><div>          ?FORALL(</div><div>             {V1, V2}, oneof(L),</div><div>             conjunction(<br></div><div>               [{source,     lists:member(V1, vertices(G))},</div><div>                {sink,       lists:member(V2, vertices(G))},</div><div>                {in_sources, lists:member(V1, sources(G))},</div><div>                {in_sinks,   lists:member(V2, sinks(G))}</div><div>               ]</div><div>              )</div><div>            )<br></div><div>         )</div><div>      ).</div></div></div><div><br></div><div>And how to make it work:</div><div><br></div><div><div>prop_vertices(Module) -></div><div>    ?FORALL(</div><div>       L, digraph(),</div><div>       case L of</div><div>           [] -> ?WITH_G(L, equals([], vertices(G)));</div><div>           _  -></div><div>               ?FORALL(</div><div>                  {V1, V2}, oneof(L),</div><div>                  ?WITH_G(L,</div><div>                          begin</div><div>                              Vs  = vertices(G),</div><div>                              Ses = sources(G),</div><div>                              Sks = sinks(G),</div><div>                              conjunction(</div><div>                                [{source,     lists:member(V1, Vs)},</div><div>                                 {sink,       lists:member(V2, Vs)},</div><div>                                 {in_sources, lists:member(V1, Ses)},</div><div>                                 {in_sinks,   lists:member(V2, Sks)}</div><div>                                ]</div><div>                               )</div><div>                          end</div><div>                         )</div><div>                 )</div><div>       end</div><div>      ).</div><div><br></div></div><div>There is the problem. There is no way you can write ?WITH_G macro working with any of PropEr macros as a parameter. And it would have a simple solution. Just spawn the process or add hooks for clean up.</div><div><br></div><div>I know it is possible to write it in a way it will work, but it prevents to write it reliably and in structured way.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 26, 2015 at 1:44 AM, Kostis Sagonas <span dir="ltr"><<a href="mailto:kostis@cs.ntua.gr" target="_blank">kostis@cs.ntua.gr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 05/25/2015 05:11 PM, Hynek Vychodil wrote:<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
I bumped in the problem how clean up after property in PropEr. Let's<br>
have simple property where I make ets table:<br>
<br>
prop_ets() -><br>
     ?FORALL(V, integer(),<br>
         begin<br>
             E = ets:new(),<br>
             true = ets:insert(T, {V, ok}),<br>
             equals([{V, ok}], ets:lookup(T, V))<br>
         end<br>
     ).<br>
<br>
How am I supposed to delete ets table? It is trickier than looks like.<br></span>
... <SNIP><br>
</blockquote>
<br>
I am not sure I understand what it is exactly that you are finding difficult to do in the simple example above.  Here is how:<br>
<br>
=====================================================================<br>
-module(pets).<br>
-include_lib("proper/include/proper.hrl").<br>
<br>
-export_type([key/0, val/0]). % shut off compiler warning<br>
<br>
-type key() :: a | b | c.<br>
-type val() :: 0..42.<br>
<br>
prop_ets() -><br>
  ?FORALL({K,V}, {key(),val()},<br>
          begin<br>
              T = setup(),<br>
              true = ets:insert(T, {K, V}),<br>
              Res = ets:lookup(T, K),<br>
              cleanup(T),<br>
              [{K, V}] =:= Res<br>
          end).<br>
<br>
setup() -><br>
   ets:new(?MODULE, [public, named_table]).<br>
<br>
cleanup(T) -><br>
   ets:delete(T).<br>
========================================================================<br>
<br>
The pattern of doing a setup, running some commands and getting some Result, doing the cleanup you want to do, and the check that the result is the one that you expect is a general pattern in property-based testing.<br>
<br>
As you can see, the above works:<br>
<br>
kostis@pc:~/proper$ erl -pa ~/proper<br>
Erlang/OTP 17 [erts-6.4.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]<br>
<br>
Eshell V6.4.1  (abort with ^G)<br>
1> c(pets, [debug_info]).<br>
{ok,pets}<br>
2> proper:quickcheck(pets:prop_ets()).<br>
....................................................................................................<br>
OK: Passed 100 test(s).<br>
true<br>
<br>
<br>
Change the property to one that does not hold (e.g. [{K, V}] =/= Res) and you will also see that shrinking works.<br>
<br>
<br>
I am not sure I follow what you mean by your nested ?FORALL properties but note that, as shown above, you can easily imitate multiple ?FORALLs by using complex terms (tuples, lists, etc.).<br>
<br>
Hope this helps,<br>
Kostis<br>
</blockquote></div><br></div>