joshu: (Default)

I’ve done a fair amount of experimenting with vegan and vegetarian cooking, and seitan has always caught my interest. I had an initial good experience with a chicken-style seitan recipe, but something about the taste turned me off from it after the second or third time making it. Fortunately, I later found a recipe for Italian sausage from the Post-Punk Kitchen, and I’ll reproduce the modified recipe I use, with more of an herbs-de-provence flavor:

ingredients

  • wet ingredients
    • 1/2 cup chickpeas (or another type of bean; see notes below)
    • 1 cup vegetable broth
    • if you're using home-cooked beans, you can cut back on this and use some of the water the beans were cooked in
    • if you're using veggie broth powder like I do, feel free to use water in place of veggie broth here and add the proportional amount of veggie broth powder with the spices.
    • 2 Tbsp. soy sauce or Bragg’s liquid aminos
    • 1 Tbsp. oil
  • dry ingredients
    • 1 1/4 cup wheat gluten
    • 1/4 cup nutritional yeast
    • spices:
    • 2 Tbsp. granulated garlic
    • 1 tsp. dried oregano
    • 1 tsp. dried savory
    • 1 tsp. dried rosemary
    • 1 tsp. dried sage

directions

  • In a large bowl, mash the beans until they're a bit mushy; add the other wet ingredients and stir to combine.
  • In a separate bowl, combine the dry ingredients and mix to combine.
  • Mix the dry ingredients into the wet, and stir with a spoon if you like. I usually get right in there kneading with my hands since that’s how it’s going to end up anyway.
  • Mix/knead the dough until everything is incorporated. The dough should hold together pretty well, with a sort of play-dough consistency.
  • Make a long, log-shaped loaf out of the dough and roll it up in some aluminum foil (or in a clean kitchen towel, secured with twine)
  • Steam the seitan sausage to set it:
    • using a pot of water on a stovetop with a steamer basket in it, this takes about 40 minutes. I have a problem with it tending to boil dry during this relatively long cooking period, so I add more water as the boiling continues.
    • using a (stovetop) pressure cooker:
    • put the seitan in a steamer basket, with several cups of water (but not so much that it's going to get the seitan wet in the basket)
    • seal the pressure cooker
    • turn on the heat to medium-high or high (about 8 on my [electric] stove)
    • once the pressure cooker pressurizes, turn the heat down to medium (about 5 on my stove)
    • cook for 15 minutes at pressure
    • remove from heat and let the pressure cooker depressurize on its own — no quick-release needed
  • Unwrap (but be careful, it’s hot!) and store in the fridge until you want to use it. My preferred method of cooking it is sautéeing with some onions and garlic to make a filling for tacos, but it could also work well in, e.g., a stir fry

notes

  • After cooking this recipe a few times and feeling wasteful with the amount of foil, I bought a couple of plain flour sack dish towels from Amazon, as well as some reusable silicone kitchen zip-ties. These have worked really well for me!
  • I regularly substitute the beans and spices, so feel free to be creative! Combos that I’ve tried have included:
    • soy beans + garlic powder and sesame seeds
    • black beans + chipotles en adobo, cumin, and a little turmeric
joshu: (Default)

A quick brain-dump of some thoughts brought up by a post from Jayarava’s Raves, Rumination, the Stress Response, and Meditation:

Death is something we want to face with grace. It's the ultimate test of our test of our faith. We can feel good about ourselves if we face death with equanimity. Depression and other forms of psychological problem seem to be something we don't want to face at all. Since happiness is said to be the result of being a Buddhist, then a Buddhist suffering from distress is a kind of anathema. The reaction seems to be to pull away and isolate the person, perhaps with a sense of preventing the spread of the negativity contagion.

Responding to discomfort that we do not understand in others by turning away from it strikes me as at once understandably human and terribly misguided (especially for practitioners of Buddhism). When talking about the first noble truth (which I would paraphrase as “suffering/dukkha exists”), the Saṃyutta Nikāya says that “this noble truth of suffering is to be fully understood”. I can’t understand something by averting my gaze when it’s uncomfortable. If I regard suffering and malady as something that doesn’t happen to Buddhists, I think that I have confused human Buddhists with Bodhisattvas, and in so doing, I have limited my ability to perceive and address suffering. Indeed, if I already didn’t experience suffering, I wouldn’t really have much need for Buddhism, would I?

What’s more, if I see negativity as a contagion that I need to defend myself against, I think I display a lack of confidence in my own practice. While certainly I would be well-advised not to throw myself into strongly negative situations to test the strength of my practice as a Buddhist, avoiding them when they arise in my daily life feels like I’m treating my practice as fragile, needing protection from those around me. In so doing, it feels like I’m writing a big asterisk on “the cessation of suffering”, and writing a paragraph of fine print about the specific external situations that need to exist for this promise to not be void.

endnotes:

  1. “I am not exempt from illness” is noted as one of the five themes for contemplation, which can be found on SuttaCentral or Wikipedia.
  2. I initially wrote up these ideas in a comment on Jayarava’s blog, and then lost them because statefulness in Internet things is hard, especially when they involve a POST request to try and get a preview. Maybe this can serve as a useful lesson on impermanence.
joshu: (Default)

I’d like to share some thoughts that I have on the topic of modifying the English language to improve its precision and usefulness, following in the tradition of an English-language modification called E-Prime.

To summarize the Wikipedia article I linked above, E-Prime eliminates the word “to be”. To me, this seemed at first blush (a) extremely difficult, (b) really fascinating as an exercise of thought and language, and (c) unnecessarily austere. I don’t think my mind has changed on any of these three points, so I’ll try to go through them:

I have a lot of difficulty speaking without using the verb “to be”. I find writing a lot easier, probably because my writing always involves some revision and rewording when I find a sentence doesn't flow the way I would like it to. Speaking seems more awkward, because it entails stopping mid-sentence to rephrase a sentence that wouldn't end well without the expected “is” or “was” or “am”. Still, I find it difficult, not impossible, and I sometimes have fun with it as a linguistic experiment.

I find E-Prime valuable and interesting because it effectively cuts away a lot of the dressing in our language that makes us seem like we speak objectively. In many cases, opinions become a lot more obvious as just that. In addition, I’ve found that sometimes it makes me uncomfortable to communicate in E-Prime among speakers of conventional English, because it sounds like I have some sort of massive ego: most of my sentences wind up starting with “I”, and often “I find”, or “I think”, or “I have the opinion that”. I don’t consider this aspect more of a problem than normal language usage, but I find it interesting in that it highlights the fact that when we speak, we speak from our experience. In my case, it makes me more mindful, which I think overall is a good thing.

I think, though, that in aiming for mindfulness and clarity, E-Prime uses an axe where a scalpel (or at least a knife) would provide more utility: E-Prime, as stated, would remove entire tenses from the English language: the progressive (“I was running”, “she’s eating”, “they’re going to Canada”), and even the often-disparaged passive, which I think can have a particularly mindfulness/clarity benefit in that it can reframe a sentence in terms of your experience. Additionally, eliminating “be” doesn’t help one of my large problems with modern speech, namely the use of “good”, “bad”, and other such overloaded terms. A friend of mine who I regularly discuss this with has counseled me that it might help our language to largely avoid all attributives, saying:

[…] almost always, even though it takes more words to describe effects that way, [doing so] clarifies my thinking about the subject in a way that justifies the extra words.

“Extra words” feels true to me especially after writing this email, but if I have one message to send today, try this exercise out! My modified E-Prime consists of:

  • avoid “to be” except in verbal constructions
  • avoid adjectives with fuzzy meanings like “bad”, “good”, “right”, “wrong”, and instead try to explain your meaning.
  • take care with your speech, and think hard

happy speaking!

joshu: (Default)

I really like Python decorators. They provide a useful way to manipulate functions in a language that treats functions as first-class objects (i.e., a language that can pass around a function in the same way that you can pass around a string or an integer). They also provide a useful road into talking about some topics in computer science, namely closures and partial application!

But let’s start with the concrete, shall we?

Say that I’m working on an application that uses a database connection, and I find myself writing code that looks like this, using a global db variable:

def do_a_query(query):
    db.connect()
    result = db.query(query)
    db.close()
    return result

def execute_an_insert(obj):
    db.connect()
    db.insert(obj)
    db.close()
    return True

If you’ve got an eye for patterns, you’ll likely notice that I’ve re-used the same code in two places and will probably re-use it in more: opening and closing a database connection acts like a set of parentheses around my other code, and it seems tedious to write it again and again.

But here come decorators to the rescue! I can, instead, write:

def with_db(f):
    def _f_with_db(*args, **kwargs):
        db.connect()
        result = f(*args, **kwargs)
        db.disconnect()
        return result
    return _f_with_db

@with_db
def do_a_query(query):
    return db.query(query)

@with_db
def execute_an_insert(obj):
    db.insert(obj)
    return True

And it clears up a lot of the boilerplate. Fantastic! (Ignore for a moment those *args and **kwargs; we can come back to what they mean later. Suffice it to say, for now, that they pass along the arguments untouched.) I could even do something fancy, like extend my with_db function to re-use existing open connections:

def with_db(f):
    def _f_with_db(*args, **kwargs):
        try:
            result = _f_with_db(*args, **kwargs)
        except DBConnectionError:
            db.connect()
            result = f(*args, **kwargs)
    return _f_with_db

And the functions decorated with it shouldn’t care: it provides them with an active db connection that they can rely on, and that’s all they need to know.

Closures

So, let’s talk for a moment about closures. A closure, simply put, is a function – or a reference to a function – with some additional state attached. In Python, this generally looks like:

def make_a_closure(seed_variable):
    state = something_generates_state_with(seed_variable)
    def _closure(other_arg):
        return do_some_things_with(state, other_arg)
    return _closure

We would then call make_a_closure(some_seed) to get a closure function seeded with some_seed. For example, imagine that we wanted to make a function that, given a Unix Epoch timestamp, would return some predetermined format of date:

def make_a_strftime_closure(format_string):
    def _strftime_closure(epoch_timestamp):
        return time.strftime(format_string, time.gmtime(epoch_timestamp))
    return _strftime_closure

pretty_date = make_a_strftime_closure("%A, %B %e %Y")
print "The unix epoch began on %s" % pretty_date(0)
# The unix epoch began on Thursday, January  1 1970
print "Beyoncé was born on %s" % pretty_date(368434800)
# Beyoncé was born on Friday, September  4 1981

Suppose, though, we want a standardized format of time for our logs:

iso_date = make_a_strftime_closure("%Y-%m-%dT%H:%M:%S%z")
print "The unix epoch began on %s" % iso_date(0)
# The unix epoch began on 1970-01-01T00:00:S+0000

To tie this back to decorators: if you notice, a decorator function is just a closure with the decorated function as its bound state:

def decorate_a_function(f):
    def _decorated(*args, **kwargs):
        return f(*args, **kwargs)
    return _decorated

Partially Applied Functions

Partially applied functions sounds kind of gnarly and complicated but describes a pretty straightforward concept: applying some arguments to a function ahead of time.

Imagine, if you will, our original example with do_a_query and execute_an_insert, but this time without a global DB object:

def do_a_query_with_db(db, query):
    db.connect()
    result = db.query(query)
    db.close()
    return result

If you find yourself writing a lot of functions with a shared argument (e.g. db), you could use a partial application to supply the db argument ahead of time, using functools.partial:

do_a_query = partial(do_a_query_with_db, global_db)
do_a_query(some_query) # equivalent to do_a_query_with_db(global_db, some_query)

Python’s own documentation calls out that partial() is a pretty simple decorator:

Roughly equivalent to:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

So there you have it: Python’s decorators not only provide a neat way to manipulate and use functions, they also provide us a foot in the door for some pretty neat CS concepts!

Tune in next time for a choice of:

  • Functional Python II: Decorators and Wacky Hidden Functions
  • Functional Programming II: Folding and Currying

Profile

joshu: (Default)
joshu

January 2016

S M T W T F S
     12
3456789
10111213141516
1718192021 2223
24252627282930
31      

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 29th, 2016 03:12 pm
Powered by Dreamwidth Studios