Jonathan Eunice committed 716a303

about to edit ReMatch

Comments (0)

Files changed (5)

     import re
-    match ='(pattern\w*)', some_string)
+    match =, some_string)
     if match:
     from intensional import Re
-    if some_string in Re(r'(pattern\w*)'):
+    if some_string in Re(pattern):
         print _[1]
-Note this turns the sense of the matching around, asking "is a given string *in*
-the set of items this pattern describes?" The ``Re`` pattern is an intensionally defined set--namely, the
-set of all strings matching the pattern. This makes excellent sene in cases where
-you have a clear intent for the match--for example, determining "is the given string
-within the set of *all legitimate commands*?"
+There are two things to note here: First,
+this turns the sense of the matching around, asking "is a given string *in*
+the set of items this pattern describes?" The ``Re`` pattern is an intensionally
+defined set (namely "all strings matching the pattern"). This order often makes
+excellent sense whey you have a clear intent for the test. For example, "is the
+given string within the set of *all legitimate commands*?"
-If you prefer the more traditional ``re`` pattern, they are also available in a
+Second, the ``in`` test had the side effect of setting the underscore
+name ``_`` to the result. Python doesn't support *en passant* assignment, so
+you can't both test and collect results in the same motion, even though that's
+sometimes exactly appropriate. ``Re`` use introspection to get around this
+difficulty and provide neat results.
+If you prefer the more traditional ``re`` calls, you can still use them with the
 convenient *en passant* style.::
-    if Re(r'(pattern\w*)').search('string with pattern in it'):
+    if Re(pattern).search(some_string):
         print _[1]
-Note that the underscore name ``_`` holds the result.
-This works even better with named pattern components, such as::
+``Re`` works even better with named pattern components, such as::
     person = 'John Smith 48'
-    if Re(r'(?P<name>[\w\s]*)\s+(?P<age>\d+)').search(person):
+    if person in Re(r'(?P<name>[\w\s]*)\s+(?P<age>\d+)'):
         print, "is", _.age, "years old"
         print "don't understand '{}'".format(person)
 ``Re`` objects are `memoized <>`_ for efficiency, so they
 are only compiled once, regardless of how many times they're mentioned in the program.
-Or if you 
-Say you have a class ``Thing`` that requires expensive computation to
-create, or that should be created only once. You can make that happen
-simply by adding one line to its definition::
-    from mementos import MementoMetaclass
-    class Thing(object):
-        __metaclass__ = MementoMetaclass
-        def __init__(self, name):
-   = name
-        ...
-Then ``Thing`` objects will be memoized::
-    t1 = Thing("one")
-    t2 = Thing("one")
-    assert t1 is t2
- *  Derived from `an ActiveState recipe
-    <>`_ by Valentino Volonghi.
- *  It is safe to memoize multiple classes at the same time. They will all be stored in the same cache, but
-    their class is a part of the cache key, so the values are distinct.
- *  This implementation is *not* thread-safe, in and of itself. If you're
-    in a multi-threaded environment, wrap object instantiation in a lock.
- *  Be careful with call signatures. This metaclass
-    caches on call signature, which can vary if keyword args
-    are used. E.g. ``def func(a, b=2)`` could be called ``func(1)``, ``func(1,2)``,
-    ``func(a=1)``, ``func(1, b=2)``, or ``func(a=2, b=2)``--and all resolve to the
-    same logical call. And this is just for two parameters! If there are more
-    than one kwarg, they can be arbitrarily ordered, creating *many* logically
-    identical permuations. Thank Goodness Python doesn't allow kwargs to come
-    before positional args, else there'd be even more ways to make the same
-    call.
-    So if you instantiate an object once, then again with a logically
-    identical call but using a different calling structure/signature, the
-    object won't be created and cached just once--it will be created and
-    cached multiple times.::
-        o1 = Thing("lovely")
-        o2 = Thing(name="lovely")
-        assert o1 is not o2   # because the call signature is different
-    This may degrade performance, and can also create
-    errors, if you're counting on ``mementos`` to create just one object.
-    So don't do that. Use a consistent calling style, and it won't be a problem.
-    In most cases, this isn't an issue, because objects tend to be
-    instanitated with a limited number of parameters, and you can take care
-    that you instantiate them with parallel call signatures. Since this works
-    99% of the time and has a simple implementation, it's worth the price of
-    this inelegance. For the 1% edge-cases where multiple call signature
-    variations must be conclusively resolved to a unique canonical signature,
-    the ``inspect`` module could be used (e.g. ``getargvalues()`` or
-    ``getcallargs()`` to create such a unified key.
- *  Not to be confused with the `memento <>`_
-    module, which does something completely different.
- *  In some cases, you may not want the entire initialization-time call signature
-    to define the cache key--only part of it. (Because some arguments to ``__init__``
-    may be useful, but not really part of the object's 'identity'.) The
-    best option is to design ``__init__`` without superflous attributes, then
-    create a second
-    method that adds sets useful-but-not-essential data. E.g.::
+It's entirely possible to implement an intensional set like idea with
+other Python mechanisms, such as ``lambda`` expressions, test functions,
+and list comprehensions. Many (most?) Python programs already *de facto*
+use this implicit intensional set approach. Making intensional sets
+explicit, however, has the benefit of making what's being done more
+clear. It provides a mechanism for cleaning up several sort of ucky
+parts of Python:
-        class OtherThing(object):
-            __metaclass__ = MementoMetaclass
-            def __init__(self, name):
-       = name
-                self.color = None
-                self.weight = None
-            def set(self, color=None, weight=None):
-                self.color = color or self.color
-                self.weight = weight or self.weight
-                return self
-        ot1 = OtherThing("one").set(color='blue')
-        ot2 = OtherThing("one").set(weight='light')
-        assert ot1 is ot2
-        assert ot1.color == ot2.color == 'blue'
-        assert ot1.weight == ot2.weight == 'light'
+ *  Messy, guts-exposed regular expression tests
+ *  Overly verbose lambda expressions
+ *  Long, non-DRY ``if``/``elif``/``else`` constructions (with ``switch``)
+ *  A mess of mechanisms for collection filtering
-    pip install mementos
+    pip install intensional
 (You may need to prefix this with "sudo " to authorize installation.)
+from intensional import *
 # Any = Union, Every = Intersection
 # might want to complete more of the set functions like symmetric difference, discard, etc
+# should this be reorganized into multiple files?
 class ReMatch(orderedstuf):
 class Re(IntensionalSet):
+    ### need go back meahcnism
     def __init__(self, pattern, flags=0):
         self.pattern = pattern
         self.flags   = flags
         # this method -> calling method -> MementosMetaclass.__call__ -> Re.__init__ -> caller
         inspect.currentframe().f_back.f_back.f_back.f_back.f_locals['_'] = result
+        # do we want to make the variable for '_' settable?
+        # do we want to wait for an attribute to be called to get it?
         return result
     def __contains__(self, item):
     def __contains__(self, item):
         return fnmatch.fnmatch(item, self.expr)
 class Any(IntensionalSet):
     An item is in an Any if it is or is in any member of the set.
-    version=verno("0.012"),
+    version=verno("0.013"),
     author='Jonathan Eunice',
     description='Intensional sets in Python',
     assert 12 in a2
     assert 12 not in bn
+def test_Glob():
+    assert "alpha" in Glob("a*")
+    assert "beta" not in Glob("a*")
 def test_Test():
     mytest = Test('x.startswith("a")')