On Wed, Dec 6, 2017 at 11:23 PM, Philip McGrath
<phi...@philipmcgrath.com> wrote:
>> 1) At least one of the fields must be set at creation
> What does it mean for one of the fields not to be set at creation? Is there
> implicitly some not-initialized value like #f that is also valid for the
> constructor? Do you want your accessor functions to raise an error if
> someone tries to access a non-initialized field?

Our system pushes chunks of data around.  A chunk is a small file on
disk that lives in the '.chunks/' directory.  If it's being actively
worked with then it gets copied to the '.scratch/' directory.  This
struct tracks where the file currently exists; you wouldn't create one
of these if the chunk isn't on disk (there are other mechanisms for
that), so at least one and possibly both of the paths must be set.

Yes, the fields will default to #f, although throwing an exception on
access is also an option.

>> 3) Both fields will return string? when accessed, as that makes it
>> easier to insert into the DB when the time comes.
> As you may know, the reference warns that "some paths may not be
> representable as strings" and that "decoding and re-encoding the path’s byte
> string [to a string] may lose information". You may be able to ignore this
> in your particular circumstances, but you might consider using the
> byte-string representation of paths (which doesn't have this problem), or
> this might be an argument in favor of multiple accessor functions/methods
> which convert to different formats.
> More broadly, what is the meaning of mutating one of the fields of your
> struct? Is there a compelling reason not to use an immutable struct and
> functional update?

Good question, I should have provided the context originally.  Sorry for that.

Mutating the fields would usually happen when a chunk gets copied to
the scratchdir to be worked with, deleted from the scratchdir when
you're done with it, or moved to the chunksdir if it's finished being
assembled.  There's no reason not to use functional update, but I
haven't seen a straightforward way to do that since there is no
'set-db-chunk-foo' as opposed to 'set-db-chunk-foo!'.   I guess I need
to use 'struct-copy'?  At that point it seems more sensible to have a
small module pertaining solely to managing chunk information that uses
a hash for a backing store, since hashes are easier to work with.  Or
go full OO and create an object that tracks it for me.

>> (let ([old-mut set-db-chunk-scratchdir-path!])
>>   (set! set-db-chunk-scratchdir-path!
>>       (lambda (chnk val)
>>         (old-mut chnk (if (path? val) (path->string val) val))))))
> Regardless of anything else, I would definitely not do this. To me, this
> would "work against the idea of functional programming" far more than using
> a class. (Also, I have the impression that mutating a module-level variable
> can have performance implications.)

Oh, absolutely.  This is krunky as heck and when I found myself
considering it is when I realized I needed to back away from the
keyboard and ask the list for the right way to do it.

> If I wanted to use a mutable struct with the sorts of wrappers you describe,
> I would write a module with the struct definition and the wrapper functions
> and export only the interface with guards, perhaps using rename-out (or the
> rename option with contract-out) to give the wrappers nice external names. I
> will sometimes even use a submodule for the purpose of packaging up an
> abstraction and giving only a high-level interface to surrounding code.
> Alternatively, using a class could be a valid choice, but I would probably
> only consider that if you have other code that uses racket/class: it seems
> like a fairly large set of concepts to add just for this. I have come to
> appreciate racket/class in the right circumstances, especially for
> representing stateful objects or lots of variants with slight variations in
> method behavior. I don't think there's anything inherently un-functional
> about classes (and I'd say an immutable object is more functional than a
> mutable struct).

Good advice, thanks.

You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to