kellysmith12.21
2020-12-22 10:32:24

In case you haven’t seen, Scribble does have a <https://docs.racket-lang.org/scribble/lp.html?q=lp2|literate programming library>.


sorawee
2020-12-22 10:42:02

If datum-&gt;syntax doesn’t work (it should though), you can also try syntax-local-introduce



gknauth
2020-12-22 13:40:22

That is a very nice document to read. So much useful information normally not revealed by the creator of a program to its users or maintainers.


samth
2020-12-22 14:01:07

It would certainly be possible to make a scribble generated document look like that


samth
2020-12-22 14:01:40

You can take a look at scribble/acmart for an example of using a different set of latex styles


jjsimpso
2020-12-22 15:07:15

Thanks @rokitna! Your solution works. I didn’t know how to get that to work syntactically. The ,#’require-magic-name part is what I was missing.


jjsimpso
2020-12-22 15:10:53

I also had to mess around with paths, I ended up putting a symlink to my magic/ directory in src/ so that it could be referenced with “magic” instead of "../magic". That fixed an issue when running raco make from outside of src/. In general, is there a way to get the path of the file being compiled during macro expansion?


joshibharathiramana
2020-12-22 15:37:26

I’m working through eopl, but want to implement everything using match instead of using the eopl package. I’m stuck at the cps interpreter - specifically, how would I write https://github.com/iambrj/eopl/blob/master/src/cps-letrec/cps-letrec.rkt#L54\|this tail recursively? I could always use a closure, but I’m curious if I can just reuse Racket’s lambda in some clever way.


soegaard2
2020-12-22 15:40:59

What kind of output is expected to be the result of (cps some-expression) ?


joshibharathiramana
2020-12-22 15:44:18

I want to rewrite (cps-letrec expr env) into (cps-letrec expr env k) where k is the control context


gknauth
2020-12-22 15:45:19

I would love to see a small Racket program (as an example) made literate as an example like the one above. (Yeah I know, “So go ahead and do it!”) I looked at the docs and realized first I would have to reacquaint myself with what Knuth intended when he created Literate Programming. It’s been a while. It occurs to me others may have a handle on that already.


soegaard2
2020-12-22 15:45:23

Yes - but how are expressions represented in the output? (I don’t have my eopl book here).


joshibharathiramana
2020-12-22 15:45:51

so for instance, if I were to do (cps-letrec '(+ 1 2) init-env identity) would evaluate to 3


joshibharathiramana
2020-12-22 15:48:25

here is what the current interpreter does "letrec.rkt"&gt; (cps-letrec '(+ 1 2) init-env) 3


soegaard2
2020-12-22 15:49:18

So you are evaluating and cps’ing at the same time?


soegaard2
2020-12-22 15:50:42

Okay - I found a pdf. The grammar for the output is:


joshibharathiramana
2020-12-22 15:52:26

> So you are evaluating and cps’ing at the same time? Umm I’m not sure I understand, are they supposed to be distinct? My understanding of cps is to make the control context explicit


sorawee
2020-12-22 15:53:33

CPS is a compilation. It’s supposed to produce another program.


soegaard2
2020-12-22 15:53:39

Rewriting a program P into cps form P’ doesn’t evaluate the program. It simply rewrites the program into a new program (using a restricted set of constructs). That program can then be evaluated.


soegaard2
2020-12-22 15:54:31

So for example, when you rewrite if: [(list 'if condition then-clause else-clause) (if (cps-letrec condition env) (cps-letrec then-clause env) (cps-letrec else-clause env))] The idea is to produce an instance of cps-if-exp in the grammar.


samth
2020-12-22 15:54:52

That document is in racket, though?


joshibharathiramana
2020-12-22 15:55:14

so this is not a valid cps rewrite? [(list 'if condition then-clause else-clause) (cps-letrec condition env (lambda (b) (if b (cps-letrec then-clause env k) (cps-letrec else-clause env k))))]


soegaard2
2020-12-22 15:56:05

No, you will need to produce an if-expression (are EOPL using s-expression or records to represent expressions)?


soegaard2
2020-12-22 15:56:53

@anything Have you seen the blog posts Jay wrote (some years ago)


joshibharathiramana
2020-12-22 15:57:05

I believe eopl uses records and leaves rewriting them using procedures as exercises


soegaard2
2020-12-22 15:58:14

joshibharathiramana
2020-12-22 15:58:57

> you will need to produce an if-expression what would the expression give me when evaluated? Would it work as a scheme if?


sorawee
2020-12-22 16:00:52

> are EOPL using s-expression or records to represent expressions I don’t know what “record” is, but looking at your code, it seems that you are matching against S-expression, no?


joshibharathiramana
2020-12-22 16:01:39

yes


sorawee
2020-12-22 16:02:08

(I guess record is struct in Scheme)


joshibharathiramana
2020-12-22 16:03:03

@soegaard2 I am still in chapter 5 where they rewrite the letrec interpreter by making the control context explicit. I haven’t looked at chapter 6 yet.


joshibharathiramana
2020-12-22 16:06:28

the book transforms the letrec interpreter so that all clauses are tail recursive and control context grows only in the third parameter k


joshibharathiramana
2020-12-22 16:08:20

I would like to do the same with my interpreter, but I can’t figure out how to rewrite this clause [(list 'lambda (list args ...) body) (lambda host-args (cps-letrec body (foldr ext-env env args host-args)))] without using a closure


soegaard2
2020-12-22 16:10:25

Okay - I think I get the context now. You are not doing a cps-transform on a program. You are writing an interpreter that has an explicit representation of continuations.


joshibharathiramana
2020-12-22 16:10:59

yes yes, sorry for framing my question so terribly :sweat_smile:


soegaard2
2020-12-22 16:11:40

That’s ok!


soegaard2
2020-12-22 16:12:32

So wrt [(list 'lambda (list args ...) body) (lambda host-args (cps-letrec body (foldr ext-env env args host-args)))] You need to ask yourself what apply-procedure will need to do.


soegaard2
2020-12-22 16:13:36

I exptect that apply-procedure will be called as (apply-procedure proc val cont).


soegaard2
2020-12-22 16:14:35

So if proc is represented as a Racket closure, you will need to pass the continuation cont along to the procedure proc.


soegaard2
2020-12-22 16:15:06

You could for example have the convention that the first argument of all procedures are the continuation.


soegaard2
2020-12-22 16:17:47

[(list 'lambda (list args ...) body) (lambda (cont . host-args) (value-of/k body (foldr ext-env env args host-args))) cont)] Here value-of/k is your cps-letrec (I think).


soegaard2
2020-12-22 16:19:18

Note that value-of/k expects three arguments:


joshibharathiramana
2020-12-22 16:25:17

yes this would work, but is it tail recursive? Since value-of/k is called inside a lambda, its not tail recursive correct?


joshibharathiramana
2020-12-22 16:38:41

but if you look at <https://github.com/mwand/eopl3/blob/master/chapter5/letrec-lang/interp.scm#L36|eopl’s >value-of/k , it is indeed tail recursive


joshibharathiramana
2020-12-22 16:39:27

so my question is, can I use Racket’s lambda for representing procedures, but still not lose out on tail recursion?


joshibharathiramana
2020-12-22 16:43:33

I hope at least my question makes sense now :sweat_smile:


me1890
2020-12-22 16:46:21

I’m pretty sure the answer is yes


me1890
2020-12-22 16:46:47

because all somethink like (define (f x) x) expands to using lambda


soegaard2
2020-12-22 16:50:04

The last expression in a lambda expression is in tail position, so it is not a problem to call value-of/k inside lambda.


joshibharathiramana
2020-12-22 16:51:13

whoaa I didn’t know this about tail calls! May I ask where you quoted the above from?


joshibharathiramana
2020-12-22 16:51:44

Thank you for putting up with my pestering :smile:



soegaard2
2020-12-22 16:55:35

It just happens to be where I remember it is described. I think it is in the Racket docs too somewhere.





arthertz
2020-12-22 17:04:43

@arthertz has joined the channel


gknauth
2020-12-22 18:18:15

Thank you @soegaard2! I don’t remember if I saw that before, but it certainly fits the bill. And @samth yes you’re right.


anything
2020-12-22 20:08:30

Thanks all of you! I hadn’t seen this post by Jay. Great stuff, specially to me because I enjoy the Hanoi problem at a lot and had been meaning to illustrate it like that. There couldn’t be a better example to me right now. (@samth, yes, that example.pdf is a program in Racket, but written in noweb, not with Scribble.) So I think my intuition was right — perhaps what I want is just to have Scribble produce a LaTeX document like noweb does, with the cross-references and the same layout. The layout itself is just a LaTeX article, so perhaps it is “only” the chunk layout and the cross-referencing that’s need. I don’t know if I would be able to figure something like that out, but if I’m not to far from the required knowledge, I would surely have the motivation to do it. The end result would in fact be a lot better than noweb. Scribble is limitless, after all. Great stuff. Thanks so much!


soegaard2
2020-12-22 20:10:25

@anything Check Jay’s archive. There are quite a few of his blog posts in this style.


rokitna
2020-12-22 20:56:24

I bet define-runtime-path is at least part of the solution you’re looking for there.


kellysmith12.21
2020-12-22 23:41:56

I’ve run into the issue that, although I can wrap match to produce immutable bindings, it only works in the case that I can extract all of the bound variables from a pattern. Since match expanders can extend patterns arbitrarily, I can’t hard code such extraction for a few patterns. I’ve found that the match modules have a private procedure to extract bound variables from a pattern; would it be possible to add something similar to the public API?


kellysmith12.21
2020-12-23 03:02:39

Perhaps it’d be best to file a feature request on GitHub?


anything
2020-12-23 03:03:01

To close this chapter. After looking at Jay’s Hanoi post (and not being able to compile it locally), I went to look at scribble/lp2 (the newer version of scribble/lp). The documentation gave a nice introduction, so I do understand how it works more or less. I built some examples, looked at the latex source code. The language scribble/acmart worked nicely too in the basic examples. So I seems I understand — to produce an output like the one done by noweb, I could fork scribble/acmart and get the job done. But the job seems a bit over my head. In any case, I can easily see that Racket is by far the best tool there is around to produce things like documents. To write a document without a programming language as beautiful as Racket is a major crime. Word-like users, pure LaTeX users (such as myself) are really missing out on the nice life of having a powerful extensible language to produce beautiful documents. (It’s just not easy.)

I wonder if pollen is a more gentle solution to the objective of producing a LaTeX document in the literate programming style, but I guess not because scribble/lp2 comes ready with the chunk-feature, which is the essence of the solution. So it seems that the solution is really forking scribble/acmart (say), adjust it and worrying about the LaTeX design as a second phase.


samth
2020-12-23 03:25:28

I only pointed to scribble/acmart as an example — I think adjusting the LaTeX preamble used by scribble would be much easier than that.


samth
2020-12-23 03:25:56

Yes, an issue for that would be great.


kellysmith12.21
2020-12-23 04:37:13

Done!