dotlambda.scrbl (5124B)
1 #lang scribble/manual 2 @require[@for-label[@only-in[dotlambda 3 #%dot-separator 4 #%dotted-id 5 #%module-begin 6 #%top-interaction] 7 racket/stxparam]] 8 9 @title{Dotted identifiers and @racket[λ<arg>.code] syntax} 10 @author[@author+email["Suzanne Soy" "racket@suzanne.soy"]] 11 12 @(begin 13 (module orig-racket/base racket/base 14 (require scribble/manual) 15 (provide racket/base:#%module-begin 16 racket/base:#%top-interaction) 17 (define racket/base:#%module-begin (racket #%module-begin)) 18 (define racket/base:#%top-interaction (racket #%top-interaction))) 19 (require 'orig-racket/base)) 20 21 @defmodulelang[dotlambda]{ 22 This @hash-lang[] language overrides @racket/base:#%module-begin and 23 @racket/base:#%top-interaction from @racketmodname[racket/base], and splits 24 identifiers which contain dots, following these rules: 25 26 @itemlist[ 27 @item{A single dot splits the identifier, and the dot is replaced with 28 @racket[#%dot-separator]. If an identifier is split by one or more 29 non-consecutive dots, all the resulting identifiers, including the 30 occurrences @racket[#%dot-separator] are placed in a syntax list, starting 31 with @racket[#%dotted-id], so that @racket[a.b.c] gets transformed into 32 @racket[(#%dotted-id a #%dot-separator b #%dot-separator c)].} 33 @item{A leading dot (which is not followed by another dot) is allowed, and is 34 replaced with @racket[#%dot-separator], like dots occurring in the middle of 35 the identifier.} 36 @item{A dot immediately preceded or followed by an ellipsis @racket[…] can be 37 omitted, so that @racket[a.….b], @racket[a….b], @racket[a.…b] and 38 @racket[a…b] are all translated to 39 @racket[(#%dotted-id a #%dot-separator … #%dot-separator b)].} 40 @item{Two or more dots do not split the identifier, but one of the dots is 41 removed (i.e. it escapes the other dots).} 42 @item{If an identifier ends with a dot, a single trailing dot is removed and 43 the identifier is otherwise left intact (i.e. the trailing dot escapes the 44 whole identifier).} 45 @item{Identifiers consisting only of dots are left unchanged, as well as the 46 following: @racket[..+], @racket[...+], @racket[..*], @racket[...*], 47 @racket[…], @racket[…+], @racket[…*] and @racket[::...].}] 48 49 Furthermore the syntax @racket[λarg₁.arg₂.….argₙ.(expr …)] is recognised as a 50 shorthand for @racket[(λ (arg₁ arg₂ … argₙ) (expr …))], so that 51 @racket[λx.(+ x 2)] is roughly translated to @racket[(λ (x) (+ x 2))]. If the 52 @racket[_var] part is left empty, then it defaults to @racket[%1], @racket[%2] 53 and so on. The number of parameters is determined from the syntactical 54 contents of the function's body, before performing macro-expansion. The term 55 @racket[λ.(+ %1 %2)] is therefore roughly translated to 56 @racket[(λ (%1 %2) (+ %1 %2))]. The variable named @racket[%] can be used as a 57 shorthand for @racket[%1], so that @racket[λ.(+ % 10)] is therefore roughly 58 translated to @racket[(λ (%) (+ % 10))]. 59 60 Since this substitution is performed on the whole program, before 61 macro-expansion, these notations are performed regardless of the context in 62 which an expression occurs. For example, the quoted term @racket['a.b] will 63 also get translated to @racket['(#%dotted-id a #%dot-separator b)]. In this 64 way, the @racket[#%module-begin] from @racket[dotlambda] works a bit like if 65 it were a reader extension. 66 67 @bold{Warning:} There probably are some issues with hygiene, especially in 68 mixed contexts (e.g. literate programs, or typed/racket programs with untyped 69 code at phase 1). I will think about these issues and adjust the behaviour in 70 future versions. Future versions may therefore not be 100% backward-compatible 71 with the current version, but the general syntax of dotted identifiers should 72 hopefully not change much.} 73 74 @defform[#:kind "syntax parameter" 75 (#%dotted-id ids-and-separators …)]{ 76 The default implementation currently translates @racket[a.b.c.d] to 77 @racket[(d (c (b a)))], and @racket[.a.b.c] to 78 @racket[(λ (x) (c (b (a x))))]. 79 80 This behaviour can be altered using @racket[syntax-parameterize]. I don't 81 think syntax parameters can be modified globally for the whole containing file 82 like parameters can (via @racket[(param new-value)]), so the exact mechanism 83 used to customise the behaviour of @racket[#%dotted-id] may change in the 84 future.} 85 86 @defidform[#%dot-separator]{ 87 Indicates the presence of a (possibly implicit) dot. The original string 88 (usually @racket["."] or the empty string @racket[""] for an implicit dot 89 before or after an ellipsis) is normally stored in the 90 @racket['dotted-original-chars] syntax property of the occurrence of the 91 @racket[#%dot-separator] identifier.} 92 93 @defform[(#%module-begin . body)]{Overridden form of 94 @racket/base:#%module-begin and @racketmodname[racket/base]} 95 96 @defform[(#%top-interaction . expression)]{Overridden form of 97 @racket/base:#%top-interaction from @racketmodname[racket/base]} 98 99 @include-section{typed-dotlambda.scrbl}