unofficial mirror of help-guix@gnu.org 
 help / color / mirror / Atom feed
* How to lower a record to the build code ?
@ 2021-05-05 16:58 edk
  2021-05-05 18:18 ` Christopher Baines
  0 siblings, 1 reply; 3+ messages in thread
From: edk @ 2021-05-05 16:58 UTC (permalink / raw)
  To: help-guix

Hi,

I've been stuck for a few days on the following:
Let's say I have a record type:

(define-record-type* <my-record> my-record make-my-record
  my-record?
  this-record
 (first-field my-record-first-field)
 (second-field my-record-second-field))

And a function that uses such a record, but needs to run on the build
side, because it also needs the store path of a package (I can't edit
this function):

(define (function-of-a-record-and-a-build-time-path rec path)
  "Concatenate the path, first, and second field"
  (string-append path " " (my-record-first-field rec) " " (car
  (my-record-second-field rec)) " " (cdr (my-record-second-field rec))))

How can I use this record in the build side. For example, I'm unable to
build the following G-exp:
(define a-record (my-record
              (first-field "first")
              (second-field '("second" . "third"))))


#~(with-output-to-file (string-append #$output "/file.txt")
     (lambda _
       (display (function-of-a-record-and-a-build-time-path #$a-record
     #$bash)))))

I expect the gexp to compile to a file in the store whose contents are
/gnu/store/....bash/ first second third

The error is   1. &gexp-input-error: #<<my-record> first-field: "first"
second-field: ("second" . "third")>

I tried to define a gexp-compiler, but I have clearly no idea of what
I'm doing and I could sometimes make it work if I convert the record
into a list, but not if there is a list within that list.

I've read the relevant sections of the manual, and the code, and
basically all instances of a call to define-gexp-compiler in the source
code, but nothing comes close to what I need.

I really could use some help,

Thank you very much,

Edouard.

P.S. here is a minimal not-working example that you can copy paste in
guix repl in order to reproduce my problem:


(use-modules
 (guix gexp)
 (guix store)
 (guix derivations)
 (guix records)
 (guix monads)
 (gnu packages bash))
(define (build-gexp gexp)
  "Build GEXP using the local daemon."
  (let ((derivation
         (run-with-store (open-connection)
           (gexp->derivation
            "noname"
            gexp))))
    (build-derivations
     (open-connection)
     (list derivation))
    (derivation-output-path (assoc-ref (derivation-outputs derivation) "out"))))
;; There is a record type that I need on the build side
(define-record-type* <my-record> my-record make-my-record
  my-record?
  this-record
 (first-field my-record-first-field)
 (second-field my-record-second-field))
(define a-record (my-record
              (first-field "first")
              (second-field '("second" . "third"))))
(define (function-of-a-record-and-a-build-time-path rec path)
  "Concatenate the path, first, and second field"
  (string-append path " " (my-record-first-field rec) " " (car (my-record-second-field rec)) " " (cdr (my-record-second-field rec))))

;;   1. &gexp-input-error: #<<my-record> first-field: "first" second-field: ("second" . "third")>
(build-gexp
 #~(with-output-to-file (string-append #$output "/file.txt")
     (lambda _
       (display (function-of-a-record-and-a-build-time-path #$a-record #$bash)))))


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to lower a record to the build code ?
  2021-05-05 16:58 How to lower a record to the build code ? edk
@ 2021-05-05 18:18 ` Christopher Baines
  2021-05-07 16:21   ` Edouard Klein
  0 siblings, 1 reply; 3+ messages in thread
From: Christopher Baines @ 2021-05-05 18:18 UTC (permalink / raw)
  To: edk; +Cc: help-guix

[-- Attachment #1: Type: text/plain, Size: 2386 bytes --]


edk@beaver-labs.com writes:

> I've been stuck for a few days on the following:
> Let's say I have a record type:
>
> (define-record-type* <my-record> my-record make-my-record
>   my-record?
>   this-record
>  (first-field my-record-first-field)
>  (second-field my-record-second-field))
>
> And a function that uses such a record, but needs to run on the build
> side, because it also needs the store path of a package (I can't edit
> this function):
>
> (define (function-of-a-record-and-a-build-time-path rec path)
>   "Concatenate the path, first, and second field"
>   (string-append path " " (my-record-first-field rec) " " (car
>   (my-record-second-field rec)) " " (cdr (my-record-second-field rec))))
>
> How can I use this record in the build side. For example, I'm unable to
> build the following G-exp:
> (define a-record (my-record
>               (first-field "first")
>               (second-field '("second" . "third"))))
>
>
> #~(with-output-to-file (string-append #$output "/file.txt")
>      (lambda _
>        (display (function-of-a-record-and-a-build-time-path #$a-record
>      #$bash)))))

Could you ungexp the record access bits? So something like:

  (string-append #$path " " #$(my-record-first-field rec) " " #$(car
    (my-record-second-field rec)) " " #$(cdr (my-record-second-field
    rec)))

Obviously, then the handling of rec would just be on the build side.

I'm not quite sure quite what your code looks like, in the example you
give, you've got a number of problems.

Ignoring the #$a-record, you'll need to (mkdir #$output) before trying
to write to a file within that directory.

Secondly, function-of-a-record-and-a-build-time-path isn't defined on
the build side.

If you want to define function-of-a-record-and-a-build-time-path on the
host side, then you could have it return a gexp, something like:

  (define (function-of-a-record-and-a-build-time-path rec path)
    "Concatenate the path, first, and second field"
    #~(string-append #$path " " #$(my-record-first-field rec) " " #$(car (my-record-second-field rec)) " " #$(cdr (my-record-second-field rec))))

  (build-gexp
   #~(begin
       (mkdir #$output)
       (with-output-to-file (string-append #$output "/file.txt")
         (lambda _
           (display #$(function-of-a-record-and-a-build-time-path  a-record bash))))))

With these changes, the example you give works for me.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 987 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to lower a record to the build code ?
  2021-05-05 18:18 ` Christopher Baines
@ 2021-05-07 16:21   ` Edouard Klein
  0 siblings, 0 replies; 3+ messages in thread
From: Edouard Klein @ 2021-05-07 16:21 UTC (permalink / raw)
  To: Christopher Baines; +Cc: help-guix

Dear Christopher,

I can't thank you enough, your idea of "ungexp[ing] the record access
bits" is what got me out of the tarpit.

You can see the resulting code here, which will hopefully clear the
misunderstandings generated by my oversimplification of the minimal
nonworking example:
https://issues.guix.gnu.org/issue/48277

Thanks again !

Cheers,

Edouard.


Christopher Baines writes:

> edk@beaver-labs.com writes:
>
>> I've been stuck for a few days on the following:
>> Let's say I have a record type:
>>
>> (define-record-type* <my-record> my-record make-my-record
>>   my-record?
>>   this-record
>>  (first-field my-record-first-field)
>>  (second-field my-record-second-field))
>>
>> And a function that uses such a record, but needs to run on the build
>> side, because it also needs the store path of a package (I can't edit
>> this function):
>>
>> (define (function-of-a-record-and-a-build-time-path rec path)
>>   "Concatenate the path, first, and second field"
>>   (string-append path " " (my-record-first-field rec) " " (car
>>   (my-record-second-field rec)) " " (cdr (my-record-second-field rec))))
>>
>> How can I use this record in the build side. For example, I'm unable to
>> build the following G-exp:
>> (define a-record (my-record
>>               (first-field "first")
>>               (second-field '("second" . "third"))))
>>
>>
>> #~(with-output-to-file (string-append #$output "/file.txt")
>>      (lambda _
>>        (display (function-of-a-record-and-a-build-time-path #$a-record
>>      #$bash)))))
>
> Could you ungexp the record access bits? So something like:
>
>   (string-append #$path " " #$(my-record-first-field rec) " " #$(car
>     (my-record-second-field rec)) " " #$(cdr (my-record-second-field
>     rec)))
>
> Obviously, then the handling of rec would just be on the build side.
>
> I'm not quite sure quite what your code looks like, in the example you
> give, you've got a number of problems.
>
> Ignoring the #$a-record, you'll need to (mkdir #$output) before trying
> to write to a file within that directory.
>
> Secondly, function-of-a-record-and-a-build-time-path isn't defined on
> the build side.
>
> If you want to define function-of-a-record-and-a-build-time-path on the
> host side, then you could have it return a gexp, something like:
>
>   (define (function-of-a-record-and-a-build-time-path rec path)
>     "Concatenate the path, first, and second field"
>     #~(string-append #$path " " #$(my-record-first-field rec) " " #$(car (my-record-second-field rec)) " " #$(cdr (my-record-second-field rec))))
>
>   (build-gexp
>    #~(begin
>        (mkdir #$output)
>        (with-output-to-file (string-append #$output "/file.txt")
>          (lambda _
>            (display #$(function-of-a-record-and-a-build-time-path  a-record bash))))))
>
> With these changes, the example you give works for me.



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-05-07 16:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-05 16:58 How to lower a record to the build code ? edk
2021-05-05 18:18 ` Christopher Baines
2021-05-07 16:21   ` Edouard Klein

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).