<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>