Hi Mark! Mark H Weaver <m...@netris.org> skribis:
> l...@gnu.org (Ludovic Courtès) writes: >> Mark H Weaver <m...@netris.org> skribis: >>> The public interface I've created is quite a bit different than what >>> we've been discussing so far. I'm open to changing it, but here's what >>> the attached patch currently exports from (srfi srfi-9 gnu): >>> >>> (modified-copy <struct-expr> (<field-path> <expr>) ...) >>> (modified-copy-nocheck <struct-expr> (<field-path> <expr>) ...) >>> >>> where <field-path> is of the form (<field> ...) >> >> I’d still want named single-field setters, for convenience. For that, >> we probably still need a separate ‘define-immutable-record-type’. > > Agreed. Cool! Could you integrate it somehow, along with the tests I provided? >> Also, I’d want to avoid the term ‘copy’, which is sounds low-level; >> ‘set’ seems more appropriate to me. WDYT? > > I agree that 'copy' is not a good term to use here, especially since no > copy is made in the zero-modification case of (modified-copy s). > > However, I find the term 'set' misleading, since no mutation is taking > place. Maybe 'update'? I dunno, I don't have strong feelings on this. I don’t find ‘set’ misleading because there’s no exclamation mark, and because it’s conceptually about setting a field’s value. WDYT? >> Regarding the interface for multi-field nested changes, I’d still >> prefer: >> >> (set-field p (foo bar) val >> (foo baz) chbouib) >> >> Or is it less readable than: >> >> (set-field p ((foo bar) val) >> ((foo baz) chbouib)) > > I find the first variant to be very un-scheme-like. Yes; in hindsight, I have the same feeling. >> Finally, I think there’s shouldn’t be a ‘-nocheck’ version. Dynamic >> typing entails run-time type checking, that’s a fact of life, but safety >> shouldn’t have to be traded for performance. > > Hmm. I agree that the 'nocheck' variant should not be prominently > mentioned, and perhaps not documented at all, but I suspect it will > prove useful to keep it around, even if only for our own internal use to > build efficient higher-level constructs. > > For example, when I built this 'modified-copy' machinery, I was unable > to build upon the usual (<getter> s) syntax, because that would cause > the generated code to include many redundant checks (one for each field > retrieved). Would these checks be alleviated by Andy’s work on peval “predicates”? > For example, for (modified-copy s ((foo-x) 'new)) where 's' contains 10 > fields, the expanded code would include 9 separate checks that 's' is > the right type. Couldn’t ‘modified-copy’ be implemented differently so that there’s only one check? That seems like the most obvious (not necessarily the easiest) way to address the problem. Every time ‘car’ is used, there’s a type-check that users cannot eliminate. IMO, if it were to be eliminated, it should be via orthogonal means, not via the API: for instance, when the compiler knows the check would always pass at run-time, or with (declare (unsafe)), or with ‘-DSCM_RECKLESS’. A ‘car-nocheck’ wouldn’t be convenient, would it? :-) [...] >> and more importantly coordinate so we don’t waste time working on the >> same code in parallel. > > I started this work after you were (probably) asleep, When I don’t sleep, I also have a daytime work, and a family, among other things, which is why I am not this responsive. Also, I was assuming I was holding a mutex on this, so-to-speak. Lastly, I check email less frequently when I have a hack on my mind. :-) > and rushed to post about it before you woke up, so I did my best > there. If you would prefer to use your own code instead, that's okay > with me. As long as we end up with a functional-multi-setter that > generates good code, I'll be satisfied. Yeah, me too. So I’m happy we’re getting close to an even better solution! >> FWIW I was using this approach to represent the tree of accessors: >> >> (define (field-tree fields) >> ;; Given FIELDS, a list of field-accessor-lists, return a tree >> ;; that groups together FIELDS by prefix. Example: >> ;; FIELDS: ((f1 f2 f3) (f1 f4)) >> ;; RESULT: ((f1 (f2 (f3)) (f4))) >> (define (insert obj tree) >> (match obj >> ((head tail ...) >> (let ((sub (or (assoc-ref tree head) '()))) >> (cons (cons head (insert tail sub)) >> (alist-delete head tree)))) >> (() >> tree))) >> >> (fold-right insert '() fields)) > > I agree that this is much nicer than my corresponding code. Thanks for > sharing. Would you like me to incorporate something like this into my > code, or would you like to start with your code and maybe cherry-pick > ideas/code from mine? Either way is fine with me. I’ll let you see whether/how you can borrow from this in your code, if that’s fine with you. Thanks, Ludo’.