[racket-users] Re: [Shameless self-promotion] Articles about programming-language theory for working programmers in Racket
Hi Alexander, Thank you for the nice words, neighbor đ -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Request for comments: An embedded DSL for CSS in Racket
> I'd be interested in trying a working prototype. It's hard to evaluate the > wisdom of the technical choices without enjoying the benefits of the new > interface. Thank you for your interest. The implementation needs some fixes that I expect to finish by the end of the week that starts tomorrow. As soon as I do that, Iâll publish a preliminary version and let you know. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Request for comments: An embedded DSL for CSS in Racket
> I just meant: it's an approach that has worked before. "Better"? That's for > you to decide. Alright :) Regarding the syntax of the DSL, I was intentionally vague about it in the original post because I wanted to focus on the technical choices I made. But let me expand on it a bit the means of an example. The following is the source code: (define two-column-layout #`(#:max-width 910px [@media (and screen (#:min-width 960px)) #:max-width 1000px [a #:color |#ff0011|]])) (css-expr->string #`([body #:margin-left 10px #:padding-left (px 10) #:font-family "Equity" "Concourse" Arial #:border {#:left (1px solid yellow) #:right (2px solid black)} #,@two-column-layout])) The following is the compiled CSS: body { margin-left: 10px; padding-left: 10px; font-family: "Equity", "Concourse", Arial; border-left: 1px solid yellow; border-right: 2px solid black; max-width: 910px; } @media screen and (min-width: 960px) { body { max-width: 1000px; } body a { color: #ff0011; } } Note that: - [Selector âbodyâ, declarations âmargin-leftâ and âpadding-leftâ] The value â10pxâ is expressible in two ways â10pxâ and â(px 10)â. The former representation is better for writing out explicitly (yes, it is a pun on â10pxâ being a symbol in Racket). The latter representation is better when the magnitude is a variable, for example, â(px #,gutter)â. Similar representation options are available elsewhere in the DSL, for example, CSS at rules. - [Selector âbodyâ, declaration âfont-familyâ] The CSS value delimited by quotes is a Racket string, the CSS value not delimited by quotes is a Racket symbol. In fact, in the DSL both the values â10pxâ and âArialâ go through the same translation mechanism. - [Selector âbodyâ, declaration âfont-familyâ] Lists of CSS values do not require extra parenthesis in the DSL. - [Selector âbodyâ, declaration âborderâ] It is possible to nest declarations, a featured borrowed from SASS. - [Selector âbodyâ, declaration âborderâ, sub-declarations âleftâ and ârightâ] A composite CSS value require extra parenthesis in the DSL. - [Selector âbodyâ, splicing âtwo-column-layoutâ] A mixin is the result of an âunquote-splicingâ. Mixins can have parameters, in the form of a function that returns a piece of DSL syntax. This is a feature from SASS that the DSL gets for free, because of the Racket embedding. The same is true of SASS variables. - [Mixin âtwo-column-layoutâ, at-rule â@mediaâ and selector âaâ] It is possible to nest rules. Another feature borrowed from SASS. - [Mixin âtwo-column-layoutâ, selector âaâ, declaration âcolorâ] It is possible to represent colors with Racket symbols, for example, â|#ff0011|â and â\#ff0011â. Unsurprisingly, they go through the same translation mechanism as â10pxâ and âArialâ. This is one of the very few places where I anticipate users having to escape characters in symbols. There are many more tricks in this DSL. This example serves only to give you a flavor of what I am trying to accomplish while trying to avoid overwhelm you with the details. These details are still changing, which is the main reason why I have not published the library yet. Of course, if it interests you, I can give an overview of the whole language. But that goes beyond my main point for the moment, which is to figure out if I am using the right tools for the job. If you have more suggestions, please comment. I am happy to read your feedback. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Re: Request for comments: An embedded DSL for CSS in Racket
Hi, all. Greg Trzeciak: I did not know about Garden, thank you for the reference. In particular, I liked the way he talks about decoupling selectors and declarations. It is something I have been doing in my CSS for a long time: previously with SASS mixins, now with my library and calls to Racket functions in a CSS rule. But I had never thought about the practice in terms of decoupling selectors and declarations. It is a nice new frame for an existing picture. Matthew Butterick: > None of the below is meant to deter your voyage of discovery! On the contrary, your feedback encourages to move on! :) > 1) Perhaps have a look at the approach used by the `xml` and `html` and `json` > libraries, which is 1) parse data from string, 2) store data in nested > structs, 3) generate new string from nested-struct thingy. I understand this approach, but I do not understand how it is better than what I proposed. Can you please elaborate on that? > 2) Maybe a metalanguage that embeds at the reader level, and expands certain > source strings into S-expressions? See http://docs.racket-lang.org/debug/ for > an example, where the `#R` prefix in source takes on special meaning. This idea of prefixing is interesting. I view it as separate from the previous one, though. I could have (or not) prefixes to either strings or S-expressionsâin fact, in âdebugâ, the â#Râ prefix is for S-expressions. I actually had a similar thing in a previous iteration of my language. Not at the reader level, but as macro called âcssâ. Here is an example: â(css [body {âŠ}])â. I decided to drop it because it was nothing more than â#`â. What else do you think the prefix could do? How is it better than the macro version? > Notationally, how is this an improvement over regular CSS? And if it's not, > why not use regular CSS notation, and parse it? I believe it is easier to build syntactically correct S-expressions than it is to concatenate strings to form syntactically correct CSS. At the very minimum, there is a guarantee that there are no missing semicolons or closing braces. I also believe it is a simpler approach: parsing S-expressions with âsyntax-parseâ is simpler than parsing text. > 1) To write a library that actually parses and generates good CSS, I'd have to > keep up with the CSS spec, and all the browsers, and that gives me the > shivers. Then you will be happy to know that I did the work that gives you the shivers. I read the CSS specifications to make sure my library only generates syntactically correct CSS. Yes, it took me a while :) And yes, I plan on updating the library with respect to changes to the specification. Most changes to CSS are not syntactical, so it should not be too hard. > 2) Most of what I need is basic computational work â variable substitution, > math operations, string expansions â and I couldn't figure out what a separate > library would add that I couldn't already do with simple Racket functions > embedded in a Pollen source file. There are some things that are impossible to do with text manipulation alone. For example, to nest rules (in particular, âat rulesâ with media queries) and attributes. I believe those are powerful features because they allow for better organization and maintainability. So, even if I were to use Pollen preprocessor on stylesheets, I would be generating SASS. But, if âthe book is a programâ why shouldnât the stylesheet be a program as well? :) * * * I plan to release this library for the general public. My idea is to publish it as soon as I finish working on the new version of my website, which is serving as testbed. But I am doing the strange things I mentioned on my original posting so I decided to collect feedback as soon as possible. Please keep the comments coming and stay tuned for the release of the library. I am not committing to any schedule, but I expect it to be ready by the end of this year. And thank you Greg Trzeciak and Matthew Butterick for the insightful messages! -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Request for comments: An embedded DSL for CSS in Racket
Hi, all. I am working on an embedded DSL for CSS in Racket. I want to get feedback from the community regarding the projectâs goals and my choice of tools for implementing it. LANGUAGE I want to use Racket to generate CSS for me. I am not interested in a â#langâ language, but in a DSL that lives embedded in the code. In particular, I want âquoteâ and âunquoteâ. The best I can think of is something like: (define main-background-color #'red) (define the-css #`([body #:background-color #,main-background-color])) (css-expr->string the-css) ;; => "body{background-color:red;}" Note the explicit use of syntax objects. They allow for arbitrary âquoteâ and âunquoteâ and preserve source location information, which improves the quality of error messages. This is the best solution I could find, but I recognize it is unusualâI cannot name a single other example of embedded DSL in Racket that operates with syntax objects directly. Can you think of something better? COMPILER FRONT END I want good error messages, so I am using âsyntax-parseâ. I defined the concrete syntax tree in terms of syntax classesâeach production rule on the context-free grammar for the concrete syntax tree is a âsyntax-parseâ syntax class. For example, the following defines a âstylesheetâ as a list of ârulesâ: (define-syntax-class stylesheet (pattern (rule:rule ...))) The abstract syntax tree are typed structs, because I want to benefit from the correctness guarantees of Typed Racket. For example, the following is a struct for âstylesheetsâ: (struct stylesheet ([rules : (Listof rule)]) #:transparent) Then, the parser uses âsyntax-parseâ with the syntax classes to generate the typed structs. For example, the following is a parser rule for âstylesheetsâ: (define (parse/stylesheet expression) (syntax-parse expression [stylesheet:stylesheet (extended:stylesheet (map parse/rule (syntax->list #'(stylesheet.rule ...])) With this approach, I get a combination of good parsing error messages and typed structures to work on the compiler back end. But there is no âsyntax-parseâ in Typed Racket, so the parser module must be untyped. The interaction between untyped (compiler front end) and typed (compiler back end) modules leads to performance penalties. Overall, the whole architecture feels awkward, I feel like I am fighting the tools. Can you think of a better solution? COMPILER BACK END I use the typed structures in a module that concatenates strings to form CSS. This is the part I am happiest about, but I accept suggestions of more principled approaches than carefully constructed calls to âstring-appendâ and âstring-joinâ. OPINION My inspiration were the DSLs from http://www.cliki.net/CSS. I could not find a Racket equivalent. The following is an example of what the language looks like, recreating the CSS from http://bettermotherfuckingwebsite.com/: ([body {#:margin (40px auto) #:max-width 650px #:line-height 1.6 #:font-size 18px #:color |#444| #:padding (0 10px)}] [h1 h2 h3 {#:line-height 1.2}]) ;; => body{margin:40px auto;⊠Furthermore, I implemented some ideas that I borrowed from other CSS preprocessors such as SASS/Less. For example, the language supports nested declarations and attributes, appropriately unnesting them when generating the CSS output. What I like about embedding this DSL in Racket is that some of the preprocessorsâ features are free. For example, CSS variables and mixins are just âunquoteâ in Racket. I am using this DSL to build my website in Pollen, and so far I am happy with the results. I am envisioning more principled approach to CSS than concatenating strings, which other (excellent) projects do. For example, see Typography for Lawyers at https://github.com/mbutterick/pollen-tfl/blob/1267be5bd002d4d0fe09aaef89b4089147128841/styles.css.pp. Is this something that interests you too? How do you think I can make this project better and more useful to the community? * * * Thank you very much for your attention and for the feedback. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Potential small bugs on SEwPR
1. On Section 14.4, The CK Machine, on page 243, there is a reference to /part I(6.4)/, mentioning the specification for the CK Machine: "Comparing the Redex specification with the specification in part I(6.4)". But I believe /part I(6.4)/ is about the CEK Machine. The CK Machine is the subject of /part I(6.3)/. 2. On Section 18.4, Rewriting Calls to Meta-functions, on page 290, it says "In part I, we use the notation `M{X := V}' to express the substitution of all free occurrences of `X' in `M' with `V'." But I believe the notation in part I was `M[X â V]'. Also, on the last paragraph of the section, it says "Without this empty string, Redex would insert a gap between the `[' and the `M' in the final output. I believe this is referring to the `M[X â V]' notation, and not the `M{X := V}' notation. Finally, I'd like to take the opportunity to ask a question: The book says that, by default, Redex typesets meta-functions in small-caps. But, on my tests, running the latest version of Redex, I see proportional sans-serif instead. Has this changed since the book was published, or am I doing something wrong? Is there a way to restore the old behavior without having to add a compound rewriter for each meta-function? Thanks a lot for SEwPR and Redex. I finished reading it this weekend and loved it! Best. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Possible bug in SEwPR, Exercise 15.1
Thanks for adding the entry to the errata. It was fun finding the bug in my version: I forgot to /unfreeze/ (call) the function that represents the branches of the `if' statement. I used DrRacket's visual toolsâthe stepper, the tracer and the debuggerâto figure the issue. Not only that, but I used that find a nasty, nasty bug I introduced while (mistakenly) copying the `subst' meta-function from the book. I was able to go through 3 chapters before finding out that I wrote `X_3' in place of a `X_2'. That was a hard one, it drove me crazy for an hour :) And, of course, DrRacket was indispensable! Best. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Possible bug in SEwPR, Exercise 15.1
Thanks for the blazing fast response and for clarifying it for me. Also, thanks for acknowledgment; my name is Leandro Facchinetti. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Possible bug in SEwPR, Exercise 15.1
Hi, all, and authors of SEwPR in particular. I believe Exercise 15.1 has the following problems: 1. The function passed to the Y combinator should have an parameter before `x' called `tri'. 2. `ifz' is not a construct in ISWIM as presented in the previous chapters. I could extend the language to support it, of course, but I think this does not contribute to the goal of the exercise. Instead, I think it should use `iszero'. Summing up the previous two points, the code looks like: ((Y (λ tri (λ x (((iszero x) (λ y 0)) (λ y (+ x (tri (- x 1 3) - Let me take the opportunity to thank the authors for the book, PLT Redex and Racket. The more I learn, the more I appreciate the effort you put into them. Best. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Question about type annotations in `define' form
Hi, all. Why does the following typecheck: #lang typed/racket (provide group) (define #:forall (A) (group [list : (Listof A)] [count : Exact-Positive-Integer]) : (Listof (Listof A)) (: group-step (All (A) ((Listof A) (Listof A) (Listof (Listof A)) -> (Listof (Listof A) (define (group-step list group groups) (cond [(and (empty? list) (empty? group)) groups] [(empty? list) (cons (reverse group) groups)] [(= (length group) count) (group-step (rest list) `(,(first list)) (cons (reverse group) groups))] [else (group-step (rest list) (cons (first list) group) groups)])) (reverse (group-step list empty empty))) But the following doesn't: #lang typed/racket (provide group) (define #:forall (A) (group [list : (Listof A)] [count : Exact-Positive-Integer]) : (Listof (Listof A)) (define #:forall (A) (group-step [list : (Listof A)] [group : (Listof A)] [groups : (Listof (Listof A))]) : (Listof (Listof A)) (cond [(and (empty? list) (empty? group)) groups] [(empty? list) (cons (reverse group) groups)] [(= (length group) count) (group-step (rest list) `(,(first list)) (cons (reverse group) groups))] [else (group-step (rest list) (cons (first list) group) groups)])) (reverse (group-step list empty empty))) (Notice the change in the declaration of the inner function's signature, inlined in the `define' vs. separate on it's on `(: ...)'.) The error message: Type Checker: insufficient type information to typecheck. please add more type annotations in: group-step >From reading Typed Racket's reference, section 2.4 Definitions, I thought the latter was another way of writing the former. Thanks. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.