Thursday, December 13, 2007

Biking the wrong way

Today I drove the U-Haul truck from Port Townsend to Sequim to drop it off. My plan was to bring my bicycle along, bike from the drop-off to the bus stop, and catch the bus back home. This bus only runs about every 3 hours, so it was important to time things correctly. I failed.

First, I didn't have internet access working in the new house, so I couldn't look up bus info, and couldn't remember it well.

Second, I wasn't paying attention to the clock.

Third, I rode my bike on the wrong path. Here's what I could have done:


View Larger Map

(Assume I cut across that sharp left turn that Google Maps won't let me do, because it thinks this is for a car.)

But I turned left too early, and meandered around for a while. Here's what I did instead:


View Larger Map

That's 7.5 miles. I'm pretty impressed with myself, considering how long it has been since I was in shape, and how, with the move & everything, the last couple months have been little exercise and a gain of 10 pounds.

And then, after the bus ride, I rode the bike up the big hill to the house.

And then, I put the babies in the stroller, and walked to the grocery store to get dinner for the family.

I'm feeling proud of myself, and very hopefull for my future exercise.

Saturday, December 08, 2007

An attempt at an immutable Queue

Eric said he will write about an immutable queue implementation. I really like the way the immutable stack turned out, essentially using references between Stack<> objects to implement a linked list, but I couldn't figure out a similarly elegant way to do the same thing for Queue. Maybe people who are more clever will come up with something better, but I just had each Queue<> object contain a list of references to elements.

I wrote once in C# 2.0, using an array to store the elements. The code would be cleaner if I used a List<>, but then I would be harder to verify immutability.

class Queue<T> : IQueue<T>

{

public static readonly IQueue<T> Empty = new Queue<T>(new T[] { });


 

readonly T[] elements;


 

Queue(T[] elements)

{

this.elements = elements;

}

public bool IsEmpty { get { return this.elements.Length == 0; } }

public T Peek() { return this.elements[0]; }

public IQueue<T> Remove()

{

T[] newElements = new T[this.elements.Length - 1];

Array.Copy(this.elements, 1, newElements, 0, newElements.Length);

return new Queue<T>(newElements);

}

public IQueue<T> Add(T value)

{

T[] newElements = new T[this.elements.Length + 1];

Array.Copy(this.elements, newElements, this.elements.Length);

newElements[newElements.Length - 1] = value;

return new Queue<T>(newElements);

}

public IEnumerator<T> GetEnumerator()

{

for (IQueue<T> Queue = this; !Queue.IsEmpty; Queue = Queue.Remove())

yield return Queue.Peek();

}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); }

}

Then I rewrote using C# 3.0, taking advantage of the rich support for sequences. The code is much simpler, but I think that's basically because the IEnumerable extension methods do pretty much what I did in my first attempt. But I'll take it. J

class Queue2<T> : IQueue<T>

{

readonly IEnumerable<T> elements;


 

public static IQueue<T> Empty = new Queue2<T>(new T[] { });


 

Queue2(IEnumerable<T> elements)

{

this.elements = elements;

}


 

IQueue<T> IQueue<T>.Add(T value)

{

return new Queue2<T>(this.elements.Concat(new T[] { value }));

}


 

IQueue<T> IQueue<T>.Remove()

{

return new Queue2<T>(this.elements.Skip(1));

}


 

T IQueue<T>.Peek()

{

return this.elements.First();

}


 

bool IQueue<T>.IsEmpty

{

get

{

return this.elements.Count() == 0;

}

}


 

IEnumerator<T> IEnumerable<T>.GetEnumerator()

{

return this.elements.GetEnumerator();

}


 

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

{

return this.elements.GetEnumerator();

}

}


 


 


 


 

Saturday, November 24, 2007

Immutable data class generator: it lives!

Well, it works. You invoke like this:

. .\Library.DataClass.ps1

class MyClass {

    field ([string]) S

    field ([int]) I

} > MyClass.cs

And then you can write:

MyClass mc = new MyClass.Builder().SetS("xxx").ToMyClass();

MyClass mc2 = new MyClass.Builder(mc).SetS("yyy").ToMyClass();

And the output looks like:

internal partial class MyClass

{

public readonly System.String S;

public readonly System.Int32 I;


 

public MyClass(string S, int I)

{

this.S = S;

this.I = I;

}

public class Builder

{

public string S;

public int I;

public Builder()

{

}

public Builder(MyClass value)

{

this.S = value.S;

this.I = value.I;

}

public virtual MyClass ToMyClass()

{

return new MyClass(this.S, this.I);

}

public virtual Builder SetS(string value)

{

this.S = value;

return this;

}

public virtual Builder SetI(int value)

{

this.I = value;

return this;

}

}

}

The main issue is that the ToMyClass and Set* methods are virtual. I think I may be hitting a bug in PowerShell, but I'm still researching it. For now, this will have to do.

Here's the implementation of Library.DataClass.ps1:

function Class

{

    param (

        [String] $name,

        [ScriptBlock] $memberScriptBlock

    )


 

    $class = New-Object System.CodeDom.CodeTypeDeclaration $name

    $class.TypeAttributes = [System.Reflection.TypeAttributes]::NotPublic

    $class.IsPartial = $true


 

    $constructor = New-Object System.CodeDom.CodeConstructor

    $constructor.Attributes = [System.CodeDom.MemberAttributes]::Public

    $class.Members.Add( $constructor ) | Out-Null

    

    $builderClass = New-Object System.CodeDom.CodeTypeDeclaration "Builder"

    $class.Members.Add( $builderClass ) | Out-Null


 

    $builderConstructor = New-Object System.CodeDom.CodeConstructor

    $builderConstructor.Attributes = [System.CodeDom.MemberAttributes]::Public

    $builderClass.Members.Add( $builderConstructor ) | Out-Null

    

    $builderConstructor2 = New-Object System.CodeDom.CodeConstructor

    $builderConstructor2.Attributes = [System.CodeDom.MemberAttributes]::Public

    $builderConstructor2.Parameters.Add(

        (New-Object System.CodeDom.CodeParameterDeclarationExpression( $name, "value" ))

    ) | Out-Null

    $builderClass.Members.Add( $builderConstructor2 ) | Out-Null

    

    $realizeMethod = New-Object System.CodeDom.CodeMemberMethod

    $realizeMethod.Attributes = [System.CodeDom.MemberAttributes]::Public

    $realizeMethod.Name = "To$name"

    $realizeMethod.ReturnType = $name


 

    $ctorExpression = New-Object System.CodeDom.CodeObjectCreateExpression

    $ctorExpression.CreateType = New-Object System.CodeDom.CodeTypeReference($name)

    $realizeMethod.Statements.Add(

        (New-Object System.CodeDom.CodeMethodReturnStatement(

            $ctorExpression

        ))

    ) | Out-Null

        

    $builderClass.Members.Add( $realizeMethod ) | Out-Null


 

    # return a hash of the CodeDom objects related to

    # this field

    function field

    {

        param (

            [Type] $type,

            [String] $name

        )

        

        @{

            type = $type

            name = $name

            readonlyFieldDeclaration = $(

# CodeDom doesn't support 'readonly' fields.

# See http://blogs.msdn.com/bclteam/archive/2005/03/16/396915.aspx

#                $field = New-Object System.CodeDom.CodeMemberField($type, $name)

#                $field.Attributes = [System.CodeDom.MemberAttributes]::Public

#                $field

                New-Object System.CodeDom.CodeSnippetTypeMember("`tpublic readonly $type $name;`n")

                )

            fieldDeclaration = $(

                $field = New-Object System.CodeDom.CodeMemberField($type, $name)

                $field.Attributes = [System.CodeDom.MemberAttributes]::Public

                $field

            )

            parameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

            fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

                (New-Object System.CodeDom.CodeThisReferenceExpression),

                $name

            )

            parameterReference = New-Object System.CodeDom.CodeVariableReferenceExpression $name

            setMethodName = "Set$name"

        }                

    }

    

    & $memberScriptBlock | foreach {

        $class.Members.Add( $_.readonlyFieldDeclaration )

        

        $constructor.Parameters.Add( $_.parameter )


 

        $constructor.Statements.Add(

            $(New-Object System.CodeDom.CodeAssignStatement( $_.fieldReference, $_.parameterReference ))

        )

        

        $builderConstructor2.Statements.Add(

            (New-Object System.CodeDom.CodeAssignStatement(

                $_.fieldReference,

                (New-Object System.CodeDom.CodeFieldReferenceExpression(

                    (New-Object System.CodeDom.CodeVariableReferenceExpression "value"),

                    $_.name

                ))

            ))

        )

        

        $builderClass.Members.Add( $_.fieldDeclaration ) | Out-Null

        $setMethod = New-Object System.CodeDom.CodeMemberMethod

        $setMethod.Name = $_.setMethodName


 

        $setMethod.ReturnType = $builderClass.Name

        # This should be Public,Final, but that fails for me. Possible PowerShell bug?

        $setMethod.Attributes = [System.CodeDom.MemberAttributes] "Public"

        $setMethod.Statements.Add(

            (New-Object System.CodeDom.CodeAssignStatement(

                $_.fieldReference,

                (New-Object System.CodeDom.CodeVariableReferenceExpression ("value"))

            ))

        )

        $setMethod.Statements.Add(

            (New-Object System.CodeDom.CodeMethodReturnStatement(

                (New-Object System.CodeDom.CodeThisReferenceExpression)

            ))

        )

        

        $setMethod.Parameters.Add(

            (New-Object System.CodeDom.CodeParameterDeclarationExpression( $_.type, "value" ))

        )

        $builderClass.Members.Add( $setMethod )

        

        $ctorExpression.Parameters.Add( $_.fieldReference )

        

    } | Out-Null    

    

    $csharpCodeProvider = New-Object Microsoft.CSharp.CSharpCodeProvider

    $sw = New-Object System.IO.StringWriter

    $codeGeneratorOptions = New-Object System.CodeDom.Compiler.CodeGeneratorOptions

    $codeGeneratorOptions.BracingStyle = "C"

    $codeGeneratorOptions.BlankLinesBetweenMembers = $false

    

    $csharpCodeProvider.GenerateCodeFromType( $class, $sw, $codeGeneratorOptions )

    

    $sw.ToString()

}

PowerShell DSLs: Using hashtables and scriptblocks together

Previously I presented the use of hashtables and scriptblocks as DSL input formats. You can also convert between them, with processing in between. I tried that out, and I think the result is interesting enough to post. Again, here is the input:

class MyClass {

    field ([string]) S

}

The previous code would use the 'field' function to manipulate the class object as appropriate:

    function field

    {

        param (

            [Type] $type,

            [String] $name

        )

        

        # add the field declaration

        $field = New-Object System.CodeDom.CodeMemberField($type, $name)

        $field.Attributes = [System.CodeDom.MemberAttributes]::Public

        $class.Members.Add( $field )

        

        # add the ctor parameter

        $ctorParameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

        $constructor.Parameters.Add($ctorParameter)


 

        # add the ctor initializer

        $fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

            (New-Object System.CodeDom.CodeThisReferenceExpression),

            $name

        )

        

        $ctorInitializer = New-Object System.CodeDom.CodeAssignStatement(

            $fieldReference,

            (New-Object System.CodeDom.CodeVariableReferenceExpression $name)

        )

        

        $constructor.Statements.Add( $ctorInitializer )

    }

    

    & $memberScriptBlock | Out-Null


 

But another idea is to have the 'field' function produce a collection of CodeDom objects that can be assembled later.

    # return a hash of the CodeDom objects related to

    # this field

    function field

    {

        param (

            [Type] $type,

            [String] $name

        )

        

        @{

            fieldDeclaration = $(

                $field = New-Object System.CodeDom.CodeMemberField($type, $name)

                $field.Attributes = [System.CodeDom.MemberAttributes]::Public

                $field

                )

            parameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

            fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

                (New-Object System.CodeDom.CodeThisReferenceExpression),

                $name

            )

            parameterReference = New-Object System.CodeDom.CodeVariableReferenceExpression $name

        }                

    }

    

    & $memberScriptBlock | foreach {

        $class.Members.Add( $_.fieldDeclaration )

        

        $constructor.Parameters.Add( $_.parameter )


 

        $constructor.Statements.Add(

            $(New-Object System.CodeDom.CodeAssignStatement( $_.fieldReference, $_.parameterReference ))

        )

    } | Out-Null

I suspect that the latter model is a little better because it separates concerns. Consider if I were to add other statements to my language, such as 'property'. The 'foreach' at the end could probably be written in a way that works for both fields and properties. However, the hashtable is slightly concerning, because it's not typed – if I get the key names wrong somewhere, I'm screwed.

I find that I'm spending quite a lot of time on this, but it's important that I find a way to create DSLs quickly. I figured that right now I'm just learning the techniques, and then if I master them, then I can do it more quickly when the time comes.

Friday, November 23, 2007

Immutable data class generator: Skeleton implementation

I've made a little progress on my PowerShell DSL for data classes, and figured it's a good time to show it off.

Here's the input format at this point:

class MyClass {

field ([string]) S

}

(I'm using the ScriptBlock approach.) I generally like the syntax, except for the need to add parentheses around the type. The alternative is to use a fully-qualified string:

class MyClass {

field System.String S

}

I'm not sure which is better, but I'm going with the first one for now, because it allows a more specific type than string.

The basis of the implementation is to write methods named 'class' and 'field'. 'class' is simple; here's an excerpt of the important bits:

$class = New-Object System.CodeDom.CodeTypeDeclaration $name

$class.TypeAttributes = [System.Reflection.TypeAttributes]::NotPublic

$class.IsPartial = $true

$constructor = New-Object System.CodeDom.CodeConstructor

$class.Members.Add( $constructor ) Out-Null

$class

The implementation of 'field' could go in several different ways. For now, I've written it to manipulate the class as appropriate, e.g.:

$field = New-Object System.CodeDom.CodeMemberField($type, $name)

$class.Members.Add( $field )


$ctorParameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

$constructor.Parameters.Add($ctorParameter)


$fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

(New-Object System.CodeDom.CodeThisReferenceExpression),

$name

)


$ctorInitializer = New-Object System.CodeDom.CodeAssignStatement(

$fieldReference,

(New-Object System.CodeDom.CodeVariableReferenceExpression $name)

)


$constructor.Statements.Add( $ctorInitializer )


(I'd like to attach the full script, but I don't see a way to do that in blogspot). It generates this output:

internal partial class MyClass

{

public string S;

private MyClass(string S)

{

this.S = S;

}

}



EDIT: See PowerShell DSLs: Using hashtables and scriptblocks together for a different view of this code.

Immutable data class generator

I'm working on a DSL implementation for defining "data classes" with certain properties in C# (see http://blogs.gotdotnet.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx for an example of the output).

Table of Contents

  1. Goals
  2. Skeleton implementation
  3. ???

PowerShell DSLs: Script block input

As an alternative to using a hashtable for input, you can use a script block. Here's a script-block-way of doing the same thing as before:

class MyClass -accessibilty:public {

member string S

}


and here's one of many ways of handling it

function class {

param (

[String] $name = $( throw
"name is required" ),

[String] $accessibilty,

[ScriptBlock] $memberScriptBlock = $( throw
"member script block is require" )

)


" $accessibilty class $name {"


& $memberScriptBlock % { " public $($_.declaration)" }


" }"

}


function member {

param (

[String] $type = $( throw
"type is required" ),

[String] $name = $( throw
"name is required" )

)


@{

declaration = "$type $name;"


}

}


What's happening here is that the first word on any line becomes a function, and the remaining words are parameters to that function. So, you're now creating an "internal DSL" in PowerShell. This lets you work in a more idoimatic PowerShell manner.


PowerShell DSLs: Hash table input

lassOne way to take PowerShell DSL input is in the form of a hash table. Taking from the Data Type with Builder example, you could write input as:

@{
kind = 'class'
name = 'MyClass'
accessibilty = 'public'
members = @{
type = 'string'
name = 'S'
}
}


How do you consume this input? Here's an example. (Note that the code generation side is not the focal point here -- the way that we interpet the input is what matters.)


if ($input.kind = 'class') {
" $($input.accessibilty) class $($input.name) {"

$input.members | foreach {
" public $($_.type) $($_.name);"
}

" }"

}


Which generates this output:


public class MyClass {
public System.String S;
}


This approach seems most effective when you need to express a lot of attributes on a single element. The downside is that the input seems a bit verbose and unnatural in some cases.

PowerShell DSLs

I've written before about my attraction to Domain-Specific Languages and my curiosity about using PowerShell to handle them, but I only recently got any time to think about it more. I'm working on a DSL implementation for defining "data classes" with certain properties in C# (see http://blogs.gotdotnet.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx#comments for an example).

I have only 3 examples of PowerShell DSLs to work from, and I don't see any guidance in this area, so I figured I'd write about what I find.

Table of Contents

  1. Prior art
  2. Why PowerShell?
  3. Custom invocation w/ a library
  4. DSL tool invocation
  5. Hash table input
  6. Script block input
  7. Using hashtables and scriptblocks together

Warning: technical content ahead

While working at Microsoft, I had a blog for work-related issues at blogs.msdn.com. Now I need a new place to write these things, so this blog will now include technical content, along with the food, politics, family, etc. that have come before.

Friday, November 09, 2007

Reid's Journal Entry: Making Apple Crisp

Today Reid made apple crisp. I wanted to know more about it, so I asked him some questions.

J: How many oranges did you use?
R: Zero oranges. It only takes apples and a few other ingredients, which are kind of like spices. Butter,

J: Oranges?
R: No... I mean, yes

J: What else?
R: Weeds. Then we milk and cereal. This is going to be so funny! Don't write that.

J: After you mixed it up, what did you do?
R: I baked it for 2000 hours. What zee doh.

J: How did it taste?
R: It's not ready for that part yet. We added 2000 drops of stevia in. Time for what it tasted like. It tasted like... stevia. Of course it would.

Friday, October 19, 2007

A new adventure

Today I announced broadly that I'm leaving Microsoft.

I sent 3 emails. Two went to the discussion groups of tools that I own, to announce the change of ownership of these tools. Strictly for business reasons, but then the news started flowing, and I was starting to get questions. So I sent out the third - to basically every person I've worked with in the last 11 years.

What's next?

I'm going to be a stay-at-home dad. The twins are 20 months old. Reid is 6. We want to homeschool Reid, and eventually the twins.

Living off savings will require that we spend a lot less. We currently live 1.9 miles from Microsoft campus, which is a damn expensive place to be. With me not working there, it doesn't make sense to live here, so we're moving away.

We've picked Port Townsend as our new home. It's such a cool city. 8000 people. 25mph speed limits. Hopefully we can bike & walk just about everywhere.

It's also a good choice because I love old, wooden boats, and PT has plenty of them. But that's for the future - right now, our attention will be on the family. Catching up on rest, taking good care of ourselves, being together.

I'm trying to leave Microsoft on good terms, and that includes trying to wrap things up on my current project so that it will succeed when I'm gone.

There's also a lot of work to do to get the house ready, purge our stuff some more, find a new home, pack, and move. Whew!

Thursday, September 06, 2007

Great music you haven't heard before: Mindless Self Induglence

Electronic punk. Real punk - they actually step outside of what's acceptable. Good for them.

They're starting to get known, it seems. I wonder how that will change them?

The track that got me was Panty Shot. Somehow this live verson is so much better than the studio recording.

Great music you haven't heard before: Emergency Broadcast Network

Here are some bits of music that I think are really great, but that aren't widely known. Maybe I'll do a few posts.

Emergency Broadcast Network

Industrial + electronica + video. I found these by accident. I was in the record shop, flipping through the industrial section, and picked out Telecommunication Breakdown because it had an interesting cover.

3:7:8 is particularly catchy.


Sunday, July 01, 2007

Tuesday, May 29, 2007

The difficulty of purging toys

My friend over at Confessions of a Hoarder talks about her difficulty decluttering kids' toys.

I have a hard, hard time dealing with toys, too.

I have been able to purge just about every group of things I call "mine": my hair, my computers, my motorcycles, my tools, my clothes, my books.

Once my wife got the bug, she started purging her stuff, too. That has been going well, and we work on it together.

One of the reasons I find toys difficult is that I'm making the decision for someone else. I know that, by getting rid of 1/2 of my books, I lose something (the opportunity to read that book at a moment's notice, the status symbol of books that define "me" to visitors) and gain something in return (space on the shelf, ease of managing my stuff, order in my home, money that I don't have to spend on more storage). I can decide if that trade-off is the right choice for me.

However, with the kids toys, I know that most of the gain is the parents' (for it is our feet that hurt when we step on a marble; we are the ones that separate the blocks, trains, wedgits, and legos) and most of the loss is kids' (they don't have access to a toy that they might enjoy).

What I remind myself of is how much the kids gain, too:

- Their parents are slightly less cranky.

- Their parents have more free time to spend with the kids, to cook nutritious meals, to take care of themselves so they can take care of the kids.

- Kids, too, like a clear, open space to engage in play.

- Clear, open spaces are particularly good for wrestling with Dad.

- Being able to clearly see a small number of toys works better than being surrounded by a plethora. It gives kids a chance to really focus their play in one area, and to not be overwhelmed when considering what play to do next.

- Kids play with non-toy things as often as toy things. Wooden spoons and sofa cushions are current favorites. Those items serve double-duty (yes, you can stir with a wooden spoon), thereby increasing their "density" in the home.

I've noticed recently that even the babies (16 months on Saturday) will often not think of playing with something until someone points it out to them. So, providing them with bucket upon bucket of toys won't really help them find fun. Having just 1 toy can meet their needs, if there's someone to help them get engaged.

In January I put a bunch of kids' toys in storage. It was a really good choice -- the kids haven't missed the toys, and life has been a bit easier since.

Saturday, May 26, 2007

Date Night



As parents of 3 small children, it's rare that Julie & I get to spend time together, just the two of us. Luckily for us, we found someone who was willing to babysit all 3, and we went out on a date.



We went for sushi.

As you can see, this is a happy thing.

Tuesday, May 15, 2007

How little do we really need?

Reading http://confessionsofahoarder.blogspot.com/2007/04/off-topic-guest-post-over-at-happy-jet.html got me thinking.

Every Thanksgiving my extended family rents a large house at the beach. There are usually about 16 people there, of which I contribute 5. For those 5, we only bring 2 suitcases, 2 backpacks, and carseats. There are only a few toys, unlike the hundreds of overflowing toys at home.

There are clearly some things missing, like clothes for the other weather, but still, we do very well with very little.

One important factor is the help we get. For example, with other adults around, we have time to keep up on laundry, washing every day, so we only need 3 days worth of clothes.

It's something we think about often when working on decluttering and pondering how much we really need for our happiness.

-Jay on a Pocket PC phone

Saturday, May 12, 2007

This just seen

It fills my heart with corporate pride.

-Jay on a Pocket PC phone

Board games on the computer

It's nice to sit down at a table to play a board game. You get some real human interaction that is missing from, say, television. But when it's time for dinner, you have to end the game. Or the peices get distributed -- under the sofa, behind the dresser, into a baby's digestive tract.

These problems go away when you play on a PC. No losing virtual chess peices. Go works well on the computer, too. Dominoes doesn't as well, since you can't hide your peices from your opponent, but having two PCs can do the trick.

But I'm still trying to figure how to get an online version of Twister.

Tuesday, May 01, 2007

How dumb do phishers think I am?

I just got a mail with this contents:

Dear Customer, jbasuki.

You are receiving this message, due to you protection, Our Online Technical Security Service Foreign IP Spy recently detected that your online account was recently logged on from am 88.30.167.175 without am International Access Code (I.A.C) and from an unregistered computer, which was not verified by the Our Online Service Department.

If you last logged in you online account on Thursday April 5th 2007, by the time 6:45 pm from an Foreign Ip their is no need for you to panic, but if you did log in your account on the above Date and Time, kindly take 2-3 minute of your online
banking experince to verify and register your computer now to avoid identity
theft, your protection is our future medal.


Verification Link
(removed)

Notice: You can acess your account from a foreign IP or
country by getting am (I.A.C) International Access Code, by contacting our local
brances close to you.

Do people really fall for such badd speling and gramer?

Thursday, April 26, 2007

Twins spin me around

My first youtube upload. The camera was upside-down, and I don't know how to flip the video. *sigh*.

Monday, April 16, 2007

Plant walk

On Sunday Reid & I went on a plant walk in Discovery Park. It turned out we were the only people who showed (besides the leader).


I met a lot of plants that I hope to meet again, including Stinging nettle, Plantain, and Horsetail. I'm pretty sure I've seen plantain around my neighboorhood; I am looking forward to finding it & adding it to my local snacking menu, which currently includes chickweed, dandelion, and blackberries.


I'd like to find something close to home that will make a tasty tea.

At the right is a snap of horsetail that I took.

Friday, March 09, 2007

mead bottling

When we drank mead in December, we decided that making a lot more was a good idea.

Bottling underway

Rinsing the bottles (so they're not sticky)


A full complement

A change in drinkware

The babies have broken a lot of glasses recently. Luckily they haven't gotten cut, but we still needed to find something to drink out of.


Goals:


- Sturdy, so babies can't break them easily

- 12-20oz seems like the right size

- fits comfortably in the dishwasher

- Not plastic, for reasons I described before.

- Cheap, ideally something that we can get used.


This turned out to be an easy one: we're using pint, regular-mouth mason jars. The meet all of the above, plus they can take a secure lid, so babies won't spill my pint of milk on the carpet.


I'm wondering how well they would work for tea and coffee, especially since you can get them with a handle. Will they cope with the thermal stress?


Storing leftovers

The babies are getting better at opening drawers and unloading the contents on to the floor. That means that all the things stored down low are now stacked on top of the things that are already stored up high. It's a mess.

The lowest drawer contained the plastic food storage containers. Even before the babies, this drawer was my nemesis - hard to keep organized, difficult to put things away, hard to get out what you need, and impossible to find a lid & container that match.

Now, those items are stored on a shelf that really didn't have the room to spare. (The picture on the right is the result of a dedicated organizing effort on that shelf; many of the items are either holding food in the fridge, or scattered around the house.) Frustrated by the chaos I can't control, I'm looking for something better.

Today I use mason jars for liquids (kombucha, milk, yogurt, kefir, and low-viscosity soups), as well as for fermentation, but they don't work well for, say, cheese. They're also a bit heavy and fragile for carrying in a backpack to a festival or something, and of course, they don't stack.

nesting. Nesting keeps things compact. You can often buy sets of plastic food storage containers that nest, but they only nest in one way. I want a set where each item nests in another of the same size & shape.

stacking lids. I need lids that have a sensible home, too. They should stack.

only a few sizes. Instead of a set of 20 items, each one of them different, I want only two or three sizes/shapes. This way it's easy to find a lid & a container that match, and I don't have to think very hard to select a container for the job. If I had two sizes, I'm guessing they'd need to be about one cup and one quart.

transparent. I want to be able to see what's inside without opening the lid.

durable with secure lid. Putting the container in my backpack shouldn't mean that everything else gets a taste of the contents. On a related note, removing the lid shouldn't be so hard that the contents go flying.

no sharp edges. I'm surprised I even have to write this, but my "disposable" Glad containers have rough edges, as a consequence of being made out of minimal materials.

glass or ceramic. I find that hand-washing plastic is hard - it never really feels clean. I am concerned about the chemical reactions between acidic foods and plastics, as well as the leeching of plastic compounds. I don't own a microwave, but I've heard concerns that microwaving in plastic can be dangerous, too.

Looking at my list, I don't think it's possible to find one item that can meet all of these needs. Right now, the best plan I can think of is a composite one:


  • Mason jars continue to do what they're doing today.


  • Keep a few of the plastic Tupperware-style containers for the backpack, in various sizes.


  • A set of glass 1c and 1qt containers with good lids, similar to:

    That's the best that I can come up with. What do you recommend?

 
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.