<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 2, 2015 at 4:24 AM, Lloyd R. Prentice <span dir="ltr"><<a href="mailto:lloyd@writersglen.com" target="_blank">lloyd@writersglen.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>Your code exhibits a depth of understanding and subtlety that I can only hope to aspire to.</div><div><br></div><div>Can you help me understand the ?LET(... and ?SUCHTHAT(... expressions? </div></blockquote></div><br></div><div class="gmail_extra">I agree with Fernando, that it is often nicer to pull these things into a function on its own, and use that function as in:<br><br></div><div class="gmail_extra">f(X) -> [1,2] ++ e(X).<br></div><div class="gmail_extra">e(X) when X < 5 -> [];<br></div><div class="gmail_extra">e(X) -> [X].<br><br></div><div class="gmail_extra">In the QuickCheck models however, you would often end up writing many of such one-off functions, so this is why I sometimes tend to use the [X || test()] scheme.<br><br></div><div class="gmail_extra">As for ?LET(...) and ?SUCHTHAT(...): They are macros which are used in QuickCheck like tools (Erlang QuickCheck, Proper, Triq, ...). If you have a generator like choose/2 which generates numbers between two endpoints:<br><br>6> triq_dom:sample(<br> triq_dom:choose(1, 10)).<br>[5,9,1,3,7,6,1,5,3,8,9]<br><br></div><div class="gmail_extra">Some times, however, you don't want a raw generator. You want to do something to the result before you use it. The problem however is that the generator generates. So your code would have to:<br><br></div><div class="gmail_extra">1. draw a specimen from the generator.<br></div><div class="gmail_extra">2. apply some function to the drawn specimen<br></div><div class="gmail_extra">3. return the result of the application, but do so as a new generator doing this!<br><br></div><div class="gmail_extra">This is what ?LET(...) does[0]. Writing<br><br></div><div class="gmail_extra">?LET(I, choose(1,10),<br></div><div class="gmail_extra"> I * 7).<br><br></div><div class="gmail_extra">would return a new generator, which draws a number between 1 and 10, and returns 7 times that number. That is, it returns numbers in the range [7,14,21,28,...,70].<br><br></div><div class="gmail_extra">The ?SUCHTHAT(..) macro is used as ?SUCHTHAT(S, Gen, Pred(S)). It picks a specimen from Gen and then tests it against Pred. If Pred(S) returns true, it returns that value. If Pred(S) returns false, it tries generating a new value satisfying the predicate. I.e., generate S from Gen such that P(S) is true. ?SUCHTHAT(..) itself is a generator, doing this internally[1].<br><br></div><div class="gmail_extra">You use the ?SUCHTHAT(..) macro to reject certain values which are not desirable. In the case of trying to remove an element from a map, you want to generate an element that is not present in the map in some cases. This is to verify such removal has no effect on the map. So I use a ?SUCHTHAT(...) to make sure the generated target is not already present in the map. I expect to be able to find such a value in relatively few tries. Even considering very large maps with thousands of elements, you can easily generate a new element randomly, which isn't in there.<br><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">[0] ?LET(..) is a monadic bind over the quickcheck monad.<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">[1] The caveat of ?SUCHTHAT is that you want it to generate a valid value fairly quickly. If you are drawing random hay from a haystack to find a needle, and the haystack is large, then it is a bad idea. You have a random search problem at hand then.<br></div><div class="gmail_extra"><br clear="all"><br>-- <br><div class="gmail_signature">J.</div>
</div></div>