Type conversion in accessors?
Posted: Thu Aug 11, 2011 8:31 pm
I'm struggling a little bit with figuring out what the lispy way to handle a problem with accessor type-conversion, and am hoping someone can point me in the right direction.
I'm parsing a stream of delimited strings. The protocol specifies that the first string is an integer value indicating the type of the message, followed by some arbitrary number of delimited strings (determined by the message type.)
A message might be defined as:
And on the wire, the stream (shown with 2 messages of TYPE:1) would look like:
I've modeled the various structures that can be received on the wire, however different messages may populate different fields in a structure. Currently, I've got a bunch of ugly code that does string processing and type conversion as the stream is parsed, but this is ugly and cumbersome. I'd much prefer to put the type conversion around the slots of the class and do the conversion when setting the value. Unfortunately I'm having a hard time figuring out exactly how to make this happen.
In a nutshell, instead of having code that does something like:
I'd prefer to say:
I'm feeling like there may be a way to do this with slot accessors and :before or :around methods, but am not seeing the path clearly (and could certainly be off in the weeds.)
Any pointers here are appreciated.
**Edit**
As a follow-up, I realize I can use (read-from-string) to get automatic conversion for many cases, but there is some strange behavior in the system that requires special handling. For instance, some messages have boolean fields where NULL=false and *anything*=true, while other messages have boolean fields where 0=false and *anything-else*=true, while yet others have 1=true, and *anything-else*=false.
Yes, bask in the horribleness, but that's what I'm stuck with.
I'm parsing a stream of delimited strings. The protocol specifies that the first string is an integer value indicating the type of the message, followed by some arbitrary number of delimited strings (determined by the message type.)
A message might be defined as:
Code: Select all
MESSAGE_TYPE: 1 (LOCATION-OVERVIEW)
string: name
integer: location-id
double: resource-rating
Code: Select all
1@Haymarket@[email protected]@1@Joliet@[email protected]@...
In a nutshell, instead of having code that does something like:
Code: Select all
(let ((token (parse-next-token my-stream))
(setf (slot-value obj 'resource-rating) (read-from-string token))))
Code: Select all
(let ((token (parse-next-token my-stream))
(setf (slot-value obj 'resource-rating) token))
Any pointers here are appreciated.
**Edit**
As a follow-up, I realize I can use (read-from-string) to get automatic conversion for many cases, but there is some strange behavior in the system that requires special handling. For instance, some messages have boolean fields where NULL=false and *anything*=true, while other messages have boolean fields where 0=false and *anything-else*=true, while yet others have 1=true, and *anything-else*=false.
Yes, bask in the horribleness, but that's what I'm stuck with.