Re: [racket-users] Why do single-form modules behave differently?

2021-01-02 Thread Michael MacLeod
Oops, sorry about interpreting your question wrong. Unfortunately I don't
know the answer to your actual question.

On Sat, Jan 2, 2021, 10:24 PM Sage Gerard  wrote:

> I know about that. I asked why it was designed that way.
>
>
> Sent from ProtonMail mobile
>
>
>
>  Original Message 
> On Jan 3, 2021, 12:18 AM, Michael MacLeod < michaelmmacl...@gmail.com>
> wrote:
>
>
> There's an edge case of 'module' when only one form is provided which
> results in that form being partially expanded to determine if such
> expansion would lead to a #%plain-module-begin form. Otherwise (more than
> one form provided) they are wrapped in #%module-begin with no partial
> expansion occurring.
>
> I think this might be causing the discrepancy you witnessed.
>
> From the docs (https://docs.racket-lang.org/reference/module.html):
>
> If a single form is provided, then it is partially expanded in a
> module-begin context. If the expansion leads to #%plain-module-begin, then
> the body of the #%plain-module-begin is the body of the module. If partial
> expansion leads to any other primitive form, then the form is wrapped with
> #%module-begin using the lexical context of the module body; this
> identifier must be bound by the initial module-path import, and its
> expansion must produce a #%plain-module-begin to supply the module body.
> Finally, if multiple forms are provided, they are wrapped with
> #%module-begin, as in the case where a single form does not expand to
> #%plain-module-begin.
>
> (This response was adapted from one of my earlier replies to the mailing
> list. Search racket-users for "perplexed by macro-expansion behavior near
> #%module-begin" for more context).
>
> Best,
> Michael
>
> On Sat, Jan 2, 2021 at 8:26 PM Sage Gerard  wrote:
>
>> Why does Racket handle modules with exactly one form differently?
>>
>> I ran into a bug where modules in my module language won't expand if the
>> modules have exactly one form, so I'm just curious.
>>
>> (Wild guess: It's Racket's way of checking for a shortcut to end
>> expansion earlier)
>>
>> *~slg*
>>
>>
>> --
>> 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.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/OVvZ0OK4_PfyvXCWfuvzDWBM5-ellmDvNmWchVmsCwAJb_rbSZkCkyraakcGsEMSCl2BsLsWtMXFhQcXY75IKhYiYYGQQEI7lVXLgGBbTCc%3D%40sagegerard.com
>> <https://groups.google.com/d/msgid/racket-users/OVvZ0OK4_PfyvXCWfuvzDWBM5-ellmDvNmWchVmsCwAJb_rbSZkCkyraakcGsEMSCl2BsLsWtMXFhQcXY75IKhYiYYGQQEI7lVXLgGBbTCc%3D%40sagegerard.com?utm_medium=email_source=footer>
>> .
>>
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmBvs5KK4vQmwio93D1NZ9hTOoSv-Qkm8XOjF%2B4JWDOiHg%40mail.gmail.com.


Re: [racket-users] Why do single-form modules behave differently?

2021-01-02 Thread Michael MacLeod
There's an edge case of 'module' when only one form is provided which
results in that form being partially expanded to determine if such
expansion would lead to a #%plain-module-begin form. Otherwise (more than
one form provided) they are wrapped in #%module-begin with no partial
expansion occurring.

I think this might be causing the discrepancy you witnessed.

>From the docs (https://docs.racket-lang.org/reference/module.html):

If a single form is provided, then it is partially expanded in a
module-begin context. If the expansion leads to #%plain-module-begin, then
the body of the #%plain-module-begin is the body of the module. If partial
expansion leads to any other primitive form, then the form is wrapped with
#%module-begin using the lexical context of the module body; this
identifier must be bound by the initial module-path import, and its
expansion must produce a #%plain-module-begin to supply the module body.
Finally, if multiple forms are provided, they are wrapped with
#%module-begin, as in the case where a single form does not expand to
#%plain-module-begin.

(This response was adapted from one of my earlier replies to the mailing
list. Search racket-users for "perplexed by macro-expansion behavior near
#%module-begin" for more context).

Best,
Michael

On Sat, Jan 2, 2021 at 8:26 PM Sage Gerard  wrote:

> Why does Racket handle modules with exactly one form differently?
>
> I ran into a bug where modules in my module language won't expand if the
> modules have exactly one form, so I'm just curious.
>
> (Wild guess: It's Racket's way of checking for a shortcut to end expansion
> earlier)
>
> *~slg*
>
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/OVvZ0OK4_PfyvXCWfuvzDWBM5-ellmDvNmWchVmsCwAJb_rbSZkCkyraakcGsEMSCl2BsLsWtMXFhQcXY75IKhYiYYGQQEI7lVXLgGBbTCc%3D%40sagegerard.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmC0ZMqoGv8SF8jiEkLJfE4SL1SKsCuJUT1W2qYDORo19Q%40mail.gmail.com.


Re: [racket-users] provide-if-not-defined

2020-09-02 Thread Michael MacLeod
Does this example work: http://pasterack.org/pastes/95923?

`if-not-defined` is written as a provide transformer which uses
`syntax-local-module-defined-identifiers` to get the list of phase-0
identifiers defined in the module.

Best,
Michael

[code also pasted below]:

#lang racket/base

(module implementation racket/base
  (provide (if-not-defined "^my-"
   + ; my-+ from this module
   - ; - from racket/base
   * ; my-* from this module
   / ; / from racket/base
   ))

  (require (for-syntax racket/base
   racket/provide-transform
   syntax/parse))

  (define-syntax if-not-defined
(make-provide-transformer
 (lambda (stx modes)
   (syntax-parse stx
 [(_ pattern:string var:id ...)
  (define regex (regexp (syntax-e #'pattern)))
  (define phase-0-ids
(hash-ref (syntax-local-module-defined-identifiers) 0))
  (define (find-id+sym v)
(define v-string (symbol->string (syntax-e v)))
(for/or ([id (in-list phase-0-ids)])
  (define id-string (symbol->string (syntax-e id)))
  (define maybe-match
(and (string=? v-string
   (regexp-replace regex id-string ""))
 (not (string=? id-string v-string
  (if maybe-match
  (cons id
(string->symbol v-string))
  #f)))
  (for/fold ([exports '()])
([v (in-list (syntax->list #'(var ...)))])
(define maybe-id+sym (find-id+sym v))
(cond [maybe-id+sym
   (cons (export (car maybe-id+sym)
 (cdr maybe-id+sym)
 0
 #f
 (car maybe-id+sym))
 exports)]
  [else
   (cons (export v
 (syntax-e v)
 0
 #f
 v)
 exports)]))]

  (define (my-+ a b)
(+ a b 100))

  (define (my-* a b)
(* a b 100)))

(require 'implementation rackunit)

(check-equal? (+ 2 3) 105)
(check-equal? (- 2 3) -1)
(check-equal? (* 2 3) 600)
(check-equal? (/ 2 3) 2/3)

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmBAd%2BhNHsO3CkthY5ojuZ%2B_Rgj87rKbQrPXrAw5Fxcw7w%40mail.gmail.com.


Re: [racket-users] require and syntax-case

2020-07-12 Thread Michael MacLeod
The issue isn't actually with the `(_ (x y))` pattern---it's with the
`#'(require (x y))` template.

When `require` is passed a module path like `(file "test1.rkt")`, it
introduces any identifiers [just `ok` in this case] with the same lexical
context of the module path itself[1].

The issue is that the expansion of `req2` adds a macro introduction scope
to the `(file "test1.rkt")` syntax object. Since the module path has an
additional scope, `ok` will have an additional scope; it won't bind the
`ok` from test2.rkt, and we get an unbound identifier error.

With `req1`, the parentheses around (file "test1.rkt") in the expanded code
come from the use site of the macro, so the `ok` identifier will have the
expected lexical context.

With `req2`, the parentheses around (file "test1.rkt") in the expanded code
come from the macro itself, not from the use site of the macro. Notice the
difference: in `(require x)` the parentheses are "in the x", but in
#'(require (x y)) the parentheses are from the (#') template.

You may be able to achieve your end goal using make-require-transformer[2],
which would probably end up being much nicer than what I'm about to go into.

Alternatively you could resort to using the unhygenic `datum->syntax` to
ensure that the resulting syntax object doesn't have the extra macro
introduction scope. I've added some checks before the template to ensure
that the forms passed to the macro are of the proper shape.

```
(define-syntax (req2 stx)
  (syntax-case stx ()
[(_ (x y))
 ; throw a "bad syntax" error if the
 ; arguments are incorrect
 (and (free-identifier=? #'x #'file)
(string? (syntax-e #'y)))
 #`(require
 #,(datum->syntax
; create the syntax object (x y)
; using the lexical context of y
#'y
(list #'x #'y)))]))
```

You may want to use `syntax-parse` instead, which makes these sorts of
checks much simpler to write, and usually gives better error messages than
"bad syntax".

```
(require (for-syntax racket/base syntax-parse))
(define-syntax (req2 stx)
  (syntax-parse stx
[(_ ((~literal file) y:str))
 #`(require #,(datum->syntax #'y (list #'file #'y)))]))
```

---
[1] `module-path` part under the `require` section from
https://docs.racket-lang.org/reference/require.html?q=require#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29
[2]
https://docs.racket-lang.org/reference/stxtrans.html?q=require%20transfo#%28def._%28%28lib._racket%2Frequire-transform..rkt%29._make-require-transformer%29%29



On Sun, Jul 12, 2020 at 8:18 PM Roman Klochkov 
wrote:

> I try to make a macro, that expands to the require form.
>
> I put in test1.rkt
> ```
> #lang racket/base
> (provide ok)
> (define ok 1)
> ```
>
> I put in test.rkt
> ```
> #lang racket
> (define-syntax (req1 stx)
>   (syntax-case stx ()
> [(_ x) #'(require x)]))
>
> (define-syntax (req2 stx)
>   (syntax-case stx ()
> [(_ (x y)) #'(require (x y))]))
>
> (req2 (file "test1.rkt"))
> ok
> ```
>
> When I run it, I have the error: ok: unbound identifier
>
> If I change `req2` to `require` or to `req1`, then it returns 1 as should.
>
> What's wrong with (_ (x y)) pattern ?
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/af6dcad0-69ff-406f-8183-dc691d302a5eo%40googlegroups.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmCq2dsK1gY8W0tVRMBtNpttGD0d2UpK6AmN2PvVMUm6mA%40mail.gmail.com.


Re: [racket-users] Matching groups of optional elements

2020-05-04 Thread Michael MacLeod
I'm not sure this is possible with only using `match` patterns. A
combination of the `list-rest` and `app` patterns as well as the `in-slice`
procedure from `racket/sequence` should do the trick, though:

#lang racket

(require racket/match)

(define (collect-optional-vals x)
  (for/list ([y (in-slice 4 x)])
y))

(match '(req-a req-b name1 age1 first1 last1 name2 age2 first2 last2)
  [(list-rest req-a req-b (app collect-optional-vals optional-vals))
   (list req-a req-b optional-vals)])

On Mon, May 4, 2020 at 7:16 PM David Storrs  wrote:

> I'm trying to write a parser for a CSV file with optional columns.
> Simplified version:  There are 2 mandatory columns, after which there can
> be 0+ 4-column groups describing a person.  Each group has the same column
> headers.
>
> ; legal column arrangements:
> RequiredA RequiredB
> RequiredA RequiredB Name Age First Last
> RequiredA RequiredB Name Age First Last Name Age First Last
>
>
> ; illegal:  if an optional group is present, it must have all 4 columns
> RequiredA RequiredB Name Age First Last Name
>
> I thought I could do this straightforwardly with `match`, but I'm wrong.
> Can someone point me to the way to write such a match clause?
>
>
> Various failed attempts:
> (list reqA reqB (opt1 opt2 opt3 opt4) ...)   ; syntax error. matching
> clauses do not do grouping like this
> (list reqA reqB (list opt1 opt2 opt3 opt4) ...) ; didn't expect this to
> work since it would specify an embedded list.  I was right.
>
> This one surprised me:
> (match row
>   [(list required1 required2 (and opt1 opt2 opt3 opt4) ...)
>(list opt1 opt2 opt3 opt4)])
>
> This distributes the ... over the four items inside the 'and' clause such
> that each of the 'optionalN' identifiers matches all remaining elements.
> '(("Name" "Age" "First" "Last")
> ("Name" "Age" "First" "Last")
> ("Name" "Age" "First" "Last")
> ("Name" "Age" "First" "Last"))
>
> In hindsight it makes sense -- the 'and' causes it to match the element
> across all four patterns.  They all match because they are identifiers and
> therefore match anything.  Then the '...' causes it to do that for all
> remaining elements, generating lists into each of the identifiers because
> that's what '...' does.
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAE8gKocCPSgVQG_aMSC%3DQJAmAtxvmCN8vqpwsankKnCJZAOotw%40mail.gmail.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmA6Xo87zckX4N8JbXDJVaVob6cp3Dk%2B%3DD3DG80DDgonyQ%40mail.gmail.com.


Re: [racket-users] DrRacket and command line arguments

2020-04-18 Thread Michael MacLeod
You can parameterize `current-command-line-arguments` like so:

```
#lang racket

(require racket/cmdline)

(define foo (make-parameter 7))

(parameterize ([current-command-line-arguments #("--thing" "9")])
  (command-line
   #:program "foo"
   #:once-each
   [("--thing") thing "The thing" (foo thing)])
  (displayln (foo)))
```

See the docs

for more information.


On Sat, Apr 18, 2020 at 11:03 AM David Storrs 
wrote:

>
> Is there a way to specify command line arguments when running inside
> DrRacket?
>
> For example:
>
> #lang racket
> (define foo (make-parameter 7))
> (command-line
>  #:program "foo"
>  #:once-each
>  [("--thing") thing "The thing" (foo thing)]
>  )
> (displayln (foo))
>
>
> If running in DrRacket, how can I make this spit out 9 instead of 7?
>
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAE8gKocbjLNy%3D9S-g4HSc6WmOJf2TAsd7LOzbEYGQsm%3DYLGLAg%40mail.gmail.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmBKwf--7mBpuTtCEG9a_n2%3DBPP5g1sHtwwhjQUDJF8Bbw%40mail.gmail.com.


Re: [racket-users] Starting racket with at-exp

2020-03-02 Thread Michael MacLeod
$ racket -i -l scribble/reader -e "(use-at-readtable)" -l
your-lang-without-@-support

should do the trick. For example, to start a REPL in typed/racket with
@-reader support, you would use:

$ racket -i -l scribble/reader -e "(use-at-readtable)" -l typed/racket
> @+[2 3]
  - : Integer [more precisely: Positive-Index]
5

Documentation source:
https://docs.racket-lang.org/scribble/reader-internals.html

On Mon, Mar 2, 2020, 1:24 PM Stephen De Gabrielle 
wrote:

>
> I tried this but had no luck;
>
> Miriams-MBP:~ spdegabrielle$ cat start.rkt
>
> #lang at-exp racket/base
>
> (require racket/format)
>
> (displayln "try me")
>
> (~a "foo bar")
>
> @~a{foo bar}
>
>
> Miriams-MBP:~ spdegabrielle$ racket -t ~/start.rkt -i
>
> Welcome to Racket v7.6.
>
> try me
>
> "foo bar"
>
> "foo bar"
>
> > (~a "foo bar")
>
> ; readline-input:1:0: #%top-interaction: unbound identifier;
>
> ;  also, no #%app syntax transformer is bound
>
> ;   at: #%top-interaction
>
> ;   in: (#%top-interaction ~a "foo bar")
>
> ; [,bt for context]
>
> > @~a{foo bar}
>
>   ; readline-input:2:0: #%top-interaction: unbound identifier;
>
> ;  also, no #%app syntax transformer is bound
>
> ;   at: #%top-interaction
>
> ;   in: (#%top-interaction ~a "foo bar")
>
> ; [,bt for context]
>
>
>
> On Mon, Mar 2, 2020 at 4:57 PM Faré  wrote:
>
>> How may I start a racket command-line (or emacs subprocess) with the
>> at-exp racket language? (or at-exp something else) The obvious
>> racket -l 'at-exp racket'
>> doesn't work.
>>
>> —♯ƒ • François-René ÐVB Rideau •Reflection•
>> http://fare.tunes.org
>> The universe isn't made of atoms, it's made of stories — Muriel Rukeyser
>>
>> --
>> 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.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/CAN7nBXeD%3DspMKcN4Dz3zxoYJTo3vTwpVXNy6%3DHBP3e0tevaZBw%40mail.gmail.com
>> .
>>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAGHj7-JHX3b%2BG-2czkcQUd3b_k3VXyd%3D_XwAMw7-kWvR6mtEgg%40mail.gmail.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmC%3Dm27CC1FjXFA6c5vxs7eOszC72ChpgOwWb08TquRaXg%40mail.gmail.com.


Re: [racket-users] perplexed by macro-expansion behavior near #%module-begin

2020-01-13 Thread Michael MacLeod
I believe this due to an edge case of 'module': when there is only one form
provided, it is partially expanded to determine if its expansion would lead
to a #%plain-module-begin form. Otherwise (more than one form provided)
they are wrapped in #%module-begin with no partial expansion occurring.

>From the docs (https://docs.racket-lang.org/reference/module.html):

If a single form is provided, then it is partially expanded in a module-begin
context
.
If the expansion leads to #%plain-module-begin
,
then the body of the #%plain-module-begin

is the body of the module. If partial expansion leads to any other
primitive form, then the form is wrapped with #%module-begin using the
lexical context of the module body; this identifier must be bound by the
initial module-path import, and its expansion must produce a
#%plain-module-begin

to supply the module body. Finally, if multiple forms are provided, they
are wrapped with #%module-begin, as in the case where a single form does
not expand to #%plain-module-begin

.

On Mon, Jan 13, 2020, 12:18 PM Matthew Butterick  wrote:

> Below, the two modules `test1` and `test2` use the same expander `exp` and
> otherwise differ only in the presence of the string "foo" as the second
> datum in `test2`.
>
> The syntax objects passed to #%module-begin are more different than that,
> however: the syntax passed to the first is
>
> #'(#%module-begin 'mac-result)
>
> wheras the second gets:
>
> #'(#%module-begin (mac 42) "foo")
>
> Thus my question: why is `mac` getting expanded at different times based
> on the presence of "foo"?
>
>
> ;;;
> #lang racket
>
> (module exp racket
>   (provide #%datum mac (rename-out [mb #%module-begin]))
>
>   (define-syntax-rule (mac x) 'mac-result)
>
>   (define-syntax (mb stx)
> (println (syntax->datum stx))
> (syntax-case stx ()
>   [(_ . EXPRS)
>#'(#%module-begin . EXPRS)])) )
>
> (module test1 (submod ".." exp)
>   (mac 42))
> (require 'test1)
> ;; '(#%module-begin 'mac-result)
>
> (module test2 (submod ".." exp)
>   (mac 42) "foo")
> (require 'test2)
> ;; '(#%module-begin (mac 42) "foo")
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/C0F76736-B28C-4F64-A1AA-D2B2EFD34BF8%40mbtype.com
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CACehHmD0PKdkJZ4CGmZ%2BV6JtknkDQQMx9BXMX_oTBqK0KHR%2B8g%40mail.gmail.com.