I have a custom environment properties (that is almost ready for release to Github) that works like so:
\begin{properties}
\item[no max in reals] \forall a \in \Re, \exists b \in \Re : a < b
\item[minimum natural] \exists n \in \Na : \forall m \in \Na, n \le m
\end{properties}
and would produce (sans typo)

However, for a more complicated example, the spacing seems to be off:

I think this has something to do with the behavior of \NewDocumentEnvironment that I'm not accounting for…
MWE
\documentclass{article}
\usepackage{amsmath,amsthm} % \text{...}; \newtheorem{...}{...}
\usepackage{xparse,expl3}
\usepackage[hidelinks]{hyperref} % For some reason, this affects
% numbering of the equations.
\ExplSyntaxOn
% makes sure math content is centered
\cs_new:Nn \property_do_fill:
{ \hskip \textwidth minus \textwidth }
% enters math mode and starts a property
% does not typeset a math comment
\cs_new:Nn \property_do_begin:
{
\equation
\quad\bullet
\property_do_fill:
}
% enters math mode and starts a property
% does typeset math comment
\cs_new:Nn \property_do_begin:n
{
\equation
\quad\bullet\enspace\text{\slshape #1}
\property_do_fill:
}
% ends this property and exists math mode
\cs_new:Nn \property_do_end:
{
\property_do_fill:
\endequation
}
\bool_new:N \g_property_first_item_bool
\NewDocumentEnvironment { properties } { }
{
\bool_set_true:N \g_property_first_item_bool
% Delimits properties
% starts off by beginning a property, and then redefines itself
% to end a previous property before starting a new one.
\DeclareDocumentCommand \item { o }
{
\bool_if:NTF \g_property_first_item_bool
{ \bool_set_false:N \g_property_first_item_bool }
{ \property_do_end: }
\IfValueTF { ##1 }
{ \property_do_begin:n { ##1 } }
{ \property_do_begin: }
}
}
{ \property_do_end: }
\theoremstyle{definition}
\newtheorem{definition}{Definition}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Extra %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This stuff isn't necessary for compilation, but is stuff that I use
% in the example. Feel free, of course, to use it in your own stuff
% (LPPL and all that jazz). I find it helps further logicall organize
% stuff, although it acts a little weird with AUCTeX's fold mode.
% Save the old \forall
\cs_set_eq:NN \for_all: \forall
% create a *new* forall that takes two arguments: the predicate and
% the other thing. Because I forgot FOM.
\cs_new:Nn \for_all:nn
{
\for_all: #1,\; #2
}
\DeclareDocumentCommand \forall { s }
{
\IfBooleanTF { #1 }
\for_all:
\for_all:nn
}
% Save the old \exists
\cs_set_eq:NN \exists: \exists
% create a *new* forall that takes two arguments: the predicate and
% the other thing. Because I forgot FOM.
\cs_new:Nn \exists:nn
{
\exists:\,#1:#2
}
\DeclareDocumentCommand \exists { s }
{
\IfBooleanTF { #1 }
\exists:
\exists:nn
}
\ExplSyntaxOff
\def\Na{\mathbf N}
\begin{document}
\begin{definition}[group]
A group is a set $G$ together
with a binary operation $*$ on $G$
that satisfies the following axioms:
\begin{properties}
\item[associativity] \label{def:group:assoc}
\forall{a,b,c \in G}{(a * b) * c = a * (b * c)}
\item[identity] \label{def:group:identity}
\exists{e \in G}{\forall{a \in G}{a * e = a = e * a}}
\item[inverse] \label{def:group:inverse}
\forall{x \in G}{\exists{b \in G}{a * b = b * a = e}}
\end{properties}
\end{definition}
\end{document}


\existsand\forallto commands with arguments is something I'd never do (and your redefinitions break common LaTeX syntax). – egreg Sep 11 '13 at 09:11\parindent). Point taken about redefinitions; I suppose I should just caps them (\ForAll) instead? – Sean Allred Sep 11 '13 at 12:11equationenvironments. – egreg Sep 11 '13 at 12:17