OT: Re: Just took a look in the perl newsgroup....

Carl Banks imbosol at aerojockey.com
Thu May 29 13:40:13 EDT 2003


Bengt Richter wrote:
> On Wed, 28 May 2003 14:17:37 -0600, Steven Taschuk <staschuk at telusplanet.net> wrote:
> 
>>Quoth Bengt Richter:
>>  [...]
>>> IMO that's still a workaround for the case (;-) where you want to rebind
>>> in the same scope. But I just thought of an alternative, which see below
>>> in stripped-down version of previous example:
>>  [...]
>>>         ## a local case structure with rebinding in local scope
>>>         try: raise `x`
>>>         except '1':
>>>             # case code in same scope as case
>>>             inner_var = '<<value bound in scope of "case" 1)>>'
>>>         except '2':
>>>             inner_var = '<<value bound in scope of "case" 2>>'
>>>         except:
>>>             inner_var = '<<value bound in scope of "case" default>>'
>>
>>Yikes.
>>
>>Inherently fragile due to reliance on interning of repr(x).  Won't
>>work at all if/when string exceptions go away.
> Which version requires interning of repr(x)? It looks like the code is less
> efficient than the corresponding if/elif/else code, however.
> 
>>
>>A strong candidate for a Most Outlandish Proposal award.  (In
>>fact, I think you're a strong candidate for a Lifetime Achievement
>>Award in this area.  <0.25 wink>)
>>
> LOL ;-)
> I figure the best QA for toys is playing with them ;-)
> 
> Responding to the objections above <~ ^ @>
> 
> ====< ycase.py >=====================================
> class Switch(object):
>    def __init__(self, *caseNames):
>        for name in caseNames:
>            if not isinstance(name,str): name = `name`
>            exec ('class _%s(Exception):pass'%name) in self.__dict__
>            del self.__dict__['__builtins__']
>    def __call__(self, name):
>        raise getattr(self, '_%s'%name, ValueError)
> 
> case = switch = Switch(1,2,'foo')
> 
> def f(x):
>    def g(x):
>        inner_var = 5      
>        ## a local case structure with rebinding in local scope
>        try: switch(x)
>        except case._1:
>            # case code in same scope as case
>            inner_var = '<<value bound in scope of "case" 1)>>'
>        except case._2:
>            inner_var = '<<value bound in scope of "case" 2>>'
>        except case._foo:
>            inner_var = '<<value bound in scope of "case" foo>>'
>        except:
>            inner_var = '<<value bound in scope of "case" default>>'
>        print 'inner_var as seen at end of "case":', inner_var
>    g(x)
> 
> for i in (0,1,2,'foo'): print '---- f(%r) -----'%i; f(i)
> =====================================================
> [19:59] C:\pywk\clp>ycase.py
> ---- f(0) -----
> inner_var as seen at end of "case": <<value bound in scope of "case" default>>
> ---- f(1) -----
> inner_var as seen at end of "case": <<value bound in scope of "case" 1)>>
> ---- f(2) -----
> inner_var as seen at end of "case": <<value bound in scope of "case" 2>>
> ---- f('foo') -----
> inner_var as seen at end of "case": <<value bound in scope of "case" foo>>
> 
> ;-)
> 
> Regards,
> Bengt Richter


Better, perhaps, have the "case" cache results, like this:

    _case_cache = {}

    def case(v):
        if _case_cache.has_key(v):
            return _case_cache[v]
        class Case(Exception):
            value = v
        _case_cache[v] = Case
        return Case

    switch = case


Then the resulting case statement looks like:

    try: raise switch(n)
    except case(1):
        print 1
    except case(2):
        print 2
    except:
        print 'default'


Very neat, clever idea.


-- 
CARL BANKS




More information about the Python-list mailing list