On Aug 17, 2016, at 1:25 PM, Chris Forster <[email protected]> wrote:
> I see your point Junsong; this is just a list (it's a LIST! for heaven's 
> sake) and so can be handled like a list (i.e. without any global variable to 
> track mutation). In part I led astray I think by modeling my solution to this 
> problem on how I've handled footnotes in plaintext (i.e. put in a numbered 
> footnote marker, and collect note text in a global list, that can be appended 
> to the end of the document);

True, mutation of state variables is not a core Racket / functional-programming 
idiom. But if you were to look through the Racket source code you'd find plenty 
of instances where `set!` is used in this way. So if it's the best tool for the 
job, use it. 

In practice, there are a lot of Racket functions that approximate the benefits 
of mutation without the drawbacks, for instance:

+ for/fold
+ parameters
+ generators

These often end up being simpler to think about than the `set!` approach.


> footnotes, unless I'm still misunderstanding something, are most easily 
> handled through mutation--because, unlike items in a list, they have no 
> single container (i.e. they could occur anywhere in a document). I think 
> that's right... (the irony of being confused by how to handle lists in a LISP 
> is not lost on me.)

If you're talking about continuously numbered footnotes, that's right -- the 
challenge is that the context for numbering is the whole project, whereas 
Pollen source files are ordinarily rendered one by one. 

(This is a limitation of Pollen's non-monolithic approach to structuring a 
project. To be fair, sequential footnote numbering is a relic of the 
letterpress age and makes no sense in the digital age, though academics seem in 
no hurry to let it go ;)

Putting a footnote counter in "pollen.rkt" won't actually work, because that 
file gets run separately every time a source file is rendered, so it won't 
"remember" the footnote count between renders.

The Rackety way to do this is to define a parameter, which is essentially a 
well-behaved global variable. What you do is:

1) Set up a new source file with the parameter.

2) `require` this file into your "pollen.rkt". The parameter is a function, and 
you retrieve its current value by invoking it as a function, or set its value 
by passing it an argument.

3) Then set up a render script that uses `parameterize` to set the initial 
value of the parameter, and preserves the state of the value between each page.


Here's a short example showing how multiple submodules can share state through 
a parameter. It works the same way if you turn the submodules into independent 
source files.



#lang racket/base

(module params racket/base
  (provide (all-defined-out)) 
  (define footnote-number (make-parameter "this value is overridden")))

(module pollen-rkt racket/base
  (require (submod ".." params))
  (provide (all-defined-out)) 
  (define (do-note which)
    (displayln (format "~a has note ~a" which (footnote-number)))
    (footnote-number (add1 (footnote-number)))))

(module foo racket/base
  (require (submod ".." params) (submod ".." pollen-rkt))
  (provide (all-defined-out))
  (define (do-foo-notes)
    (do-note 'foo)
    (do-note 'foo)
    (do-note 'foo)))

(module bar racket/base
  (require (submod ".." params) (submod ".." pollen-rkt))
  (provide (all-defined-out))
  (define (do-bar-notes)
    (do-note 'bar)
    (do-note 'bar)))

(module zam racket/base
  (require (submod ".." params) (submod ".." pollen-rkt))
  (provide (all-defined-out))
  (define (do-zam-notes)
    (do-note 'zam)
    (do-note 'zam)
    (do-note 'zam)
    (do-note 'zam)
    (do-note 'zam)))

(module main racket/base
  (require (submod ".." params) (submod ".." foo)
           (submod ".." bar) (submod ".." zam))
  (parameterize ([footnote-number 1])
    (do-foo-notes)
    (do-bar-notes)
    (do-zam-notes)))


-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to