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.