I saw your pull request adding the warning, thank you very much, that
should ease the things a lot.  I have added the #7424 into my RSS reader
and am looking forward to it getting merged.

Ludovic Courtès <[email protected]> writes:

> Tomas Volf <[email protected]> skribis:
>
>> Incidentally, I completely forgot that this-packages is a thing (I never
>> managed to use it correctly, I usually end up in infinite loops).  But
>> that gives me an idea.  What about:
>>
>>     (let ((services (modify-services ...)))
>>       (operating-system
>>         (inherit %base-os)
>>         (services this-operating-system-services)))
>>
>>     (package
>>       (inherit foo)
>>       (inputs (modify-inputs this-package-inputs ...)))
>>
>> ?
>
> And where would the identifier ‘this-package-inputs’ come from?
>
> There’s an important property of macros referred to as “hygiene” (a
> proper name would be “referential transparency”).  One aspect of it is
> that any binding that is introduced must appear in the source.  For
> example, ‘this-package’ appears as an argument to ‘define-record-type*’.
> Hence my question.

Well, I assumed it could be done using datum->syntax, by putting
together this-package (or whatever user configured) with name of the
current field.  But if that would be problem for some reason, you could
always just do

    (define-record-type* <package>
      package make-package
      package?
      this-package
      ...
      (inputs package-inputs
              (default '())
              (thunked this-package-inputs)   ; <-- HERE
              (sanitize sanitize-inputs))
      ...)

>
> (There’s a way to break this hygiene rule (‘define-configuration’ does
> that), but it’s fraught with peril.)
>
> Besides, one might be tempted to think that:
>
>   this-package-inputs = (package-inputs this-package)
>
> … which would not be the case.

Wait, it is not?  Ugh, my head starts to hurt a little. :)

  (package (inherit %base)
    (inputs (package-inputs %base)))

  (package (inherit %base)
    (inputs (package-inputs this-package)))

  (package (inherit %base)
    (inputs inputs))

What is a difference between these three?  Up till now I have assumed
all three produce identical resulting package.

(Sorry to keep up with the constant questions, if there is recommended
reading instead, I will gladly do that instead, but records are not
documented at all last time I checked.  And reading records.scm gave me
a headache instead of knowledge. :/  The code is far outside my skill
level.)

>
> Ludo’.
>
> PS: Instead of introducing a new binding, my initial implementation used
>     a global syntax parameter, ‘inherited-value’, which would only be
>     valid within the body of an inherited thunked field.  Good thing: no
>     shadowing.  Bad thing: every user of a record type would have to
>     import (guix records) to access ‘inherited-value’—a showstopper.
>

To a degree, I assume that could have been done as:

    (define-record-type* <package>
      package make-package
      package?
      this-package
      inherited-value   ; <-- HERE

and then let-bind it in every thunked field?  If it is possible for
this-package, it should work for inherited-value as well I assume.  This
would still have the benefit that it would be exactly one extra binding
to worry regarding shadowing.

-- 
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.

Reply via email to