Re: [pollen] "cannot reference undefined identifier" when using eval in Pollen

2016-07-20 Thread Joel Dueck
On Wednesday, July 20, 2016 at 1:56:02 AM UTC-5, Matthew Butterick wrote:
>
>
> The problem is with 'POLY-FUNCS in the macro template. When you put the 
> quote mark on the front, then everything inside POLY-FUNCS gets treated as 
> a symbol. But in fact, you only want the target name to behave as a symbol, 
> and you want your new function-name identifier to behave as a variable 
> (that refers to your imported function). 
>
> The solution is to match the target and function separately in your 
> `with-syntax` pattern, and then only put the quote mark on the first one 
> (once this problem is fixed, notice that the `eval` becomes unnecessary; 
> notice also the use of the `...` matching operator so we can handle the new 
> syntax bits in the template one at a time, rather than all at once):
>
>
This is a big help for my understanding of macros, thanks. I felt that eval 
was a bit of a hack, but I had not understood that with-syntax could use 
`...` to produce repeating patterns that aren't tied to the syntax pattern 
passed in by `syntax-parse`. I guess I might have been able to infer this 
from Hendershott's explanation 

 
that `with-syntax` can be considered as simply a rearranged `syntax-case`.

I'm still curious as to why one can't `eval` a symbol matching the name of 
a function in a Pollen file though, even when that function is defined in 
the same file. I will probably never absolutely need to use it that way, 
but it runs counter to my understanding of Pollen files as full-fledged 
Racket programs.

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


Re: [pollen] "cannot reference undefined identifier" when using eval in Pollen

2016-07-20 Thread Matthew Butterick

On Jul 19, 2016, at 9:42 PM, Joel Dueck  wrote:
> 
> So to that end I wrote the poly-branch-tag macro, a simplified version of 
> which is here:
> 
> (define-for-syntax site-poly-targets '(pdf html))
> 
> (define-syntax (poly-branch-tag stx)
>   (syntax-parse stx
> [(_ TAG:id)
>  (with-syntax ([POLY-FUNCS (for/list ([target (in-list 
> site-poly-targets)])
>  (list target (format-id stx "~a-~a" 
> target #'TAG)))])
>#'(define-tag-function (TAG attributes elems)
>(define poly-func (second (assq (current-poly-target) 
> 'POLY-FUNCS)))
>((eval poly-func) attributes elems)))]))

The problem is with 'POLY-FUNCS in the macro template. When you put the quote 
mark on the front, then everything inside POLY-FUNCS gets treated as a symbol. 
But in fact, you only want the target name to behave as a symbol, and you want 
your new function-name identifier to behave as a variable (that refers to your 
imported function). 

The solution is to match the target and function separately in your 
`with-syntax` pattern, and then only put the quote mark on the first one (once 
this problem is fixed, notice that the `eval` becomes unnecessary; notice also 
the use of the `...` matching operator so we can handle the new syntax bits in 
the template one at a time, rather than all at once):


#lang racket
(require rackunit (for-syntax syntax/parse racket/syntax) pollen/tag 
pollen/setup)

(define (html-bold . xs) "this is html-bold")
(define (pdf-bold . xs) "this is pdf-bold")

(define-for-syntax site-poly-targets '(pdf html))

(define-syntax (poly-branch-tag stx)
  (syntax-parse stx
[(_ TAG:id)
 (with-syntax ([((POLY-TARGET POLY-FUNC) ...) (for/list ([target (in-list 
site-poly-targets)])
(list target 
(format-id stx "~a-~a" target #'TAG)))])
   #'(define-tag-function (TAG attributes elems)
   (define poly-func (second (assq (current-poly-target) (list (list 
'POLY-TARGET POLY-FUNC) ...
   (poly-func attributes elems)))]))

(poly-branch-tag bold)

(check-equal? (bold "hi")
  "this is html-bold")

(check-equal? (parameterize ([current-poly-target 'pdf])
(bold "hi"))
  "this is pdf-bold")



Alternatively, you could write the `poly-branch-tag` macro using a `case` 
statement. No leading quote necessary for POLY-TARGET here, because `case` 
auto-quotes whatever is on the left side of each branch. (Notice again the use 
of `...` to repeat the branch with each target / function pair.)


(define-syntax (poly-branch-tag stx)
  (syntax-parse stx
[(_ TAG:id)
 (with-syntax ([((POLY-TARGET POLY-FUNC) ...) (for/list ([target (in-list 
site-poly-targets)])
 (list target 
(format-id stx "~a-~a" target #'TAG)))])
   #'(define (TAG . xs)
   (case (current-poly-target)
 [(POLY-TARGET) (apply POLY-FUNC xs)] ...)))]))
;;;







> I started by using the (case) branching, but I wanted a way to be able to add 
> output formats in the future without fiddling with the macro every time.
> 
> All of this seemed to be working fine in my single-file DrRacket test, but 
> when I try this in an actual Pollen project I get an error (see end of this 
> post). It complains that html-bold is undefined, but it is very clearly 
> defined in tags-html.rkt (which also contains a (provide (all-defined-out)) 
> directive). Indeed, I can change test.poly.pm to call html-bold directly and 
> that works. So calling html-bold directly works, but a macro that evaluates 
> to ((eval 'html-bold) args) doesn't. 
> 
> I feel I must be missing some nuance of the scope in which Pollen files work. 
> E.g., I can run the following in DrRacket:
> 
> (define (html-bold attrs elems)
>   `(strong ,@elems))
> ((eval 'html-bold) '() '("ahoy"))
> 
> But the following in test.poly.pm gives me the same error as I get when using 
> my macro:
> 
> #lang pollen
>  
> ◊(define (html-bold elems) `(strong ,@title))
> ◊((eval 'html-bold) '() '("ahoy"))
> 
> raco pollen render -t html posts/test.poly.pm
> rendering posts/test.poly.pm
> rendering: posts/test.poly.pm as test.html
> rendering: /template.html.p as /template.html
> html-bold: undefined;
>  cannot reference undefined identifier
>   context...:
>...n/pollen/tag.rkt:79:10
>(submod /Users/joel/Documents/code/thenotepad/posts/test.poly.pm g1083 
> inner): [running body]
>(submod /Users/joel/Documents/code/thenotepad/post/test.poly.pm g1083): 
> [traversing imports]
>/Users/joel/Documents/code/thenotepad/posts/test.poly.pm: [traversing 
> imports]
>
> /Users/joel/Library/Racket/6.4/pkgs/pollen/pollen/private/cache-utils.rkt:33:0:
>  path->hash
>
> /Users/joel/Library/Racket/6.4/pkgs/pollen/pollen/private/cache-utils.rkt:76:14:
>  temp16
>/Applications/Racket