guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: reserved-keyword in macro


From: Damien Mattei
Subject: Re: reserved-keyword in macro
Date: Fri, 4 Feb 2022 17:24:54 +0100

even with $nfx$ it does not seem to be possible without set!-values:
https://docs.racket-lang.org/reference/set_.html#%28form._%28%28lib._racket%2Fprivate%2Fmore-scheme..rkt%29._set%21-values%29%29

does someone know how to implement set!-values in Scheme for Guile?

with set!-values things are really easy:
(define-syntax <+
  (syntax-rules ()

    ((_ (var1 ...) expr) (begin
  (define var1 '())
  ...
  (display "<+ multiple") (newline)
  (set!-values (var1 ...) expr)))
    ((_ var expr) (begin
   (display "<+ single") (newline)
   (define var expr)
   (display var) (newline)))))

Welcome to DrRacket, version 8.2 [cs].
Language: reader "../SRFI/SRFI-105.rkt", with debugging; memory limit: 128
MB.
> (define (foo) (values 1 2 3))
> {(x y z) <+ (foo)}
<+ multiple
> x
1
> y
2

(define-syntax </

  (syntax-rules ()

    ((</ (x ...) expr) (set!-values (x ...) expr))))

> (declare x y z)
> {(x y z) </ (foo)}
> x
1
> y
2
> z
3


On Fri, Feb 4, 2022 at 9:21 AM Damien Mattei <damien.mattei@gmail.com>
wrote:

> definitely i do not think it is possible to have a macro doing this:
> {(x y z) <- (foo)} ;; foo is a function that return 3 values (ex: (values
> 1 2 3))
> or this :
> {(x y z ...) <- (bar)} ;; bar return an arbitrary (known in advance )
> number of values
> and also have a compatibility with:
> {T[2] <- T[1]} that deal with arrays
>
> $bracket-apply$ and syntax-rules is not enough i think i will have to use
> $nfx$ overloading from SRFI-105 for doing almost the same:
> {x y z <- (foo)} which i admit is more Haskell style than Scheme
>
> On Thu, Feb 3, 2022 at 11:09 AM Damien Mattei <damien.mattei@gmail.com>
> wrote:
>
>> oh :-O yes it is the behavior expected : assign the 2nd element of an
>> array T with value 1 :
>> prefix notation of : (<- ($bracket-apply$ T 2) 1) is equivalent in Curly
>> Infix syntax to : {T[2] <- 1}
>> as expected when $bracket-apply$ is not bound we have the good result.
>> Thanks for this result.
>> Of course in this case  {T[2] <- 1} it is not a problem to have not 
>> $bracket-apply$
>> bound,
>> things became harder when doing : {T[2] <- T[4]} for example because then
>> i want to assign the result value of T[4] to T[2] and so i need to
>> evaluate T[4] before which is exactly
>> ($bracket-apply$ T 4) and at this point $bracket-apply$ is bind to:
>> (define-syntax $bracket-apply$
>>   (syntax-rules ()
>>
>>     ((_ container index)
>>      ;(begin ;;(display "$bracket-apply$") (newline)
>>      (cond ((vector? container) (vector-ref container index))
>>   ((hash-table? container) (hash-table-ref container index))
>>   (else (array-ref container index))));)
>>
>>     ((_ array index1 index2 ...)
>>      ;(begin ;;(display "$bracket-apply$") (newline)
>>      (if (vector? array)
>> (array-n-dim-ref array index1 index2 ...)
>> (array-ref array index1 index2 ...)))));)
>>
>> and is used in the RHS (right-hand side) of:
>> {T[2] <- T[4]} which expand in Curly Infix SRFI-105 to:
>> (<- ($bracket-apply$ T 2) ($bracket-apply$ T 4))
>> and then is expanded in Scheme+ in two phases:
>> first the RHS expr is evaluate in :
>> ((_ ($bracket-apply$ container index) expr)
>>      (let ((value expr)) ;; to avoid compute it twice
>> in : (array-ref T 4)
>> but the LHS (Left hand side) is not evaluated with $bracket-apply$ but
>> with the macro <-
>> in the body of let :
>> (cond ((vector? container) (vector-set! container index value))
>> which give :
>> (vector-set! T 2 value) where value is the value of expr, previously
>> expanded and evaluated.
>> And we get the good result.
>> But for this we need to have sometimes $bracket-apply$ as a bound macro
>> (or procedure) and sometimes not, being a reserved keyword NOT bound.
>> This for me obscure WHY the keyword in syntax-rules MUST not be bound to
>> behave correctly but this is like that in Scheme standarts and we have to
>> deal with.
>> I already faced this problem earlier and the solution is in the
>> previously commented code:
>>  ;; (if (equal? (quote $bracket-apply$) (quote funct-or-macro)) ;; test
>> funct-or-macro equal $bracket-apply$
>> which can only be understood knowing that the macro was in the past
>> declared like this and commented code does not match present code,here is
>> the previous definition of <- :
>> (syntax-rules ()
>>
>>     ;;  special form like : (<- ($bracket-apply$ T 3) ($bracket-apply$ T
>> 4))
>>
>>     ;; one dimension array, example: {a[4] <- 7}
>>     ;; $bracket-apply$ of SRFI 105
>>     ((_ (funct-or-macro container index) expr)
>>            (let ((value expr)) ;; to avoid compute it twice
>>
>>        ;; (if (equal? (quote $bracket-apply$) (quote funct-or-macro)) ;;
>> test funct-or-macro equal $bracket-apply$
>>
>>        ;; normal case
>>        ;; {T[2] <- 4}
>>        ;; {T[3] <- T[2]}
>>
>>        (cond ((vector? container) (vector-set! container index value))
>>                  ((hash-table? container) (hash-table-set! container
>> index value))
>>                  (else (array-set! container index value)))
>>        value))
>>
>> so the solution will be to remove $bracket-apply$ as literal in:
>> (define-syntax <-
>>   (syntax-rules ($bracket-apply$)
>>
>> and some check manually in the macro with:
>> (if (equal? (quote $bracket-apply$) (quote funct-or-macro)) ;; test
>> funct-or-macro equal $bracket-apply$
>> to branch instead of using pattern matching.
>> i will code this later but this was of great help,thanks again all.
>>
>> Damien
>>
>> On Thu, Feb 3, 2022 at 1:52 AM Vijay Marupudi <vijaymarupudi@gatech.edu>
>> wrote:
>>
>>> Hi Damien,
>>>
>>> I tried to run the code you provided. I ran
>>>
>>> -----------------------------------------------------------------
>>>
>>> (define-syntax <-
>>>   (syntax-rules ($bracket-apply$)
>>>     ((_ ($bracket-apply$ container index) expr)
>>>      (let ((value expr)) ;; to avoid compute it twice
>>>        (cond ((vector? container) (vector-set! container index value))
>>>              ((hash-table? container) (hash-table-set! container index
>>> value))
>>>              (else (array-set! container index value)));)
>>>        value))
>>>     ((_ ($bracket-apply$ array index1 index2 ...) expr)
>>>      (let ((value expr))
>>>        (if (vector? array)
>>>            (array-n-dim-set! array value index1 index2 ...)
>>>            (array-set! array index1 index2 ... value));)
>>>        (newline)
>>>        value))
>>>     ((_ (var ...) expr)
>>>      (begin
>>>        (display expr) (newline)
>>>        (let ((expr-list (call-with-values (lambda () expr) list)))
>>>          (assign-var (var ...) expr-list)
>>>          expr-list)))
>>>     ((_ var expr)
>>>      (begin
>>>        (set! var expr)
>>>        var))
>>>     ((_ var var1 var2 ...)
>>>      (<- var (<- var1 var2 ...)))))
>>>
>>> (define T (make-vector 5))
>>> (<- ($bracket-apply$ T 2) 1)
>>>
>>> -----------------------------------------------------------------
>>>
>>> After I ran that, T was
>>>
>>> #(#<unspecified> #<unspecified> 1 #<unspecified> #<unspecified>)
>>>
>>> Is that was you are looking for?
>>>
>>> > "A literal matches an input expression if the input expression is an
>>> > identifier with the same name as the literal, and both are unbound13
>>> > <
>>> https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html#FOOT13
>>> >.
>>> > " as $bracket-apply$ is already bind to a definition the pattern will
>>> > not be matched:
>>>
>>> It's possible, as in my case, I did not have it bound, and it seems to
>>> have worked the way you expected?
>>>
>>> ~ Vijay
>>>
>>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]