s c h e m a t i c s : c o o k b o o k

/ Cookbook.MatchingStructFieldsByName

This Web


WebHome 
WebChanges 
TOC (with recipes)
NewRecipe 
WebTopicList 
WebStatistics 

Other Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Schematics


Schematics Home
Sourceforge Page
SchemeWiki.org
Original Cookbook
RSS

Scheme Links


Schemers.org
Scheme FAQ
R5RS
SRFIs
Scheme Cross Reference
PLT Scheme SISC
Scheme48 SCM
MIT Scheme scsh
JScheme Kawa
Chicken Guile
Bigloo Tiny
Gambit LispMe
GaucheChez

Lambda the Ultimate
TWiki.org

How to Match Struct Fields by Name

Problem

Both pattern-matching libraries in PLT Scheme allow you to match against fields of a structure, but they only do so by position, as in the following example, in which baz is bound to the first field and bar to the second, despite the fact that the names are reversed:

(require (lib "plt-match.ss"))
(define-struct foo (bar baz))
(match (make-foo 3 4)
  [(struct foo (baz bar)) bar])

Matching by position has two disadvantages. First, it's sensitive to the order of the fields within the structure definition, and second, it requires you to include a pattern (even if it's only _) for each field in the structure, even if you only care about one of them (as above).

Sometimes it would be convenient to match and decompose a structure by field name, rather than field order.

Solution

We can do this in plt-match.ss, using a combination of the (? exp pat ...) and (app exp pat) patterns. Unfortunately, these aren't documented very thoroughly on the plt-match.ss page.

The following function demonstrates how to use these together to match by field name:

;; tested in PLT Scheme 300.3
(require (lib "plt-match.ss"))

(define-struct expr (srcloc))
(define-struct (id expr) (name))
(define-struct (lam expr) (arg body))
(define-struct (app expr) (rator rand))

;; incomplete evaluator
(define (eval e r)  ;; expr, environment (as alist)
  (match e
    [(? id? (app id-name name)) 
     (cdr (assq name r))]
    [(? app? (app app-rand rand)
             (app app-rator (? lam? (app lam-arg arg)
                                    (app lam-body body))))
     (eval body (cons (cons arg rand) r))]))

This is part of an evaluator (as opposed to a partial evaluator!) for a simple expression language. The AST nodes contain a srcloc field for source location information to use in error messages, but the evaluator doesn't care about this.

The first match clause checks to see if e is an id, applies the id-name selector to it, and binds the result to name. Note that we have to check id? explicitly; otherwise, id-name will signal an error if e is an app.

The second match clause checks to see if e is an app. If it is, it extracts its rand field with app-rand and its rator field with app-rator. The rator field is then matched against a nested pattern that deconstructs the lam value, again by name rather than by position.

Neither match clause has to do anything with the srcloc field, despite it being the first field in all three structures. Also, the second clause matches the fields of the app structure out of order, just to show that this is possible.

Discussion

As far as I can tell, this is not possible with the match.ss library, as it doesn't have an equivalent to the (app exp pat) pattern form.

The syntax above is quite verbose and convoluted. It'd be wonderful if someone could write a match-expander or a macro to clean this up, but my macro-fu and match-fu are, sadly, not sufficient to the task.


Two follow-ups:

  1. This idiom is indeed possible with the match.ss library, but instead of writing (app exp pat), one writes ( = exp pat). (Forgive the space in front of the equals sign; it's required by the wiki's markup language.)
  2. I have learned enough macro-fu and match-fu to write a library to clean this idiom up. See the views.plt package in PLaneT: http://planet.plt-scheme.org/300/#views.plt (for PLT Scheme v350 and later only).

-- RichardCobbe - 03 Nov 2006


Comments about this recipe

Contributors

-- RichardCobbe - 01 Jan 2006

CookbookForm
TopicType: Recipe
ParentTopic: PatternMatchingRecipes
TopicOrder:

 
 
Copyright © 2004 by the contributing authors. All material on the Schematics Cookbook web site is the property of the contributing authors.
The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.
Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest