[racket] Functional Updates for Structs

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Tue Aug 27 14:01:42 EDT 2013

Here is a solution: 

1. define a macro that defines structs with additional capabilities, e.g., functional updaters 

2. replace field-name with output-type and then use the extended capability to retrieve the appropriate functionality on the fly 

But as I am typing this, I am beginning to think that you really want objects not structs for your task. So perhaps the real trick is to use objects and methods because then you can exploit dynamic dispatch to get the desired functionality. Here is a sketch that is NOT working code: 

   (my-kind-of-struct name (field1 ...))
   ... (define name% (class (init-field field1 ...) (define/public (name-field1 x) field1) ... (define/public (set-name-field1 new-x) (new name% [field1 new-x][field2 field2] ...)) ...) ...)

Your macro can now expand to just 

 (send unknown-object set-name-fieldN ...) 

and you don't need to know the struct type. I bet that this will work more easily than structs plus other macrology. 

-- Matthias

On Aug 27, 2013, at 11:33 AM, Danny Gratzer <danny.gratzer at gmail.com> wrote:

> It's part of a DSL I'm writing, the idea being a user gives an accessor to some struct, a function to transform the accessed data, an updater to store the transformed data into another struct. I've nicknamed these source, pipe, and sink procedures respectively.
> The end goal is a DSL that looks like
>     (create-trans
>         (wire source through pipe into sink) ...)
> The context for this is robotics programming where source and sink structs model input and the robot respectively. If anyone's familiar with LabView, it's not entirely dissimilar. 
> I'm trying to make the DSL pleasant to use by avoiding mentioning anything about type or field names, just accessors and updaters. So I have no trouble extracting the needed data, but I there aren't any nice functional updaters generated. I could write something like
>     (create-trans output-type
>        (wire source through pipe into field-name) ...)
> which isn't too bad, but it's a bit asymmetric: source can be some arbitrarily complex function but field-name is very limited. Probably I should just suck it up and accept a bit of ugliness. 

Posted on the users mailing list.