Create gen/let for syntax sugar and to address fmap/bind confusion
Description
Problem Statement
fmap/bind confusion
Users who are not big fans of monads may find the names of and distinction between fmap and bind to be confusing. A combination of the two can exist, where users can return either a value or a generator and the system chooses to use fmap or bind automatically. The downside of this approach is it is ambiguous (i.e., a user cannot use it to generate a generator, though this is admittedly uncommon), and it offends people who like thinking about the precise types of functions (see this criticism in particular regarding a similar behavior in jQuery). However, neither of these are very serious restrictions, since falling back to fmap and bind is always an option.
syntax sugar
Writing complex generators can be very syntactically convoluted, with heavy nesting and confusing structure especially caused by the opposite argument order of fmap and bind. In the same way that clojure.core/let provides a flatter (especially when multiple clauses are present) syntax for something that can technically be accomplished using fn, a macro could flatten the syntax of generators that make a lot of use of bind and fmap while providing the same functionality.
Prior Art
This feature supposedly exists in the erlang quickcheck.
A macro in the generators namespace called let, which uses bind for multiple clauses, and whose body is processed with bind or fmap depending on whether it is a generator.
Examples:
Feature Comparison
gen/let and test.chuck's for differ in a couple independent ways, so it might be helpful to be explicit about what the different options are here. I also included Erlang's let, based on how I imagine it works.
Problem Statement
fmap/bind confusion
Users who are not big fans of monads may find the names of and distinction between
fmap
andbind
to be confusing. A combination of the two can exist, where users can return either a value or a generator and the system chooses to usefmap
orbind
automatically. The downside of this approach is it is ambiguous (i.e., a user cannot use it to generate a generator, though this is admittedly uncommon), and it offends people who like thinking about the precise types of functions (see this criticism in particular regarding a similar behavior in jQuery). However, neither of these are very serious restrictions, since falling back tofmap
andbind
is always an option.syntax sugar
Writing complex generators can be very syntactically convoluted, with heavy nesting and confusing structure especially caused by the opposite argument order of
fmap
andbind
. In the same way thatclojure.core/let
provides a flatter (especially when multiple clauses are present) syntax for something that can technically be accomplished usingfn
, a macro could flatten the syntax of generators that make a lot of use ofbind
andfmap
while providing the same functionality.Prior Art
This feature supposedly exists in the erlang quickcheck.
Another attempt at solving the same problem is test.chuck's for macro.
Proposal
A macro in the generators namespace called
let
, which usesbind
for multiple clauses, and whose body is processed withbind
orfmap
depending on whether it is a generator.Examples:
Feature Comparison
gen/let
and test.chuck'sfor
differ in a couple independent ways, so it might be helpful to be explicit about what the different options are here. I also included Erlang'slet
, based on how I imagine it works.Feature
Erlang's
let
gen/let
test.chuck/for
Multiple clauses
✓
✓
Subsequent clauses handled with
bind
N/A
✓
✓
Body uses
bind
if it's a generator✓
✓
Supports filtering
✓
Supports binding intermediate values
✓
Supports parallel generators (via
tuple
)✓