Re: [racket-users] problem with current-error-port in scribble interaction

2019-06-27 Thread Ryan Culpepper
The `uncaught-exception-handler` parameter controls the *bottom* of the 
exception handler stack, so it won't override the exception handler 
installed by Scribble's `interaction` form. If you use `with-handlers` 
(or `call-with-exception-handler`) instead, it should work.


The `uncaught-exception-handler` value is inherited by new threads, so 
it shouldn't refer to a specific escape continuation. That continuation 
(maybe the whole parent thread) may be gone by the time a child thread 
raises an exception.


Ryan


On 6/27/19 12:42 PM, Jos Koot wrote:



Hi,



The attachments are assumed to reside in the same directory and

are reduced forms of more elaborated code.

In module try-rkt I have code that captures errors such as

to avoid an error-message being written on the current-error-port,

to retrieve the error-message and to return normally.

This works well as shown in module test-try-rkt.

However, in a scribble interaction as shown in module try-scrbl,

I get page try.html in which the interaction shows the error message

and does not show the value returned by the test-proc.



How can I make the interaction behave like in module test-try.rkt?



In module try.rkt the use of eval is necessary.

It is a strongly reduced version of a testing system

that accepts sexprs and checks the returned values, the standard output and

the error-message when an error is expected.



Best wishes, Jos

--
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/5d149d7c.1c69fb81.9bc88.bf49%40mx.google.com
.
For more options, visit https://groups.google.com/d/optout.


--
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/3f14ff66-cb05-ded3-7ef1-89e3eacf3b6e%40ccs.neu.edu.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Name of undefined identifier as string in macro

2019-08-03 Thread Ryan Culpepper

On 8/3/19 10:48 AM, Zelphir Kaltstahl wrote:

Hi!

I am trying to write a macro, which checks the name of an argument for 
presence a substring. This is not the main purpose of the macro, but I 
want to do different things depending on the substring being contained 
or not contained.


Here is what I've got so far:

~
;; A macro to get the identifier name as string, shamelessly copied from 
StackOverflow and renamed:


(define-syntax identifier-name->string
   (lambda (stx)
     (syntax-case stx ()
   ((_ id)
    (identifier? #'id)
    (datum->syntax #'id (symbol->string (syntax->datum #'id)))

;; And the actual macro I want to write:

(define-syntax define-api-route
   (lambda (stx)
     (syntax-case stx (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATH)
   [(_ route GET my-content-type)
    (string-contains? (identifier-name->string (syntax route)) "abc")
    (println "abc is in the identifier name")])))
~

With this, Racket will complain, that I am referencing an identifier 
before its definition:


~
 > (define-syntax identifier-name->string
     (lambda (stx)
   (syntax-case stx ()
     ((_ id)
  (identifier? #'id)
  (datum->syntax #'id (symbol->string (syntax->datum #'id)))
 >
   (define-syntax define-api-route
     (lambda (stx)
   (syntax-case stx (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE 
PATH)

     [(_ route GET my-content-type)
  (string-contains? (identifier-name->string (syntax route)) "abc")
  (println "abc is in the identifier name")])))
 > (define-api-route abc/abc/abc GET 
application/json) 
; string-contains?: undefined;

;  cannot reference an identifier before its definition
;   in module: top-level
;   internal name: string-contains?
; [,bt for context]


There are two things going wrong here:

1. The undefined identifier is `string-contains?`. You are using it in 
the macro body, so you must require the module that provides it for-syntax:


  (require (for-syntax racket/string))

The reason you have to do that for `string-contains?` but not for 
`identifier?`, `syntax`, `lambda`, and so on is that the racket language 
implicitly does a `(require (for-syntax racket/base))` for you, and all 
of those other things are provided by racket/base. (Technically, racket 
just provides racket/base for-syntax.)


2. Your `identifier-name->string` macro needs to be a phase-1 function 
instead.


The implementation of a macro is an expression at a phase 1 higher than 
where the macro itself is defined. The top-level starts at phase 0, so 
the right-hand side of the `define-api-route` is a phase-1 expression. 
If you want to *use* (as opposed to *produce syntax referring to*) 
`identifier-name->string` in the macro body, it must also be defined at 
phase 1. Since you want to use it on a phase-1 *identifier value* and 
get a phase-1 *string value*, it should be a function.


So replace the definition of `identifier-name->string` with this:

  (begin-for-syntax
;; identifier-name->string : Identifier -> String
(define (identifier-name->string id)
  (symbol->string (syntax->datum id

If you don't want to use `begin-for-syntax`, there are two other ways to 
define this helper function and make it available to the macro body. You 
can put it in a new module and require that module for-syntax (that is, 
at phase 1). Or you can make the definition local to the 
`define-api-route` macro by moving it just inside that macro's `(lambda 
(stx) ___)`. In both cases, drop the `begin-for-syntax`.


Ryan



~

If I take away the (syntax ...) in the guard expression however, it will 
also not work, as template variables may only occur in syntax:


~
 > (define-syntax 
define-api-route 
(lambda 
(stx)   
(syntax-case stx (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE 
PATH)  [(_ route GET 
my-content-type) 
(string-contains? (identifier-name->string route) 
"abc")  
(println "abc is in the identifier name")])))

; readline-input:19:52: route: pattern variable cannot be used outside of a
;   template
;   in: route
; [,bt for context]
~

I have also tried loads of other stuff, but I cannot find a way to:

1. get the identifier name of route, whatever the user has as route (not 
a string yet!)
2. check inside the guard expression, whether the identifier name 
contains a certain substring
3. based on that substring call other macros to do the actual job of 
defining an API route


Can you help me writing this macro?
It would also be great, if the 

Re: [racket-users] Racket Jupyter/nextJournal

2019-08-14 Thread Ryan Culpepper

On 8/14/19 2:57 PM, tbrooke wrote:
There has been some discussion about Racket on Jupyter. nextJournal is a 
fairly new project for hosted notebooks that is written in Clojure and 
has support for Clojure as well as several other languages. In addition 
to Clojure they have templates for Julia,  Haskell, and Scala and they 
support Bash which should allow for installation of almost anything 
including Racket. They do have a free level and some paid levels.


I have no relationship with them other than asking about Racket support  
and Martin with nextJournal has been helping me. He is apparently stuck 
and asked if I knew of someone that could help. Here is a link to what 
he has done so far: 
https://nextjournal.com/nextjournal/racket-environment 



Can anyone help with this ?


The "jupyter run" command seems to just send the entire contents of the 
file to the kernel to evaluate. Not just the code parts, the entire JSON 
document. So the Racket kernel reads the JSON document as an 
S-expression (!), tries to evaluate it, and errors because of a comma 
(unquote in Racket) outside of quasiquote.


(Wow.)

I've found other people having similar problems:


https://stackoverflow.com/questions/56039870/how-to-use-jupyter-run-to-call-a-jupyter-notebook-on-local 
(and other question linked from comment)


On the other hand, the docs for "jupyter-run", such as I've found, seem 
to suggest that you're supposed to be able to run them on notebooks, not 
plain source files.


  https://pythonhosted.org/jupyter_runner/

So I'm confused.

In any case, to test whether the Racket kernel is working, I would 
suggest either "jupyter notebook 
/PATH/TO/iracket/examples/getting-started.ipynb" or "jupyter console 
--kernel=racket" and try evaluating some things interactively.


Ryan

--
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/ba6a6009-bba2-1c9c-3671-d89de19703c1%40ccs.neu.edu.


Re: [racket-users] Can I use the macro stepper to debug an infinite expansion loop?

2019-07-29 Thread Ryan Culpepper
The macro stepper *should* pop up a dialog after a certain (large) 
number of steps and ask if you want to interrupt it and see the 
expansion up to that point. For example, try this:


  #lang racket
  (define-syntax-rule (m) (m))
  (m)

The dialog should show up in a second or two. It can't handle an 
individual transformer in an infinite loop, though.


If you're not seeing that dialog, you can try adjusting the limit by 
setting the 'MacroStepper:MacroStepLimit preference (the default is 
4) using preferences:set.


Ryan


On 7/29/19 8:38 PM, Leif Andersen wrote:

Unfortunately no. The macro stepper requires macros to fully expand
before it can let you step through them.

You can, however, use this `obs.rkt` file (attached) to debug macros
as they are expanding, and will print the current expanding syntax to
stdout. While not the most convenient thing in the world, I have been
able to use it to debug some pretty large and hairy macros.

(Thanks to Michael Ballentyne for giving me the original script.)

On 7/29/19, William J. Bowman  wrote:

Can I use the macro stepper to debug a bug in some code that seems to be
macro
expanding infinitely?
Is it in a sandbox to prevent infinite macro expansion or something?
It looks like DrRacket's background expander allows me to kill expansion
after a
short time, but when launching the macro stepper, it just hangs... or maybe
the
timeout is longer than I'm willing to wait.

--
William J. Bowman

--
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/20190729175903.GA22568%40williamjbowman.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/bcd83e86-e63e-c423-173e-492d771535ad%40ccs.neu.edu.


Re: [racket-users] DrRacket UI question ...

2019-07-21 Thread Ryan Culpepper

On 7/21/19 10:41 PM, Tim Meehan wrote:
When hovering over names in a program that I downloaded to examine, I 
noticed a purple question mark that I had not remembered seeing before. 
I am used to hovering over a name and seeing where else it is used, 
etc., but I don't remember seeing the purple question mark before ...


I searched for DrRacket documentation in the "Racket Documentation" app, 
and also at Northwestern 
, 
but didn't see anything that described it. I'm going to try and attach a 
screenshot - but I am not sure that it will survive the mailing list 
process. In case it does not survive, I was looking at Matthias 
Felleisen's implementation of the 7GUIs tasks, specifically, task-2.rkt 
. I 
was hovering over "render" in line 27. The question mark shows up when 
pointing to the usage of "render" on line 25. I suppose that if I had to 
guess, it might have something to do with the usage being in a 
"define-syntax-rule."


Yes. The purple arrow is drawn to identifiers in syntax constants 
(things that eventually wind up in a quote-syntax form). It's different 
from a blue arrow because it shows a *potential* reference, but 
depending on how the syntax is used it may or may not turn into an 
actual reference.


Here's a simple example that shows potential references to `x` (with 
purple arrows) that do not become actual references:


  #lang racket
  (define x 12)
  (define-syntax-rule (id)
(lambda (x) x))

Ryan

--
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/53a8b8cd-cc36-2127-c6e5-d1ff15b46e12%40ccs.neu.edu.


Re: [racket-users] syntax-parse ellipsis question

2019-09-21 Thread Ryan Culpepper

On 9/21/19 10:15 PM, Jonathan Simpson wrote:

Given this macro that I'm experimenting with:

(syntax-parse #'(1 2 2 a 2 2 b 2 c) [(1 (~seq n:nat ...+ x) ...) #'((n 
... x) ...)])


How would I change it so that it returns #'(2 2 a 2 2 b 2 c) instead of 
#'((2 2 a) (2 2 b) (2 c)) ?


I don't want the parens around the individual sequences that I'm 
matching, but I haven't figured out a way to do this without using a 
pattern that forces me to add them in the body of the syntax-parse 
clause. How can I group the n and x pattern variables in the body 
without adding parens around them?


Use `~@` in the template:

  #'((~@ n ... x) ...)

Ryan

--
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/e0b92a23-9652-3059-b354-cdb50fee9f3b%40ccs.neu.edu.


Re: [racket-users] How do I secure secrets in memory?

2019-09-27 Thread Ryan Culpepper

On 9/27/19 6:56 PM, Sage Gerard wrote:
I got sloppy here in a Stripe integration: 
https://github.com/zyrolasting/stripe-integration/blob/master/main.rkt#L31


I'm not an InfoSec expert, but I know I'd like to secure the secret key 
used here in memory instead of using a parameter.


I'd probably encrypt the value provided by a client module and store it 
(write-only from the client's perspective) using set-box!. But I have 
several other questions:


1. Does the garbage collector keep a clear text copy of the secret in 
memory before I encrypt it? If so, how can I make it easy for a client 
module to set the secret key AND make it such that a garbage collection 
pass will remove the clear secret from RAM?


If the secret ever exists as (or within!) a Racket string or byte 
string, then I think you should assume that the GC might leave old 
copies in memory when it moves objects around. Memory allocated by a 
foreign library or using Racket's malloc in 'raw or 'atomic-interior 
mode shouldn't get copied by the GC.


2. Are there any existing /cross-platform/ Racket projects that can 
proactively keep secrets away from the garbage collector and swap space? 
Nothing relevant comes up for "secret", "security" or "swap" on the 
package index.


I thought about this briefly when I was working on the crypto package, 
but I decided it was way too difficult to address at the time.


3. Are there any other intermediaries in a Racket process that might 
keep a copy of a cleartext secret?


If you read the secret from a file, it might occur in an IO buffer that 
is not securely erased. If you read it in encrypted form and then 
decrypt it, the decryption implementation might use intermediate storage 
that isn't securely erased.


Ryan

--
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/373ac5e4-ebff-f00f-eb1d-e097f4017fd3%40ccs.neu.edu.


Re: [racket-users] Help me understand FFI callouts in this context?

2019-10-24 Thread Ryan Culpepper

On 10/25/19 12:45 AM, Sage Gerard wrote:

I am porting some C++ code to Racket that uses a function pointer.

C++ origin: See 294 through 306: 
https://github.com/Erkaman/vulkan_minimal_compute/blob/master/src/main.cpp#L294 

Racket destination: 
https://github.com/zyrolasting/racket-vulkan/blob/master/examples/mandelbrot.rkt#L240


How do I use function-ptr on debug-report-callback to produce a valid 
function pointer matching this signature 
? 



My current error comes from line 250, on the expression (function-ptr 
debug-report-callback _PFN_vkDebugReportCallbackEXT):


; function-ptr: contract violation
;   expected: (and ctype? (lambda (ct) (eq? 'fpointer (ctype->layout ct
;   given: #

It seems that my error was that _PFN_vkDebugReportCallbackEXT was 
(_cpointer/null (_fun ...)), but I am not sure what should take its place.


  * If I substitute _fpointer for _PFN_vkDebugReportCallbackEXT, I get
the "application; not a procedure" error.
  * If I substitute the _fun form with the signature I want, then I get
"#->C: argument is not `#' pointer"

I suspect this has something to do with the /callout/ concept from the 
manual, but I don't understand how it applies here.


The use of _cpointer/null seems wrong: its first argument is interpreted 
as a tag, so that's the source of the last error you mentioned. The 
`_cpointer/null` is unnecessary anyway, so just delete it:


  (define _PFN_vkDebugReportCallbackEXT (_fun ))

On line 250: I don't think you need to use function-ptr. The field 
setter will automatically convert debug-report-callback (I assume that's 
a Racket procedure) into a *callback* function pointer.


A *callout* is a foreign function gets converted into a Racket 
procedure; a *callback* is when a Racket procedure gets turned into a 
function pointer so it can be called from foreign code. Both are 
described by _fun ctypes.


Here's a simpler example. Suppose you have the following C code:

  /* demo.c */
  /* gcc -fpic -shared -o demo.so demo.c */

  int an_int_fun(int x) {
return x + 1;
  }

  typedef int (*int2int)(int);

  int apply_to_twelve(int2int f) {
return (*f)(12);
  }

  struct two_funs {
int2int f;
int2int g;
  };

  int apply_two_funs_and_sum(struct two_funs *tf, int arg) {
return (tf->f)(arg) + (tf->g)(arg);
  }

Here Racket bindings for the foreign code:

  (require ffi/unsafe ffi/unsafe/define)
  (define-ffi-definer define-demo (ffi-lib "demo.so"))

  (define _int2int (_fun _int -> _int))

  (define-demo an_int_fun _int2int)
  (define-demo apply_to_twelve (_fun _int2int -> _int))

  (define-cstruct _two_funs
([f _int2int]
 [g _int2int]))

  (define-demo apply_two_funs_and_sum
(_fun _two_funs-pointer _int -> _int))

In that Racket program, `an_int_fun` is a *callout*: a Racket procedure 
that calls foreign code when applied.


  (an_int_fun 5) ;; => 6

If you call `apply_to_twelve` with a Racket procedure, like this:

  (apply_to_twelve add1) ;; => 13

then the FFI converts `add1` (a Racket procedure) into a function 
pointer using the _fun type `_int2int`. Foreign code can use that 
function pointer to *call back* into Racket.


Storing a function in a struct with _int2int fields does the same 
automatic conversion. For example:


  (define (f x) (expt x 2))
  (define (g x) (expt x 3))

  (define tf (make-two_funs #f #f))
  (set-two_funs-f! tf f)
  (set-two_funs-g! tf g)
  ;; or equivalently, (define tf (make-two_funs f g))

  (apply_two_funs_and_sum tf 3) ;; => 36

You can even fetch one of the function fields back and call it, like this:

  ((two_funs-f tf) 4) ;; => 16

IIUC, that creates a callout procedure that calls the callback function 
pointer that calls the original Racket procedure.


I gave `f` and `g` names so they wouldn't be collected, but in general 
you need to make sure a Racket procedure doesn't get collected when 
foreign code still has a callback for it. For example, the following 
code is likely to crash: because the callback function pointer stored in 
tf2->g refers to a Racket procedure that has probably been GC'd:


  (define tf2 (make-two_funs f (lambda (x) (expt x 5
  (collect-garbage)
  (apply_two_funs_and_sum tf 3)

See the #:keep argument of `_fun` for more information.

Ryan

--
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/6c26abc4-09bc-3a2e-369f-b14671e84958%40ccs.neu.edu.


Re: [racket-users] Implementation of paraeters

2020-03-02 Thread Ryan Culpepper
A parameter object itself is essentially just a key. To get its value, you
first look up the current parameterization in the current continuation's
continuation-marks. The parameterization contains an immutable eq?-hash
mapping parameter keys to thread cells. The parameter's value is the value
of the thread cell in the current thread. Setting the parameter mutates the
thread cell, but using parameterize with the parameter remaps the parameter
to a new thread cell. (Actually, a parameter stores its initial thread
cell, so a parameterization's size is limited to the number of distinct
parameterized parameters, not the number of all created parameters.)

The Racket CS implementation of parameters is here:
https://github.com/racket/racket/blob/master/racket/src/cs/rumble/parameter.ss
.

Ryan


On Mon, Mar 2, 2020 at 6:45 PM Hendrik Boom  wrote:

> How are parameters implemented.  My conceptial model is an association
> list (like in the original Lisp 1.5 manuel) would suffice, but that can
> lead to long searches.
>
> What is actually done in Racket?
>
> -- hendrik
>
> --
> 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/20200302174453.7lpltlzivo6iids7%40topoi.pooq.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/CANy33qmDdW%3DoGKboLV5SS0AjxRUMpJB0uVdSonEs2C5MMc4QFA%40mail.gmail.com.


Re: [racket-users] Rolling dice game

2020-02-03 Thread Ryan Culpepper

On 2/3/20 12:31 PM, Wilzoo wrote:
Hi guys, so I am working on rolling dice game in GUI, the game rules 
will be something like rolling 3 dices and then giving out points to 2 
players based on the rolled values.


Im now stuck on the showing value in GUI. Basically what I need is to 
show rolled value somewhere in frame.


This is my rolling dice code:

(define (nrandom n)
     (if (= n 0 ) '() (cons (random 1 7) (nrandom (- n 1)

this is my callback function which i know is wrong:

(new button% [parent gamew]
              [label "roll dice"]
              [min-width 150]
              ; Callback procedure for a button click:
              [callback (lambda (b e) (send (nrandom 3) show #t))])

So by using this im getting my 3 values in IDE window. Where should I 
look for information how to get them in frame in some kind of box?


I just started my programming journey and racket documentation is not 
easy for me to get any information from there tbh. Just figuring out how 
to make frame and buttons + callback functions took me good few hours.


(Warning: I haven't tested this code.)

One thing you could do is add a new message% widget to the frame. For 
example, change your callback to the following:


  ;; button callback:
  (lambda (b e)
;; creating the widget has the side effect of adding it
;; to the parent container (gamew)
(new message%
  (parent gamew)
  (label (format "Rolled a ~s" (nrandom 3
(void))

Adding a new widget to the game frame may change its size or layout. You 
can control layout with containers (see pane%, panel%, and their 
subclasses).


But message% widgets aren't very flexible in how they display text. 
Another thing you could do is add a single editor canvas and write all 
of the die-roll messages to its editor. That would look something like this:


  ;; one text% and editor-canvas% per game frame:
  (define t (new text%))
  (define ec (new editor-canvas% (parent gamew) (editor t)))

  ;; the button callback:
  ... (lambda (b e)
(send t insert (format "Rolled a ~s\n" (nrandom 3)))
(void))

You can refine this version by disallowing user edits (see `lock`), 
reliably placing the insertion point at the end of the editor before 
writing, adding styles to the die roll result, etc. See the text% 
documentation.


Ryan

--
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/66512696-4249-88d0-3d17-80942cee2a41%40gmail.com.


Re: [racket-users] Create an identifier in syntax

2020-01-23 Thread Ryan Culpepper

On 1/23/20 3:59 PM, Sean Kemplay wrote:

Hello,

I am exploring macros and am trying to define a variable at the top 
level (with the goal in mind to dynamically define a group of functions 
from a macro).


with-syntax works fine however I was just wondering if it is possible to 
directly inject an identifier as syntax within syntax - something like 
the following which does not work!


(define-syntax x
     (lambda (x)
   #`(define ,#'y "y val")))

(x)
y => y: undefined;
  cannot reference an identifier before its definition


First, to escape a quasisyntax (#`) template you need to use unsyntax 
(#,), not unquote (,).


Second, due to hygiene the y from the macro has an extra scope, so you 
can't refer to it by typing y at the top level. But you can do this, for 
example:


  (define-syntax (x2 stx)
#`(begin (define #,#'y "y val") y))

Or you can write a macro that defines a y with the lexical context of 
the macro use:


  (define-syntax (x3 stx)
#`(define #,(datum->syntax stx 'y) "y val"))

You could also write this macro with with-syntax instead. The way that 
you insert an identifier into a syntax template (quasisyntax/unsyntax vs 
with-syntax) is independent of the way you create the identifier.


(Note: using the lexical context of the macro use works here, but it's 
not always the right answer. Unhygienic macros are complicated.)


Ryan

--
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/4b02bc1c-cd8a-feed-2c1c-0025209ffab3%40ccs.neu.edu.


Re: [racket-users] Opening unix domain socket with SOCK_SEQPACKET in Racket?

2020-01-28 Thread Ryan Culpepper

On 1/29/20 12:14 AM, Milo Turner wrote:

Hello all,

I'm wondering if it's possible to open a unix domain socket with 
SOCK_SEQPACKET in Racket? It looks like currently unix-socket-lib uses 
SOCK_STREAM, and doesn't allow you to configure that flag. Is there a 
reason for this, or would it be a good idea to add this feature to the 
unix-socket-lib library? I would rather not issue the C FFI calls 
myself, because non-blocking IO is fairly difficult to do correctly from 
my previous impressions with it.


SOCK_SEQPACKET sockets don't match Racket's port interface, which 
doesn't have a notion of message boundaries, so you'd have to work 
around that interface mismatch. Also, the unix-socket library reuses 
Racket's implementation of ports backed by file descriptors. To support 
SOCK_SEQPACKET, it would need a different implementation of read and 
write that preserved message boundaries.


So it would be possible, but it's a fair amount of work, and no one 
seems to have really needed SOCK_SEQPACKET support yet.


Ryan

--
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/29dc31f9-4443-ff74-241f-45dfa8c581c2%40ccs.neu.edu.


Re: [racket-users] How to convert String to Integer

2020-02-11 Thread Ryan Culpepper
What should `(myconversion "apple")` return?
What should `(myconversion "12.3")` return?
What does `string->number` do in each of those cases?

Ryan


On Tue, Feb 11, 2020 at 11:34 AM Alain De Vos 
wrote:

> I tried the following function to conver a String to an Integer.
>
> #lang typed/racket
> (: myconversion (-> String Integer))
> (define (myconversion str)
>   (string->number str))
>
> The error given is :
> Type Checker: type mismatch
>   expected: Integer
>   given: (U Complex False) in: (string->number str)
>
> I guess this is because a number is not an Integer.
>
> How to proceed?
>
> I found the following code on internet , but this looks like a real
> overkill for this simple problem ,
>
> (: numerical-char->integer (-> Char
>Integer))(define (numerical-char->integer char)
>   (let ([num (- (char->integer char) 48)]) ; 48 = (char->integer #\0)
> (if
>  (or (< num 0) (> num 9))
>  (raise 'non-numerical-char #t)
>  num)))
> (: string->integer (-> String
>Integer))(define (string->integer str)
>   (let ([char-list (string->list str)])
> (if (null? char-list)
> (raise 'empty-string #t)
> (foldl
>  (λ([x : Integer] [y : Integer])
>(+ (* y 10) x))
>  0
>  (map numerical-char->integer char-list)
>
> --
> 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/4a13bb2e-3107-4c5f-aee6-6d29e493c040%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/CANy33q%3D%2BjTWLBbNa-DW_g0M-Pba2SRJMMPhu8uGHfXHV0JRJ%2Bg%40mail.gmail.com.


Re: [racket-users] Separate compilation/caching for Scribble?

2020-03-25 Thread Ryan Culpepper
You can use `raco make` (or `raco setup` for docs of installed packages) to
compile the Scribble files, but that won't compile the examples. Those are
dynamically evaluated when the Scribble documents are run.

For `make-log-based-eval`, are you using a separate evaluator (and separate
log file) for each Scribble file?

Ryan

On Wed, Mar 25, 2020 at 7:56 PM William J. Bowman 
wrote:

> Does Scribble support separate compilation or some kind of caching and I'm
> just
> missing it?
>
> I'm building a multi-page website using Scribble, with many @examples that
> take
> a while to run.
> If I touch *any page*, all the other pages have to rebuild, re-running the
> long
> running examples.
>
> I've hacked up a caching system for examples using make-log-based-eval and
> with-cache, but it's completely unreliable, occasionally giving 'could not
> replay log' when nothing has changed in that file.
>
> Am I missing something?
>
> --
> William J. Bowman
>
> --
> 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/20200325185631.GK26958%40williamjbowman.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/CANy33q%3DZ7nfiF%3DqntgSnaD%3D8%2B4L%3DR4CTb73K_T8mzfoXJxXrFQ%40mail.gmail.com.


Re: [racket-users] Separate compilation/caching for Scribble?

2020-03-25 Thread Ryan Culpepper
I'm not clear on what `with-cache` is doing in this setup, but it seems
like a potential source of errors. If the goal is to automatically use
`'replay` if the log file exists and `'record` otherwise, why not do the
following?

(make-log-based-eval the-log-file (if (file-exists? the-log-file)
'replay 'record))

Ryan


On Wed, Mar 25, 2020 at 8:57 PM William J. Bowman 
wrote:

> On Wed, Mar 25, 2020 at 08:51:18PM +0100, Ryan Culpepper wrote:
> > You can use `raco make` (or `raco setup` for docs of installed packages)
> to
> > compile the Scribble files, but that won't compile the examples. Those
> are
> > dynamically evaluated when the Scribble documents are run.
> Yeah, I was thinking of "compilation" as in caching the output document
> from
> each module.
>
> > For `make-log-based-eval`, are you using a separate evaluator (and
> separate
> > log file) for each Scribble file?
> Yes. However, I'm using `with-cache` and a wrapper to detect whether a
> cache
> file exists (separate cache file each evaluator), and use 'replay mode if
> the
> cache file exists, so I don't have to manually switch to 'replay mode, or
> manually re-record if I alter an example (instead, just clear the cache).
>

-- 
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/CANy33qnePkB3LERw-s8kmGWi4e%2B0T%3D%3D0Tgy%3Da5mHE9odkpFFrQ%40mail.gmail.com.


Re: [racket-users] Make your computer talk in Racket on Windows in 5 lines

2020-05-16 Thread Ryan Culpepper
I wrote a little flashcard program in Racket to help myself learn Czech
vocabulary (here: https://github.com/rmculpepper/racket-jazyk), and when
run on a Mac it uses `say` for audio. IIRC, I had to install extra "voice"
packages for Czech, but that consisted of clicking a few buttons in
Settings.

Ryan

On Sat, May 16, 2020 at 8:21 PM Sorawee Porncharoenwase <
sorawee.pw...@gmail.com> wrote:

> On Mac, there’s a say command, so this would do it.
>
> (system "say \"hello world\"")
>
> When I had a Linux machine, I recalled using a command named espeak,
> which is similar to say on Mac.
>
> On Sat, May 16, 2020 at 11:15 AM Sam Phillips 
> wrote:
>
>> Stephen De Gabrielle and I are wondering if any Mac or Linux users
>> have similar short programs to make their computer talk.
>>
>>
>> https://www.reddit.com/r/Racket/comments/gkz3yi/make_your_computer_talk_in_racket_on_windows_in_5/
>>
>> Cheers,
>> Sam
>>
>> ->8->8-
>> #lang racket/base
>>
>> (require ffi/com)
>>
>> (define voice
>>   (com-create-instance "SAPI.SPVoice"))
>>
>> (com-invoke voice "Speak" "hello world")
>>   ->8->8-
>>
>> --
>> 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/CAHsjV0zG4mFbryy4uYWHS-%3DvP%3D10_bCjFxBR5wS%2BUkaFuLkx5Q%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/CADcuegvCXTUCVBqA2WcViWC1AjbMvdbJuE_NbF0y5%2BHUzKjc2g%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/CANy33qntsqwCjfw8RWLMmigVBpznYaJVwr0maXZL2-q8WXJHTA%40mail.gmail.com.


Re: [racket-users] Incorporating Markdown documents into Scribble

2020-09-13 Thread Ryan Culpepper
What should the splicing version do in the following case:

  some text
  @(markdown-inline "file-with-sections.md")
  some trailing text

In particular, what should happen to the trailing text? Scribble doesn't
have a notion of returning to the top-level after a section. One
possibility would be to append it to the final subsection of
"file-with-sections.md"; another would be to create a "Continuation"
section to hold trailing text. Both of those seem bad to me; if the
trailing text contained another inline markdown file with sections, the
second file's sections would be at a deeper section level than the first
file's sections.

Or instead of mapping inline-Markdown sections to Scribble sections, you
could traverse the Markdown result and convert the Markdown section headers
to Scribble styled paragraphs instead. But then you would lose the benefits
of Scribble sections (eg, secref, TOC).

Ryan



On Sat, Sep 12, 2020 at 3:14 PM Shriram Krishnamurthi 
wrote:

> I need a little help with `decode` vs `decode-flow` in Scribble. (Also,
> this thread is about a question I wasn't able to find answered anywhere, so
> hopefully it will lead to a solution that others can also use.)
>
> Sometimes it's really useful to incorporate Markdown-formatted content
> into the middle of a Scribble document. (Let's not argue about this,
> please!) My assumption is that the Markdown document lives in a separate
> file (I'm not trying to do any clever textual inlining). Thanks to Greg
> Hendershott, I'm almost there! I use
>
> https://github.com/greghendershott/markdown
>
> Here are two versions of the inlining function:
>
> @(require markdown markdown/scrib scribble/decode)
>
> @(define (markdown-inline file)
>(decode-flow
>(xexprs->scribble-pres
>  (with-input-from-file file read-markdown
>
> @(define (markdown-part file)
>(decode
>(xexprs->scribble-pres
>  (with-input-from-file file read-markdown
>
> As a practical matter, `markdown-part` needs to take lots of extra
> arguments to create the appropriate part instead of just producing a
> title-less section. More importantly, you often don't want a separate
> section: you just want to "splice" the content into the current context.
>
> `markdown-inline` works great for this purpose, *except* if the included
> Markdown file contains any sections of its own, e.g.,
>
> This is text.
>
> > Lorem ipsum
>
> # Section
>
> ## Subsection
>
> Then I get this error:
>
> decode-flow: contract violation
>
>   expected: pre-flow?
>
>   given: (part-start 0 #f '((part "section")) (style #f '()) '("Section"))
> Any recommendations on how to create a "splicing" version that also
> respects having sub-sections, or is that impossible? (I've tried pulling
> out parts of the `part`, etc., but without success.)
>
> Thanks!
>
> Shriram
>
> --
> 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/3f0b1012-783d-464a-a0ed-66d3f29f8893n%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/CANy33qndj%3DZo%3DTFejErwh%3DiEMd8XG34HZu0kv3dEBQumr%2Bwgjg%40mail.gmail.com.


Re: [racket-users] Incorporating Markdown documents into Scribble

2020-09-13 Thread Ryan Culpepper
Okay, if I understand correctly, you would expect the trailing text in my
example to be appended to the final subsection from the file.

In that case, does it work if you simply remove the call to `decode-flow`
from the definition of `markdown-inline`? Then the function would
just return a list of pre-parts to be spliced into the enclosing document.

If you want to make the Markdown sections properly nest under the current
section, you would probably need to adjust the depths of all `part-start`
instances in the result. For example, if you use `markdown-inline` within a
subsection, you would probably want to increase the depth of all
part-starts by 2. I don't know if it's possible to find the current depth
automatically, so you might need to make it an extra argument to
`markdown-inline`.

I also would have expected calling `decode` and then extracting and
appending the blocks and parts to work, although it would have different
behavior wrt the trailing text. Your original message said that didn't
work, but how did it fail?

Ryan


On Sun, Sep 13, 2020 at 1:50 PM Shriram Krishnamurthi 
wrote:

> It's useful to have this behave like a `#include`. There are settings
> where you want to have a non-Scribble person author things that go "in the
> middle"; you want to think of this as just a more convenient way of writing
> what you'd have written in Scribble.
>
> I realize there's presumably a closure issue (`section` isn't going to
> come from the including file), and for that you probably want a different
> include form as well.
>

-- 
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/CANy33qm49ME9vVKLiYXSRGPgd8Xf0CHnzZpETyajtWrg48VGDw%40mail.gmail.com.


Re: [racket-users] difference in struct printing from default #:transparent versus make-constructor-style-printer

2020-09-03 Thread Ryan Culpepper
The Racket printer uses a separate property to determine whether a struct
is quotable. If you add

  #:property prop:custom-print-quotable 'never

to the declarations of Int2 and Prim2, your program should produce the
output you expect. I'll add a note to the docs for
make-constructor-style-printer.

Ryan


On Wed, Sep 2, 2020 at 10:07 PM Jeremy Siek  wrote:

> I'm seeing some bad behavior from make-constructor-style-printer when
> there are lists mixed in with the structs. It seems to switch from print
> mode to
> write mode when going under a list. Whereas the default printer for
> transparent structs gets this right. The following program demonstrates the
> difference/problem.
> Any thoughts on how to get the make-constructor-style-printer to behave
> properly?
>
> #lang racket
> (require racket/struct)
>
> (struct Int1 (value) #:transparent)
> (struct Prim1 (op arg*) #:transparent)
>
> (struct Int2 (value) #:transparent
>   #:methods gen:custom-write
>   [(define write-proc
>  (make-constructor-style-printer
>   (lambda (obj) 'Int2)
>   (lambda (obj) (list (Int2-value obj)])
> (struct Prim2 (op arg*) #:transparent
>   #:methods gen:custom-write
>   [(define write-proc
>  (make-constructor-style-printer
>   (lambda (obj) 'Prim2)
>   (lambda (obj) (list (Prim2-op obj) (Prim2-arg* obj)])
>
> (define p1 (Prim1 '+ (list (Int1 1) (Int1 2
> (print p1)(newline)
>
> (define p2 (Prim2 '+ (list (Int2 1) (Int2 2
> (print p2)(newline)
>
> The output is:
>
> (Prim1 '+ (list (Int1 1) (Int1 2)))
> (Prim2 '+ '(# #))
>
> -Jeremy
>
> --
> 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/bdeb1052-ea25-4dc0-8292-a13d15bf7870n%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/CANy33qkqaRZNAya8XAeUQ6AOg_WwjgEa-ccMqvq5_GMkGF%3D1Qg%40mail.gmail.com.


Re: [racket-users] Hygiene for a curried macro

2020-09-30 Thread Ryan Culpepper
Yes, the behavior you're seeing is a consequence of hygiene, and you should
see the same behavior in other Scheme implementations.

When the expander gets to the `let-third` call, there is a `var` identifier
in the macro's template that is used as a binder, and there is a `var`
identifier in the macro's argument that is used as a reference. Hygiene
says that a macro-introduced binder does not capture a macro-argument
reference.

The fact that they both originate from the *same* identifier given to
`let-second-and-create-let-third` is irrelevant. The hygiene condition for
`let-third` requires that they be treated differently. After all, in
"ordinary" hygienic macros, the identifiers are the same also, but the fact
that one is in the macro template and one is passed to the macro
distinguishes them.

If you want to do higher-order macro programming, the lesson is that
hygienic macros are not *pure* abstractions for syntax in the same way that
Racket's closures are pure abstractions for computation. That becomes a
problem when you want to generate macro definitions that contain
identifiers that they use as binders.

Philip provided one solution (and thanks for the macro stepper plug!). The
other solution is to pass `var` as an argument to `let-third`.

Ryan


On Wed, Sep 30, 2020 at 8:46 AM rocketnia  wrote:

>
> Hi all,
>
> I've been experimenting with a custom system of managed local variables,
> and I came up with a hygiene test case that was failing. So then I tried
> the same test case with plain Racket variables, and it failed that way
> too. Here's a minimalistic example.
>
> Basically, this is a curried macro: The user supplies a variable and gets
> a macro out, and then the user calls that macro. Can the second macro
> bind the variable the user supplied to the first one? I thought it would
> be able to, but this doesn't currently seem to be case on Racket v7.8
> [cs].
>
> Could anyone explain what's going on with this? Is there a workaround if
> I want to write this kind of macro? Should I file a bug in Racket? This
> looks pretty close to R5RS Scheme, so I wonder what the situation in the
> broader Scheme world is like, too.
>
>
> #lang racket
>
> (require rackunit)
>
> (define-syntax-rule
>   (let-second-and-create-let-third var let-third body-of-let-second)
>   (let-syntax ([let-third
>  (syntax-rules ()
>[(let-third body-of-let-third)
> (let ([var "third"])
>   body-of-let-third)])])
> ; This binding shows that the first macro *does* manage to bind
> ; the given variable, even though the second macro doesn't.
> (let ([var "second"])
>   body-of-let-second)))
>
> (check-equal?
>   (let ([x "first"])
> (let-second-and-create-let-third x let-third
>   (let-third
> x)))
>   "third"
>   "Test that a macro generated by a macro can bind a variable the user
> supplied to the generator macro")
>
> ; FAILURE
> ; actual: "second"
> ; expected: "third"
>
>
> You can also find this code in Gist form here:
> https://gist.github.com/rocketnia/cb83da2cfcddbf614dfe1dfc5e08792c
>
> Thanks in advance for any insight you have about what's going on here.
>
> - Nia
>
> --
> 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/71daa8da-25cf-426b-b709-ee9ed25b53f0n%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/CANy33qnRzmLYTLpZMEPFOabE9Hr-tk90hiaWbNcoKDZymw6kbw%40mail.gmail.com.


Re: [racket-users] querying MS SQL Server with db-lib (ODBC)

2020-09-19 Thread Ryan Culpepper
The last time I tested connecting to MS SQL Server on Windows (several
years ago), I think I was able to connect using some drivers but not
others. I was simultaneously trying to figure out authentication and the
connection string format, so once I got a working configuration I stopped
investigating. Lately I've been testing using the Docker image on Linux.

I've attached a program you can run to find out where the connection
process hangs. If you can report the results of running the program that
should help narrow down the problem.

Ryan


On Sat, Sep 19, 2020 at 12:25 AM Jin-Ho King  wrote:

> Does anyone have experience using Racket to query a MS SQL Server? I'm
> attempting to use the db-lib package (https://docs.racket-lang.org/db/)
> and odbc-driver-connect, but running the method just hangs, with no
> feedback. By contrast, using the same connection string, I can successfully
> connect using python and pyodbc.
>
> Any suggestions or tips would be appreciated!
>
> --
> 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/58e03456-b76e-4212-a170-82e1fc4fb178n%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/CANy33qmKHvD7NrR7N5NZXCsGxy2beuPTw%2BPqDHsvmJo5t%3DLqgA%40mail.gmail.com.


test-odbc.rkt
Description: Binary data


Re: [racket-users] Re: local variables are hyperlinked in scribble/manual

2020-05-25 Thread Ryan Culpepper
You can also use make-element-id-transformer, like this:

(define-syntax SET
  (make-element-id-transformer
   (lambda _ #'(racketvarfont "set"

Then Scribble will automatically replace SET within rendered code with the
element expression above.

Another trick is to break the for-label binding by introducing a local
binding that shadows it. For example, if you write

(let ([set #f])
  (racket set))

then the occurrence of `set` within the `racket` form isn't linked to `set`
from racket/set. This trick relies on being able to put a let around the
occurrences you don't want linked but not the ones that you do want linked,
so it might not work in all cases.

Ryan


On Mon, May 25, 2020 at 4:55 PM Ryan Kramer 
wrote:

> My favorite way to avoid this problem is simply to choose another name, or
> use `except-in` to avoid importing `set` for-label. But if you must use the
> name `set` and you want it linking to racket/set most of the time (but not
> this time), here is a technique I've used in the past:
>
> #lang scribble/manual
>
> @(require (for-label racket) scribble/eval
>   (for-syntax racket
>   syntax/parse))
>
> @(define-for-syntax (replace-helper stx orig-sym new-sym)
>(let ([content (syntax-e stx)])
>  (cond
>[(list? content)
> (datum->syntax stx
>(map (λ (child) (replace-helper child orig-sym
> new-sym))
> content)
>stx stx)]
>[(equal? orig-sym content)
> (datum->syntax #f new-sym stx #f)]
>[else
> stx])))
>
> @(define-syntax (replace stx)
>(syntax-parse stx
>  [(_ [orig:id new:id] body:expr)
>   (replace-helper #'body (syntax-e #'orig) (syntax-e #'new))]))
>
> @(replace
>   [SET set]
>   @interaction[
>  (let ((SET 1)) (add1 SET))])
>
>
> On Sunday, May 24, 2020 at 11:26:54 AM UTC-5, jos.koot wrote:
>>
>> Hi,
>>
>> I have:
>>
>>
>>
>> #lang scribble/manual
>>
>> @(require (for-label racket) scribble/eval)
>>
>> @interaction[
>>
>> (let ((set 1)) (add1 set))]
>>
>>
>>
>> I prepare a HTML document with DrRacket (in Windows 10).
>>
>> Works, but local variable set is hyperlinked to procedure set in the
>> documents (racket/set). I would like this variable to be typeset as any
>> other local variable. How can I do that without loosing the hyperlink where
>> I do mean the procedure from racket/set ?
>>
>>
>>
>> Thanks, Jos
>>
> --
> 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/ffd4f155-ee18-409d-b92f-9450d976220f%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/CANy33qk3Q3F6uLx9_Y%2BRNUb4j-z4DEuH3_%2BEgSc4evnNHpoXgg%40mail.gmail.com.


Re: [racket-users] Re: Exception throwing in web-server

2020-05-25 Thread Ryan Culpepper
As I understand the HTTP protocol (that is, some but not lots), the most
reasonable thing for the server to do if it discovers an error after the
status code has been sent seems to be to just hang up and let the client
realize that *something* went wrong. I don't mean just truncate the output;
I mean the server should say "here comes another chunk" and then close the
TCP connection, so it cannot be mistaken for a valid response. (The servlet
should probably make a note so the next request doesn't just fail in
exactly the same way.)

Is there are reason not to change the web server to do this automatically?

Ryan


On Mon, May 25, 2020 at 7:30 PM Norman Gray 
wrote:

>
> Thank you, Brian and Jesse, for your thoughts on this.  There may still
> be an exception problem here, though.
>
> (and sorry for being sluggish to respond)
>
> On 16 May 2020, at 20:16, Norman Gray wrote:
>
> > Now, in tracking this down I can see that I have a wrong design here:
> > the servlet has started producing output before the exception is
> > thrown, so it's at this point really too late for me to be throwing
> > errors and producing custom 5xx error pages.
>
> Brian said:
>
> > I think you need to decide when to stream, and when not to stream. In
> > my
> > web framework, most requests involve computing the entire response
> > string
> > prior to calling (response ...), so if an error is encountered, I can
> > send
> > an error response instead of a success response.
>
> and Jesse:
>
> > I suggest thinking of a servlet as a response builder, and, if
> > possible, to
> > delegate serialization of the response (output-response & friends)
> > till
> > after a response? value has been created.
>
> I agree this is the right way of thinking about things here, and it's
> reassuring to have that confirmed.  Part of what was confusing me was
> that it's not particularly clear from the documentation what
> serve/servlet's #:servlet-responder is there for.  It appears to be just
> an odd spelling of 'exception handler', as far as I can tell from the
> code.
>
> Indeed it's true that, once the HTTP status code has hit the wire,
> there's no provision in the protocol to change one's mind and come up
> with a different status (it's possible that forthcoming HTTP/3, with its
> concern to multiplex content on the wire, will come up with something
> here, but I haven't examined HTTP/3 in detail, and I'd be surprised if
> this was one of its concerns).
>
> However, a problem comes when the serialiser _does_ produce a 'real'
> exception -- meaning an exception that isn't one that I expected it to
> produce.  In that case, the response.rkt code just hangs.
>
> Consider:
>
>  #lang racket/base
>  (require web-server/servlet
>   web-server/servlet-env)
>
>  (define (make-response/output writer)
>(λ (req)
>  (response 200 #"OK" (current-seconds) #"text/plain" '()
> writer)))
>
>  (define my-app/simple
>(make-response/output
> (λ (op)
>   (display "hello" op
>  (define my-app/error
>(make-response/output
> (λ (op)
>   (error "Oooops")
>   (display "Hello" op
>  (define my-app/handlers
>(make-response/output
> (λ (op)
>   (with-handlers ((exn:fail? (λ (ex) (display "Eeek!" op
> (error "Oooops")
> (display "Hello" op)
>
>  (serve/servlet my-app/error
> #:servlet-regexp #rx""
> #:command-line? #t)
>
> If we run this server, and dereference , for
> example with curl, then the retrieval simply hangs.
>
> It appears that the handler in
> web-server-lib/web-server/response.rkt:148 is supposed to handle this
> case, but it appears not to.  I think it's possible the handler should
> be in to-chunker-t instead or as well.
>
> This means that a further possibility is to have an exception handler
> within the serialiser, and handle exceptions appropriately there (as in
> my-app/handlers above).  However all this means that a carefully-written
> servlet _must_ have such handlers, if an inadvertent exception in the
> serialiser procedure isn't to stall a client.
>
> Best wishes,
>
> Norman
>
>
> --
> Norman Gray  :  https://nxg.me.uk
> SUPA School of Physics and Astronomy, University of Glasgow, UK
>
> --
> 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/AB2357DF-5A41-429F-A7BB-7B4321EEDBE3%40glasgow.ac.uk
> .
>

-- 
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 

Re: [racket-users] Exception throwing in web-server

2020-05-25 Thread Ryan Culpepper
I'm assuming chunked Transfer-Encoding, which is IIRC what the Racket web
server uses for unknown-length payloads. If the server hasn't committed to
chunked encoding (by sending the header), then it probably hasn't sent the
status code either. So truncation is definitely detectable.

RFC 7230 Section 6.3.1 and 6.3.2 give more specific guidance than "do the
right thing", as I read it. I would summarize it as: Only automatically
retry if you know that the operation is idempotent (6.3.1) or hadn't been
processed yet (6.3.2), and only automatically retry once; otherwise, kick
the error up a level and let them decide.

RFC 7230 Section 9.6 (Message Integrity) mentions using "length or
chunk-delimited framing to detect completeness", so I think using a chunk
framing violation to signal incompleteness is fair game.

Re semantics: I haven't read that RFC yet, but generally, *semantics* only
apply to *syntactically* well-formed things. So introducing a syntax error
(the chunk framing violation) is a good way of saying "nevermind, don't
even *try* to interpret this payload", given that there are no other
options.

Re TCP: It's not a TCP error, and the client shouldn't assume it was.
Section 6.3.1 starts with "Connections can be closed at any time, with or
without intention." And the idea generalizes to any connection-oriented
transport layer. (Hanging up the phone isn't a phone error, and if you're,
say, a telemarketer, you probably wouldn't even consider the possibility
that it was a network failure.)

So I still think closing the connection after making the response
syntactically valid is a good default for the Racket web server.

BTW, if you control the client, you could also use "trailing headers" (see
Section 4.1), but the internet tells me that browsers don't support them.

Ryan


On Mon, May 25, 2020 at 9:48 PM Norman Gray 
wrote:

>
> Ryan and Matthew, hello.
>
> On 25 May 2020, at 19:43, Ryan Culpepper wrote:
>
> > As I understand the HTTP protocol (that is, some but not lots), the
> > most
> > reasonable thing for the server to do if it discovers an error after
> > the
> > status code has been sent seems to be to just hang up and let the
> > client
> > realize that *something* went wrong. I don't mean just truncate the
> > output;
> > I mean the server should say "here comes another chunk" and then close
> > the
> > TCP connection, so it cannot be mistaken for a valid response. (The
> > servlet
> > should probably make a note so the next request doesn't just fail in
> > exactly the same way.)
>
> I have spent a fair amount of quality time with the HTTP RFCs, and I'm
> surprised I can't think of an answer to this off the top of my head.
>
> Looking through RFC 7230, however (RFCs 7230--5 replace RFC 2616), we
> find in Sect.3.3.3 'Message Body Length',
>
> Since there is no way to distinguish a successfully completed,
> close-delimited message from a partially received message
> interrupted
> by network failure, a server SHOULD generate encoding or
> length-delimited messages whenever possible.  The close-delimiting
> feature exists primarily for backwards compatibility with HTTP/1.0.
>
> If a response includes a Content-Length header, then truncation would be
> detectable, if not, not.
>
> This passage is talking about network failure, but I think the
> server-failure we're talking about here is morally similar.  RFC 7230
> Sect 6.3.2, though it's talking about a slightly different thing, also
> conceives of the notion of 'partial failure conditions' whilst being
> vague about what these are or what a client should do (the implication
> is that the client should... do the right thing).
>
> HTTP is generally deliberately rather vague about the payload -- the
> representation of the named resource -- and RFC 7231 Sect.3.3 'Payload
> Semantics' is a mere four paragraphs long.  It includes text
>
> For example, the payload of a
> 200 (OK) response to GET (Section 4.3.1) represents the current
> state
> of the target resource, as observed at the time of the message
> origination date
>
> There's quite a lot that doesn't say, -- it's even prefaced by 'for
> example'.  It doesn't even say that the payload _accurately_ represents
> the state of the resource.  That sounds like quibbling, but it fits in
> with a general idea of 'the client gets what it's given, and it'll like
> it'.
>
> However vague this is, I think this would not be consistent with a
> server deliberately causing a TCP error, in a protocol at a lower layer
> than HTTP.  Apart from anything else (a) the HTTP transaction might not,
> in principle, be running over TCP, and (b) it would be a lie, since the
> problem was

Re: [racket-users] What is the purpose of "compact" code paths in print.c?

2020-05-28 Thread Ryan Culpepper
Based on a quick look, I believe it has to do with serializing compiled
code, including quoted values embedded in compiled code. Serializing
compiled code uses the same entry point as the other printing functions.
For example, try this:

(write (compile '(quote (1 2 3

and compare the output against the contents of some .zo file.

You probably don't want to make any changes that affect the behavior when
compact is true, unless you're trying to add support for a new quotable and
readable data type. In that case, ask Matthew for help :)

Ryan


On Thu, May 28, 2020 at 8:01 PM Thomas Dickerson <
thomas_dicker...@alumni.brown.edu> wrote:

> I'm working on an enhancement for write/print/display, and thought I had
> it all implemented in io/print/main.rkt before realizing that code is only
> used for Racket-CS.
>
> Now I'm working on making equivalent changes in print.c for the
> traditional implementation, and that code is substantially more complex.
> Among other things, print has a bunch of checks against a variable called
> "compact", but I can't find any comments (either in the source or in the
> git log) as to what its for / when its used.
> Can anyone comment?
>
> --
> 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/1a2b4d7d-bdf7-4cbb-bf9e-6565c7bfec28%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/CANy33qnYbuqks3NKbPXj0y6F_68nAp2bouHa386bqzHNmc07FA%40mail.gmail.com.


Re: [racket-users] querying MS SQL Server with db-lib (ODBC)

2020-09-19 Thread Ryan Culpepper
So, it seems that there are two problems: (1) the connection fails (even
though it works with pyodbc) and (2) retrieving the diagnostic information
after the error hangs with the MS driver. I don't see an obvious reason for
either problem, but I have two thoughts.

Does your connection string have any non-ASCII characters? A difference in
string conversion is one of the few things I can imagine distinguishing
odbc-driver-connect's behavior from pyodbc, since IIUC both just pass the
connection string to SQLDriverConnect without any processing. Also,
double-check backslashes.

It looks like you're using Racket CS. Could you try the program with Racket
BC too? It's possible that there's some difference in the FFI's behavior
between the two versions that the db library is not accounting for.

Ryan


On Sat, Sep 19, 2020 at 10:06 PM Jin-Ho King  wrote:

> Hi Ryan, thanks so much for your suggestions. Here is the output from
> running your program with my original connection string, which works in
> python using pyodbc:
>
> Allocating env handle... done: 0
> 0
> Setting ODBC version... done: 0
> 0
> Allocating db handle... done: 0
> 0
> Connecting... done: -1
>
>
> This is where it hangs.
>
> Based on your suggestions about trying different drivers, I tried
> switching drivers from the "ODBC Driver 17 for SQL Server” that I had been
> using to the FreeTDS driver the example in your program uses. I was able to
> successfully connect using the FreeTDS driver in python using pyodbc. Using
> the same connection string, I ran your program again. This time, running
> your program didn't hang, but the output was not promising either:
>
> Allocating env handle... done: 0
> 0
> Setting ODBC version... done: 0
> 0
> Allocating db handle... done: 0
> 0
> Connecting... done: -1
> odbc-driver-connect:
>   SQLSTATE:
>   context...:
>.../generic/interfaces.rkt:170:0: raise-sql-error
>.../odbc/connection.rkt:781:0: handle-status*
>call-with-values
>call-in-empty-metacontinuation-frame
>body of "/Users/jinho/git/eoddata/test-odbc.rkt"
>temp35_0
>run-module-instance!
>perform-require!
>namespace-require+
>proc
>call-in-empty-metacontinuation-frame
>thunk_10
>call-in-empty-metacontinuation-frame
>call-with-empty-metacontinuation-frame-for-swap
>
>
> I also confirmed using odbc-driver-connect directly that no connection is
> actually made. Do you have any other suggestions? Thanks again!
>
>
> --
> "Ad astra per alia porci"
>
> On Sep 19, 2020, at 8:12 AM, Ryan Culpepper 
> wrote:
>
> The last time I tested connecting to MS SQL Server on Windows (several
> years ago), I think I was able to connect using some drivers but not
> others. I was simultaneously trying to figure out authentication and the
> connection string format, so once I got a working configuration I stopped
> investigating. Lately I've been testing using the Docker image on Linux.
>
> I've attached a program you can run to find out where the connection
> process hangs. If you can report the results of running the program that
> should help narrow down the problem.
>
> Ryan
>
>
> On Sat, Sep 19, 2020 at 12:25 AM Jin-Ho King  wrote:
>
>> Does anyone have experience using Racket to query a MS SQL Server? I'm
>> attempting to use the db-lib package (https://docs.racket-lang.org/db/)
>> and odbc-driver-connect, but running the method just hangs, with no
>> feedback. By contrast, using the same connection string, I can successfully
>> connect using python and pyodbc.
>>
>> Any suggestions or tips would be appreciated!
>>
>> --
>> 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/58e03456-b76e-4212-a170-82e1fc4fb178n%40googlegroups.com
>> <https://groups.google.com/d/msgid/racket-users/58e03456-b76e-4212-a170-82e1fc4fb178n%40googlegroups.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/CANy33qkuK%2B%2Beg8_vZT0bE5NfvzXxB52uGzOcOWumA7DK4Zfu-Q%40mail.gmail.com.


Re: [racket-users] Help implementing an early return macro

2020-10-28 Thread Ryan Culpepper
This is a nice example of a macro design pattern that I think of as
"partial expansion with trampolining". You don't need to deal with the
internal definition context API, because you can return definitions to the
macro expander, let it handle their interpretation, and then resume your
work. Here's an implementation sketch:

1. First, make sure you're in an internal definition context:
(guarded-block form ...) => (let () (guarded-block* form ...)). The
guarded-block* helper macro has the invariant that it is always used in
internal definition context.
2. If guarded-block* has at least one form, it partially expands it, using
a stop list containing guard and Racket's primitive syntactic forms. Then
it analyzes the partially-expanded form:
- If it is a begin, it recurs with the begin's contents appended to the
rest of its argument forms.
- If it is a define-values or define-syntaxes form, it expands into (begin
defn (guarded-block* form-rest ...)). The macro expander interprets the
definition, adds it to the environment, etc. Then guarded-block* resumes
with the rest of the forms (in the same definition context).
- If it is a guard form, then you transform its contents and the rest of
the forms into a cond expression, with a recursive call in the right place.
- Anything else, assume it's an expression, and trampoline the same as for
a definition.

Also, because you're calling local-expand, you should disarm the result of
local-expand and then call syntax-protect on the syntax you produce. If you
don't disarm, then you might get "cannot use identifier tainted by macro
transformer" errors. If you don't call syntax-protect, your macro can be
misused to circumvent other macros' protection.

I've attached an implementation.

Ryan


On Wed, Oct 28, 2020 at 11:54 AM Jack Firth  wrote:

> So I'm a little tired of writing code like this:
>
> (define x ...)
> (cond
>   [(take-shortcut? x) (shortcut x)]
>   [else
>(define y (compute-y x))
>(cond
> [(take-other-shortcut? x y) (other-shortcut x y)]
> [else
>  (define z ...)
>  (cond ...)])])
>
> That is, I have some logic and that logic occasionally checks for
> conditions that make the rest of the logic irrelevant, such as an empty or
> false input or something else that should trigger an early exit. Each check
> like this requires me to write a cond whose else clause wraps the
> remainder of the body, leading to an awkward nesting of cond forms. I
> don't have this issue when the early exits involve raising exceptions: in
> those cases I can just use when and unless like so:
>
> (define x ...)
> (unless (passes-check? x) (raise ...))
> (define y ...)
> (unless (passes-other-check? x y) (raise ...))
> (define z ...)
> ...
>
> I'm aware of a few macros in the racket ecosystem that try to solve this
> problem. For example, Jay wrote a blog post
>  that creates a
> condd form that's like cond but allows embedded definitions using a #:do
> keyword. I've also seen various approaches that use escape continuations to
> implement the early exit. There's drawbacks I'm not happy about however:
>
>-
>
>For cond-like macros that allow embedded definitions, it looks too
>different from regular straight-line Racket code. I like my function bodies
>to be a sequence of definitions and expressions, with minimal nesting, just
>like the when and unless version above. I don't have to use a keyword
>or extra parentheses to signal whether a form is a definition or a when
>/ unless check in error-raising code, why should I have to do that in
>code that uses early returns?
>-
>
>Continuation-based solutions impose a nontrivial performance penalty
>and have complex semantics. I don't like that the generated code behaves
>differently from the cond tree I would normally write. What happens if
>I stick an early exit inside a lambda? Or a thread? What if I set up a
>continuation barrier? Does that matter? I don't know and I don't want to
>think about that just to write what would be a simple if (condition) {
>return ... } block in other languages.
>
> So I wrote a basic macro for this and I have some questions about how to
> make it more robust. The macro is called guarded-block and it looks like
> this:
>
> (guarded-block
>   (define x (random 10))
>   (guard (even? x) else
> (log-info "x wasn't even, x = ~a" x)
> -1)
>   (define y (random 10))
>   (guard (even? y) else
> (log-info "y wasn't even, y = ~a" y)
> -1)
>   (+ x y))
>
> Each guard clause contains a condition that must be true for evaluation
> to proceed, and if it isn't true the block takes the else branch and
> finishes. So the above would expand into this:
>
> (block
>   (define x (random 10))
>   (cond
> [(not (even? x))
>  (log-info "x wasn't even, x = ~a" x)
>  -1]
> [else
>  (define y (random 10))
>  (cond
>[(not (even? y))
> 

Re: [racket-users] ask the type of a value

2020-08-03 Thread Ryan Culpepper
but beware, for

  > (for-each
 (lambda (x) (printf "~a: ~a\n" (~v x #:min-width 28) (struct->vector
x)))
 (list "hello" (let () (struct string (n)) (string 5
  "hello" : #(struct:string ...)
  #   : #(struct:string ...)

Ryan


On Mon, Aug 3, 2020 at 6:07 PM Laurent  wrote:

> and yet:
>
> > (for-each
>(λ (x) (printf "~a: ~a\n" (~v x #:min-width 28) (struct->vector x)))
>`(hello "hello" 43110 #f #(h e l l o) #"hello" (h e l l o)
>,(new frame% [label ""])))
>
> hello   : #(struct:symbol ...)
> "hello" : #(struct:string ...)
> 43110   : #(struct:fixnum-integer ...)
> #f  : #(struct:false ...)
> #(h e l l o): #(struct:vector ...)
> #"hello": #(struct:byte-string ...)
> (h e l l o) : #(struct:pair ...)
> #(struct:object:frame% ...) : #(struct:object:frame% ...)
>
> ;)
>
>
> On Mon, Aug 3, 2020 at 4:20 PM Alexis King  wrote:
>
>> In general, the answer is “no,” mostly because it’s not clear in Racket
>> what “the type of a value” means. It’s difficult to come up with a
>> definition that would be useful enough to satisfy your criterion of not
>> “having to guess it first.” Consider: suppose you had a hypothetical
>> `type-of` operation that returned a value’s type:
>>
>> (type-of 'hello) ; => 'symbol
>> (type-of "hello") ; => 'string
>>
>> Now suppose you apply type-of to a value you know nothing about and get
>> back 'widget. Well, you don’t know what a widget is, so that didn’t
>> actually get you any further from where you started: you still don’t know
>> what to do with the value.
>>
>> Furthermore, types are not actually disjoint. You can write a struct
>> definition with properties like prop:procedure and prop:evt, and if a
>> struct has both, should type-of return the struct’s name, 'procedure, or
>> 'evt? It’s not really clear. You might be able to come up with some more
>> sophisticated system with (potentially multiple) inheritance that could
>> capture these relationships, but I can say with confidence that no such
>> system currently exists in Racket.
>>
>> Alexis
>>
>> > On Aug 3, 2020, at 09:19, Hendrik Boom  wrote:
>> >
>> > In plain, untyped Racket:
>> >
>> > It is possible to ask if a value is a symbol with symbol?
>> > It is possible to ask if a value is a string with string?
>> > etc.
>> >
>> > Is there a way to ask the type of a value without having to guess it
>> first?
>> >
>> > -- hendrik
>>
>> --
>> 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/C561F2A9-0C78-4EDA-A401-4FB067D79849%40gmail.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/CABNTSaGUiZWoU9mZbqMjB04FSu_kFOGrgyv0riU8TuKtffB_dg%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/CANy33qnV3CNH3eGpVZ59qx%2BZQfjmaJ%3D9gSBfk_TY6aSx5F4k1w%40mail.gmail.com.


Re: [racket-users] macro hiding in raco expand

2020-08-10 Thread Ryan Culpepper
You can use the functions from macro-debugger/expand to do this (within 
limits). Here's a very rough example program that reads one term from 
stdin and shows its expansion with the given hiding policy (discarding 
hygiene information---beware).


usage: racket expand.rkt < your-example-file.rkt

Ryan


On 8/10/20 3:44 PM, Éric Tanter wrote:

Hi,

I’d like to use the Racket macro expander to translate programs from a 
given source language to a target language (both scheme-ish).


However, the expansion that `raco expand` does is too violent for my 
purposes---I would need a way to specify macro hiding (as in the macro 
stepper), in order to control the level of abstraction of the expanded 
code. Is that possible?

[see example below]

Thanks,

— Éric

; test.rkt
(define-syntax-rule (swap x y)
   (let ([tmp x])
     (set! x y)
     (set! y tmp)))

(define a 10)
(define b 20)
(swap a b)

; I’d like to obtain:

…prelude…
(define a 10)
(define b 20)
(let ([tmp a])
     (set! a b)
     (set! b tmp)))

; but raco expand gives me the full story:

(module test play
   (#%module-begin
    (module configure-runtime '#%kernel
      (#%module-begin (#%require racket/runtime-config) (#%app configure 
'#f)))

    (#%provide b swap a)
    (define-syntaxes
     (swap)
     (lambda (user-stx)
       (let-values (((arg) user-stx))
         (let-values (((rslt)
                       (#%app
                        (lambda (e)
                          (if (#%app stx-pair? e)
                            (if (#%app (lambda (e) null) (#%app stx-car e))
                              (#%app
                               (lambda (e)
                                 (if (#%app stx-pair? e)
                                   (#%app
                                    cons/#f
                                    (#%app stx-car e)
                                    (#%app
                                     (lambda (e)
                                       (if (#%app stx-pair? e)
                                         (let-values (((mh) (#%app 
stx-car e)))

                                           (if mh
                                             (if (#%app
                                                  stx-null/#f
                                                  (#%app stx-cdr e))
                                               mh
                                               '#f)
                                             '#f))
                                         '#f))
                                     (#%app stx-cdr e)))
                                   '#f))
                               (#%app stx-cdr e))
                              '#f)
                            '#f))
                        arg)))
           (if rslt
             (let-values (((sc1) (#%app unsafe-car rslt))
                          ((sc2) (#%app unsafe-cdr rslt)))
               (let-values ()
                 (#%app
                  syntax-protect
                  (let-values (((loc) (#%app check-loc 'syntax/loc 
user-stx)))

                    (#%app
                     t-subst
                     loc
                     (quote-syntax (let _ (set! _ _) (set! _ tmp)))
                     '(1 recur 2 recur 3)
                     (#%app
                      t-resyntax
                      '#f
                      (quote-syntax STX)
                      (#%app
                       t-list
                       (#%app t-subst '#f (quote-syntax (tmp _)) '(1) sc1)))
                     (#%app list '(1 2) sc1 sc2)
                     (#%app list '(1) sc2))
             (let-values (((rslt) (#%app (lambda (e) null) arg)))
               (if rslt
                 (let-values ()
                   (let-values () (#%app pattern-failure user-stx '(x y
                 (#%app raise-syntax-error '#f '"bad syntax" arg
    (define-values (a) '10)
    (define-values (b) '20)
    (#%app
     call-with-values
     (lambda () (let-values (((tmp) a)) (set! a b) (set! b tmp)))
     print-values)))

--
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/94E20736-F1F7-4073-B3FA-505ADD71DB4F%40dcc.uchile.cl 
.


--
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/767ebe77-95ed-d9f7-4d00-6391482d15a9%40gmail.com.
#lang 

Re: [racket-users] telling apart files ending with a newline

2020-07-30 Thread Ryan Culpepper
If I understand the docs correctly, the OS-specific handling is in
open-input-file, but it is not the default.

Here is an alternative to read-line that preserves line endings:

  #lang racket/base

  ;; my-read-line : InputPort -> String
  ;; Like read-line, but preserves line ending.
  ;; Fails if port contains specials.
  (define (my-read-line in [mode 'any])
(define rx
  (case mode
[(any) #rx"^[^\n\r]*(?:\r\n|\n|\r|$)"]
[(linefeed) #rx"^[^\n]*(?:\n|$)"]
;; ...
[else (error 'my-read-line "unsupported mode: ~e" mode)]))
(define m (car (regexp-match rx in))) ;; rx accepts "", can't fail
(if (equal? m #"") eof (bytes->string/utf-8 m)))

  (require rackunit racket/port)

  (check-equal?
   (port->list my-read-line (open-input-string "abc\ndef\r\ngh\n"))
   '("abc\n" "def\r\n" "gh\n"))

  (check-equal?
   (port->list my-read-line (open-input-string "abc\ndef\r\ngh"))
   '("abc\n" "def\r\n" "gh"))

  (check-equal?
   (port->list my-read-line (open-input-string "\n\r\n\n\r\r\n"))
   '("\n" "\r\n" "\n" "\r" "\r\n"))

  (check-equal?
   (port->list (lambda (in) (my-read-line in 'linefeed))
   (open-input-string "\n\r\n\n\r\r\n"))
   '("\n" "\r\n" "\n" "\r\r\n"))

Ryan


On Thu, Jul 30, 2020 at 5:11 AM Shriram Krishnamurthi 
wrote:

> Suppose I have two files that are identical, except one ends in a newline
> and the other does not. If I use `read-line` to read the successive lines
> of this file, because it swallows the line separators, there is no way to
> tell them apart. E.g., these two strings
>
> "a
> b"
>
> and
>
> "a
> b
> "
>
> read using `read-line` and `open-input-string` produce the same result.
>
> This is unfortunate for a program SPDEGabrielle has induced me to write
> (-:.
>
> Any reasonable ways to work around this that rely, as much as possible, on
> the OS-specific handling `read-line` already provides?
>
> Shriram
>
> --
> 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/250c95c9-24b6-467a-ad08-0cd81abded66n%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/CANy33qn61uHVZXuJdEBuOQV%3D%2BT%3DdS-6%3DfVgTGZat_3uJCSTKwA%40mail.gmail.com.


Re: [racket-users] Can Racket implement LockedMagicDoor example of MIXEDJAVA?

2020-08-12 Thread Ryan Culpepper
On Wed, Aug 12, 2020 at 7:19 PM Siyuan Chen  wrote:

> Dear Ryan,
>
> Thanks for your solution, it works nicely!
>
> But I still have some questions:
>
> For this particular problem of LockedMagicDoor, we can use `trait` to
> solve the `mixin` problem, but can we use the same method for more general
> problems?
>
> Since traits and mixins are essentially different, they may not mimic each
> other...
>
> IMO, they are at least 2 differences:
>
> 1. Traits can not have states, but mixin can.
>
>For example, if the `secure-trait`,  `locked-needed-trait`, and
> `magic-needed-trait` have mutable states, then you can not use `trait`.  (A
> workaround may be to convert `trait` to `mixin` first and then compose a
> "state" mixin. But this will cause the same problem of name colliding,
> because `mixin` does not support renaming)
>

No, traits can contain fields, which are mutable, so a trait can manage
state.

2. `trait-sum` is symmetric, it does not support overriding.
>
>For example, in your solution:
>
>```
>(define locked-mixin
>  (trait->mixin
>   (trait-rename (trait-sum secure-trait locked-needed-trait)
> needed-item needed-item/locked)))
>```
>
>To construct `locked-mixin`, you `trait-sum` the  `secure-trait` and
>  `locked-needed-trait`, but what if there is a default implementation of
> `needed-item` in the `secure-trait`? We even hope the `locked-needed-trait`
> can delegate to `super`, something like:
>
>```
>(define locked-needed-trait
>  (trait
>   (define/override (needed-item)
> (println "locked-needed-mixin neededItem")
> (super needed-item  ;; We want to call super.
>```
>

Right, one trait cannot override another's definitions. One thing you could
do instead is use `trait-exclude` to remove the definition of `needed-item`
from `secure-trait` before linking a trait (like `locked-needed-trait`, but
using `define/public` instead of `define/override`) that defines the
`needed-item` method. But if you do that, I think there's no way to chain
to the original definition. (I haven't tried any of this, but that's what I
get from the docs.)

The key question is:
>
> Does the current racket class system have the equivalent capabilities of
> MIXEDJAVA?
>
> More concretely, we know that Racket supports mixin, but Racket's `mixin`
> is slightly different from MIXEDJAVA. This is because we seemingly can not
> implement LockMagicDoor by using only `mixin-form` (Is this by design? I
> heard that there are some historical origins of MIXEDJAVA and MzScheme).
>
> But Racket supports two additional features, i.e.  `inner` and `trait`,
>  which are not in MIXEDJAVA.
>
> Consequently,  I'm curious about whether there is any design pattern in
> Racket that can simulate the semantics of MIXEDJAVA ?
>

I'm not sure, but I think the answer is no. If we distinguish "method
names" from "method slots" (or "vtable slots", to put it in terms of one
implementation strategy), then I think this example requires the ability to
change a method name to refer to a new method slot (but only for
subclasses; existing references point to the original slot), and I don't
think Racket's class system offers that ability. In particular, I think
that feature is not expressible using `inner`, although `inner` does
require a more complicated notation of "method slot" than a Java-style
class system. Anyway, that feature sounds maybe more dangerous than
worthwhile.

But if you know that you might want to apply the secure mixin multiple
times with different needed items, then there are other ways to write that
code. One is to parameterize the mixin by the needed item directly:

  ;; make-secure-mixin : Item -> (impl/c door<%>) -> (impl/c door<%>)
  (define (make-secure-mixin the-needed-item)
(mixin (door<%>) (door<%>)
  (super-new)
  (define/override (can-open p)
(println "secure-mixin can-open")
(cond [(send p has-item the-needed-item) ]
  [else ]

  (define locked-needed-mixin (make-secure-mixin the-key))
  (define magic-needed-mixin (make-secure-mixin the-spell-book))

Another is to parameterize `secure-mixin` over the *name* of the auxiliary
hook method, using `define-member-name` etc. That avoids the problem of
needing the same *name* to refer to different "slots" at different points
in time; instead, just use two different names. But IIRC, if you read the
APLAS paper on traits in Racket (Flatt et al), you discover that `trait` is
just syntactic sugar for this kind of member-name manipulation. So traits
are this design pattern turned into a linguistic construct.

Ryan

-- 
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 

Re: [racket-users] Can Racket implement LockedMagicDoor example of MIXEDJAVA?

2020-08-11 Thread Ryan Culpepper
I don't know of a way to solve that problem using the Racket class system
alone, but here is a solution that uses traits instead, which allow you to
rename the hook methods after the fact so they don't collide.

  ;; 
  (require racket/trait)

  (define secure-trait
(trait
 (inherit needed-item)
 (define/override (can-open p)
   (println "secure-mixin can-open")
   (define item (needed-item))
   (cond
 ((not (send p has-item item)) (printf "You don't have the Key
~v\n" item)
  #f)
 (else (printf "Using Key... ~v\n" item)
   (super can-open p))

  (define locked-needed-trait
(trait
 (define/public (needed-item)
   (println "locked-needed-mixin neededItem")
   the-key)))

  (define magic-needed-trait
(trait
 (define/public (needed-item)
   (println "magic-needed-mixin neededItem")
   the-spell-book)))

  (define locked-mixin
(trait->mixin
 (trait-rename (trait-sum secure-trait locked-needed-trait)
   needed-item needed-item/locked)))

  (define magic-mixin
(trait->mixin
 (trait-rename (trait-sum secure-trait magic-needed-trait)
   needed-item needed-item/magic)))
  ;; 

Ryan


On Sun, Aug 9, 2020 at 11:12 PM Siyuan Chen  wrote:

> Hi all,
>
> Recently I read the paper "Classes and Mixins" by Matthew Flatt, Shriram
> Krishnamurthi and Matthias Felleisen.
>
> In this paper, the authors presented MIXEDJAVA.
>
> In MIXEDJAVA,
>
>> A programmer implements mixins in exactly the same
>> way as a derived class, except that the programmer cannot
>> rely on the implementation of the mixin's superclass, only
>> on its interface. We consider this an advantage of mixins
>> because it enforces the maxim "program to an interface, not
>> an implementation".
>>
> It is very close to the mixin form in Racket, because we can specific
> interface in the mixin form:
>
> ```
> (mixin (interface-expr ...) (interface-expr ...)
>   class-clause ...)
> ```
>
> In Chapter 3, they also introduced an example (a maze adventure game, I
> called it LockedMagicDoor) which uses the system.
>
> My question is:
>
> Is it possible to implement LockedMagicDoor in Racket?
>
>
> I did some experiments but failed.
>
> See following code (or
> https://gist.github.com/chansey97/aecffabb2885c83fa040ba677bde5de4):
>
> ```
> #lang racket
>
> (define the-key 'the-key)
> (define the-spell-book 'the-spell-book)
>
> (define person%
>   (class object%
> (init-field items h)
> (super-new)
>
> (define/public (has-item item)
>   (member item items))
>
> (define/public (height)
>   h)
> ))
>
> (define door<%> (interface () can-open can-pass))
>
> (define door-mixin
>   (mixin () (door<%>)
> (super-new)
>
> (define/public (can-open p)
>   (println "door% can-open")
>   #t)
>
> (define/public (can-pass p)
>   (println "door% can-pass")
>   #t)
> ))
>
> (define secure-door<%> (interface (door<%>) needed-item))
>
> (define secure-mixin
>   (mixin (door<%>) (secure-door<%>)
> (super-new)
>
> (define/public (needed-item) ;; error??
>   (println "secure-mixin needed-item")
>   #f)
>
> (define/override (can-open p)
>   (println "secure-mixin can-open")
>   (define item (needed-item))
>   (cond
> ((not (send p has-item item)) (printf "You don't have the Key
> ~v\n" item)
>   #f)
> (else (printf "Using Key... ~v\n" item)
>   (super can-open p
> ))
>
> (define locked-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
> (super-new)
> (define/override (needed-item)
>   (println "locked-needed-mixin neededItem")
>   the-key)
> ))
>
> (define magic-needed-mixin
>   (mixin (secure-door<%>) (secure-door<%>)
> (super-new)
> (define/override (needed-item)
>   (println "magic-needed-mixin neededItem")
>   the-spell-book)
> ))
>
> (define door%
>   (door-mixin object%))
>
> (define locked-mixin (compose locked-needed-mixin secure-mixin))
> (define magic-mixin (compose magic-needed-mixin secure-mixin))
>
> (define locked-magic-mixin (compose locked-mixin magic-mixin))
> (define locked-magic-door% (locked-magic-mixin door%))
>
> (define door (new locked-magic-door%))
> (send door can-open (new person% [items (list the-key the-spell-book)] [h
> 0.5]))
>
> ; class*: superclass already contains method
> ;   superclass: #
> ;   method name: needed-item
> ;   class name: ...agic-door-failed.rkt:36:2
>
> ```
>
> The problem is how to implement `secure-mixin`?
>
> Notice that since the `secure-mixin` is mixed into `locked-magic-door%`
> twice, there will be two `needed-item` methods in the inheritance chain, so
> they are naming conflict.
>
> However in MIXEDJAVA, they do not conflict:
>
>> Specifically, a composition m1 compose m2 contains two methods named
>> x if both m1 and m2 declare x and m1's inheritance interface does not
>> 

Re: [racket-users] Are Regular Expression classes Unicode aware?

2020-07-09 Thread Ryan Culpepper
If you want a regular expression that does match the example string, you
can use the \p{property} notation. For example:

  > (regexp-match? #px"^\\p{L}+$" "h\uFFC3\uFFA9llo")
  #t

The "Regexp Syntax" docs have a grammar for regular expressions with links
to examples.

Ryan


On Thu, Jul 9, 2020 at 4:32 PM Sorawee Porncharoenwase <
sorawee.pw...@gmail.com> wrote:

> Racket REPL doesn’t handle unicode well. If you try (regexp-match?
> #px"^[a-zA-Z]+$" "héllo") in DrRacket, or write it as a program in a file
> and run it, you will find that it does evaluate to #f.
>
> On Thu, Jul 9, 2020 at 7:19 AM Peter W A Wood 
> wrote:
>
>> I was experimenting with regular expressions to try to emulate the Python
>> isalpha() String method. Using a simple [a-zA-Z] character class worked for
>> the English alphabet (ASCII characters):
>>
>> > (regexp-match? #px"^[a-zA-Z]+$" "hello")
>> #t
>> > (regexp-match? #px"^[a-zA-Z]+$" "h1llo")
>> #f
>>
>> It then dawned on me that the Python is alpha() method was Unicode aware:
>>
>> >>> "é".isalpha()
>> True
>>
>> I started scratching my head as how to achieve the equivalent using a
>> regular expression in Python. I tried the same regular expression with a
>> non-English character in the string. To my surprise, the regular expression
>> recognised the non-ASCII characters.
>>
>> > (regexp-match? #px"^[a-zA-Z]+$" "h\U+FFC3\U+FFA9llo")
>> #t
>>
>> Are Racket regular expression character classes Unicode aware or is there
>> some other explanation why this regular expression matches?
>>
>> Peter
>>
>> --
>> 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/2197C34F-165D-4D97-97AD-F158153316F5%40gmail.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/CADcuegsvf-hFwofptc2ieKQmqWFzxDnD1Cn8G7bFSzBZ%2BM3EDA%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/CANy33q%3DtBkQYDg-Tv1MEw17P1ipnqUDcDDFmq_%3DTumUAGJrHAA%40mail.gmail.com.


Re: [racket-users] Re: DB hangs with postgres and broken network link

2020-07-03 Thread Ryan Culpepper
Hi Curtis, thanks for the report. No, that isn't supposed to happen. I
haven't managed to reproduce a silent hang, and looking over the
virtual-connection code it looks like any errors (eg, TCP timeout) should
be propagated to the caller. On the other hand, I don't have a way of
simulating a network outage for testing, so maybe in that case the
connection never realizes it is no longer connected, unlike the things I
tried.

Could you run your program with db logging at the debug level (eg, set the
environment variable PLTSTDERR to "debug@db error") and also add `#:debug?
#t` to your call to `postgresql-connect` and see what gets logged/printed
before the hang occurs? (You may want to redact the output.)

Ryan

On Fri, Jul 3, 2020 at 5:07 PM Curtis Dutton  wrote:

> Ok well on additional investigation this appears only to happen while
> using virtual connections. If a raw postgresql-connect is used it does
> raise a tcp timeout error.
>
> On Fri, Jul 3, 2020 at 10:51 AM Curtis Dutton  wrote:
>
>> I'm in the process of writing a simple daemon that periodically checks in
>> with a postgres database. I'm trying to make it resilient with network
>> outages.
>>
>>
>> If you connect to the database.
>> Unplug the network cable.
>> Run a query.
>>
>> The query will hang for what appears to be forever without throwing an
>> exception.
>>
>> Is this expected behavior?
>>
>>
>> Thanks,
>> Curtis
>>
> --
> 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/CAPChLEqzeN3FjhD59tTHUf3EFgW8Bo0xi_3e3Va5kPg2Ut7miA%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/CANy33qkN3tUxav9xkVnnWrA9Hd1K9JBhOdwAzSxJgDmDXtVkeg%40mail.gmail.com.


Re: [racket-users] Embedded racket (cs) question

2020-07-13 Thread Ryan Culpepper
I don't know if it helps, but config:installation-name is a promise defined
by setup/private/dirs.

Ryan


On Mon, Jul 13, 2020 at 7:23 PM Matthew Flatt  wrote:

> I'm not sure how it could be in `dynamic-require` itself, as opposed to
> a library that is loaded by `dynamic-require`, but it sounds like a bug
> at some level. Can you provide a small example?
>
> At Mon, 13 Jul 2020 11:03:41 -0500, Nate Griswold wrote:
> > Sam, thanks
> >
> > To be clear, this crash happened DURING a dynamic-require and judging by
> > the stack trace looked to be part of the dynamic-require machinery (and
> > this seems to depend on the installation name).
> >
> > I actually wasn't depending on anything but racket/base, so i don't
> believe
> > anything i was using was causing a separate dependency on promise.
> >
> > Nate
> >
> >
> > On Mon, Jul 13, 2020 at 9:32 AM Sam Tobin-Hochstadt <
> sa...@cs.indiana.edu>
> > wrote:
> >
> > > My guess, not having looked further than your email, is that when you
> > > don't include racket/promise, something is supplying a promise to
> something
> > > else but there are two different instantiations of the promise library,
> > > causing the force call from one not to recognize the promise from the
> > > other. Then force just becomes the identity function, and passes
> through a
> > > promise to somewhere that isn't expecting one.
> > >
> > > Is it possible that some library you're using features promises?
> > > Alternatively, it might be that the embedding code needs an explicit
> > > dependency on promises.
> > >
> > > Sam
> > >
> > > On Mon, Jul 13, 2020, 10:18 AM Nate Griswold 
> > > wrote:
> > >
> > >> Hello.
> > >>
> > >> I noticed something and was wondering what the list thinks:
> > >>
> > >> I am using an embedded racket Ics) and i noticed that if i embed a
> file
> > >> and don't include any libraries (for a very bare bones c file) i have
> > >> problems with a crash on a promise on any dynamic-require:
> > >>
> > >> build-path: contract violation
> > >>   expected: (or/c path-string? path-for-some-system? 'up 'same)
> > >>   given: #
> > >>
> > >> but if i do a (require racket/promise) in my rkt argument to --c-mods
> OR
> > >> if i do a ++lib racket/promise i get no crash.
> > >>
> > >> So is this expected behavior? Should racket/promise always be
> included or
> > >> no? And what exactly is going on under the hood here?
> > >>
> > >> Nate
> > >>
> > >> --
> > >> 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/CAM-xLPpg_0Ef8ByjS01Y1pKEeeFMVkF
> > k3dvGcdpRaYo3ZqDb9A%40mail.gmail.com
> > >>
> > <
> https://groups.google.com/d/msgid/racket-users/CAM-xLPpg_0Ef8ByjS01Y1pKEeeFMVk
> > Fk3dvGcdpRaYo3ZqDb9A%40mail.gmail.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/CAM-xLPpaOSxvPEDYzmkAXdFg%2BLTMA
> > H1mw57kJt7%3DCe6ipXmXDw%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/20200713112340.24e%40sirmail.smtp.cs.utah.edu
> .
>

-- 
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/CANy33q%3DBvUOi2%2BP4L4JxrbfJQxaWgbXNnP%3DV5z2yot3xR69frw%40mail.gmail.com.


Re: [racket-users] Wills, plumbers, and checking if a port is closed

2020-06-30 Thread Ryan Culpepper
Here's a function that creates a thread that waits until a port is closed
and then prints a message:

  (define (watch-for-port-close p)
(thread (lambda () (sync (port-closed-evt out)) (eprintf "port
closed\n"

For example:

  (define out (open-output-string))
  (watch-for-port-close out) ;; => #
  (close-output-port out) ;; prints "port closed"

One reason a port can get closed is because of a custodian shutdown, and in
that case you'd need to make sure that the watcher thread and its
current-error-port are not managed by the same custodian. Here's a version
that creates an unkillable thread (generally a bad idea, but probably okay
for debugging):

  (require ffi/unsafe/custodian)
  (define (watch-for-port-close p)
(parameterize ((current-custodian (make-custodian-at-root)))
  (thread (lambda () (sync (port-closed-evt out)) (eprintf "port
closed\n")

Ryan

On Wed, Jul 1, 2020 at 1:08 AM Matthew Flatt  wrote:

> At Tue, 30 Jun 2020 16:27:56 -0400, David Storrs wrote:
> > I have a port that (my current theory says) is being closed when it
> > shouldn't, but I'm having trouble isolating exactly where and when.  I
> > thought maybe I could do something Rackety to say "as soon as this port
> > gets closed, run this function".  I went digging through Wills and
> Plumbers
> > but I'm having trouble grokking it.  Am I headed in the right direction,
> or
> > is there a better way?
>
> Wills and plumbers will not help.
>
> Do you have control over where the port is used to that you can
> substitute another port? In that case, you could wrap the port with
> `make-input-port` or `make-output-port`, and then you have control over
> the close method.
>
> --
> 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/20200630164403.17c%40sirmail.smtp.cs.utah.edu
> .
>

-- 
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/CANy33qn%3Da6gWS0geiYWCd4W%3Djo5mVPSgxye6b_MxvGkzZ1N5Cw%40mail.gmail.com.


Re: [racket-users] Are Regular Expression classes Unicode aware?

2020-07-11 Thread Ryan Culpepper
Great, I'm glad it was useful!

Ryan


On Sat, Jul 11, 2020 at 12:27 PM Peter W A Wood 
wrote:

> Dear Ryan
>
> Thank you for both your full, complete and understandable explanation and
> a working solution which is more than sufficient for my needs.
>
> I created a very simple function based on the reg=exp that you suggested
> and tested it against a number of cases:
>
>
> #lang racket
> (require test-engine/racket-tests)
>
> (check-expect (alpha? "") #f)   ;
> empty string
> (check-expect (alpha? "1") #f)
> (check-expect (alpha? "a") #t)
> (check-expect (alpha? "hello") #t)
> (check-expect (alpha? "h1llo") #f)
> (check-expect (alpha? "\u00E7c\u0327") #t)   ; çç
> (check-expect (alpha? "noe\u0308l") #t) ; noél
> (check-expect (alpha? "\U01D122") #f)   ; 턢 (bass
> clef)
> (check-expect (alpha? "\u216B") #f)   ; Ⅻ (roman
> numeral)
> (check-expect (alpha? "\u0BEB") #f)   ; ௫ (5 in
> Tamil)
> (check-expect (alpha? "二の句") #t); Japanese
> word "ninoku"
> (check-expect (alpha? "مدينة") #t); Arabic
> word "madina"
> (check-expect (alpha? "٥") #f) ;
> Arabic number 5
> (check-expect (alpha? "\u0628\uFCF2") #t); Arabic letter
> beh with shaddah
> (define (alpha? s)
>  (regexp-match? #px"^\\p{L}+$" (string-normalize-nfc s)))
> (test)
>
> I suspect that there are some cases with scripts requiring multiple code
> points to render a single character such as Arabic with pronunciation marks
> e.g. دُ نْيَا. At the moment, I don’t have the time (or need) to
> investigate further.
>
> The depth of Racket’s Unicode support is impressive.
>
> Once again, thanks.
>
> Peter
>
>
> > On 10 Jul 2020, at 15:47, Ryan Culpepper  wrote:
> >
> > (I see this went off the mailing list. If you reply, please consider
> CCing the list.)
> >
> > Yes, I understood your goal of trying to capture the notion of Unicode
> "alphabetic" characters with a regular expression.
> >
> > As far as I know, Unicode doesn't have a notion of "alphabetic", but it
> does assign every code point to a "General category", consisting of a main
> category and a subcategory. There is a category called "Letter", which
> seems like one reasonable generalization of "alphabetic".
> >
> > In Racket, you can get the code for a character's category using
> `char-general-category`. For example:
> >
> >   > (char-general-category #\A)
> >   'lu
> >   > (char-general-category #\é)
> >   'll
> >   > (char-general-category #\ß)
> >   'll
> >   > (char-general-category #\7)
> >   'nd
> >
> > The general category for "A" is "Letter, uppercase", which has the code
> "Lu", which Racket turns into the symbol 'lu. The general category of "é"
> is "Letter, lowercase", code "Ll", which becomes 'll. The general category
> of "7" is "Number, decimal digit", code "Nd".
> >
> > In Racket regular expressions, the \p{category} syntax lets you
> recognize characters from a specific category. For example, \p{Lu}
> recognizes characters with the category "Letter, uppercase", and \p{L}
> recognizes characters with the category "Letter", which is the union of
> "Letter, uppercase", "Letter, lowercase", and so on.
> >
> > So the regular expression #px"^\\p{L}+$" recognizes sequences of one or
> more Unicode letters. For example:
> >
> >   > (regexp-match? #px"^\\p{L}+$" "héllo")
> >   #t
> >   > (regexp-match? #px"^\\p{L}+$" "straße")
> >   #t
> >   > (regexp-match? #px"^\\p{L}+$" "二の句")
> >   #t
> >   > (regexp-match? #px"^\\p{L}+$" "abc123")
> >   #f ;; No, contains numbers
> >
> > There are still some problems to watch out for, though. For example,
> accented characters like "é" can be expressed as a single pre-composed code
> point or "decomposed" into a base letter and a combining mark. You can get
> the decomposed form by converting the string to "decomposed normal form"
> (NFD), and the regexp above won't match that string.
> >
> > 

Re: [racket-users] Changing the charset/encoding when using the db library

2020-07-11 Thread Ryan Culpepper
The db library expects to talk to the MySQL server using utf8. If you
manage to change the connection encoding (eg with SET NAMES), it is likely
to confuse the db library and either corrupt data or make the connection
fail with an error.

Can you explain what you want to accomplish?

Ryan

On Sat, Jul 11, 2020 at 12:06 PM Bonface Munyoki 
wrote:

> Hi all.
>
> I'm using racket to connect to mysql using the db library. I'd like to
> do something like:
>
> --8<---cut here---start->8---
> `sqlalchemy.create_engine(SQL_URI+'?charset=latin1_unicode=0')`
> --8<---cut here---end--->8---
>
> basically adding the equivalent of "charset=latin1_unicode=0" in the
> SQL_URI. I can't seem to find a way to do that in racket. Would anyone
> have an idea of how I would do that?
> ---
> Bonface M. K.(https://www.bonfacemunyoki.com/)
> One Emacs to rule them all
> GPG key = D4F09EB110177E03C28E2FE1F5BBAE1E0392253F
>
> --
> 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/CABAzU5te7aqX%2B6oxUTK8qKr1XA%3DTL1TEL-Eco1s0_vBEC2F09Q%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/CANy33q%3DZS7AXaiHFHMuKkf3o7jr2BQ_zQzK9djmUCqXHn0x4Cw%40mail.gmail.com.


Re: [racket-users] Re: note about parsing speed of xml vs sxml?

2020-06-28 Thread Ryan Culpepper
Thanks Alex for pointing out the use of list->string. I've created a PR (
https://github.com/racket/racket/pull/3275) that changes that code to use
string ports instead (similar to Hendrik's suggestion, but the string port
handles resizing automatically). Could someone (John?) with some large XML
files lying around try the changes and see if they help?

Ryan


On Sun, Jun 28, 2020 at 9:56 PM Neil Van Dyke  wrote:

> If anyone wants to optimize `read-xml` for particular classes of use,
> without changing the interface, it might be very helpful to run your
> representative tests using the statistical profiler.
>
> The profiler text report takes a little while of tracing through
> manually to get a feel for how to read and use it, but it can be
> tremendously useful, and is worth learning to do if you need performance.
>
> After a first pass with that, you might also want to look at how costly
> allocations/GC are, and maybe do some controlled experiments around
> that.  For example, force a few GC cycles, run your workload under
> profiler, check GC time during, and forced time after.  If you're
> dealing with very large graphs coming out of the parser, I don't know
> whether those are enough to matter with the current GC mechanism, but
> maybe also check GC time while you're holding onto large graphs, when
> you release them, and after they've been collected.  At some point, GC
> gets hard for at least me to reason about, but some things make sense,
> and other things you decide when to stop digging. :)  If you record all
> your measurements, you can compare empirically the how different changes
> to the code affect things, hopefully in representative situations.
>
> I went through a lot of these exercises to optimize a large system, and
> sped up dynamic Web page loads dramatically in the usual case (to the
> point we were then mainly limited by PostgreSQL query cost, not much by
> the application code in Scheme, nor our request network I/O),
> and also greatly reduced the pain of intermittent request latency spikes
> due to GC.
>
> One of the hotspots, I did half a dozen very different implementations,
> including C extension, and found an old-school pure Scheme
> implementation was fastest.  I compared the performance of the
> implementation using something like `shootout`, but there might be
> better ways now in Racket. https://www.neilvandyke.org/racket/shootout/
> I also found we could be much faster if we made a change to what the
> algorithm guarantees, since it was more of a consistency check that
> turned out to be very expensive and very redundant, due to all the ways
> that utility code ended up being used.
>
> In addition to contrived experiments, I also rigged up a runtime option
> so that the server would save data from the statistical profiler for
> each request a Web server handled in production.  Which was tremendously
> useful, since it gave us real-world examples that were also difficult to
> synthesize (e.g., complex dynamic queries), and we could go from Web
> logs and user feedback, to exactly what happened.
>
> (In that system I optimized, we used Oleg's SXML tools very heavily
> throughout the system, plus some bespoke SXML tools for HTML and XML.
> There was one case in which someone had accidentally used the `xml`
> module, not knowing it was incompatible with the rest of the system,
> which caused some strange failures (no static checking) before it was
> discovered, and we changed that code to use SXML.)
>
> --
> 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/68624c9a-df35-14a3-a912-df806799a7e0%40neilvandyke.org
> .
>

-- 
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/CANy33q%3DpZw9EPmZG%2Bdz5cRYMSP17Ofntq9JwFqVVoN8ZhO6POg%40mail.gmail.com.


Re: [racket-users] Poor documentation of List*

2020-06-03 Thread Ryan Culpepper
`(List* T)` is the same as `T`, just as `(list* x)` is the same as `x`
(whether `x` is a list or not).

  > (require typed/racket)
  > (list* 4 5 6)
  - : (List* Positive-Byte Positive-Byte Positive-Byte)
  '(4 5 . 6)
  > (list* 6)
  - : Integer [more precisely: Positive-Byte]
  6
  > (:type (List* String))
  String

Ryan


On Wed, Jun 3, 2020 at 9:49 PM Hendrik Boom  wrote:

> On Wed, Jun 03, 2020 at 04:22:41PM +0100, Stephen De Gabrielle wrote:
> > Hi Hendrik,
> >
> > I can't see the example you mention in
> >
> https://docs.racket-lang.org/ts-reference/type-ref.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fbase-types-extra..rkt%29._.List%2A%29%29
> >
> > i'm assuming (List* c) is shorthand for (Pair c null)? I don't know typed
> > racket so I've probably got that terribly wrong.
>
> It might be.  But that's normally said as (List c), not List* c)
> With your interpretation, List* qould be equivalent to List.
>
> >
> > So while I can't help you with this - I wanted to encourage you to make a
> > PR to the documentation if you come up with a fix.
>
> My problem is that I don't know what the documentation is supposed to say.
>
> -- hendrik
>
> > It *used* to be hard to find the file that needs the fix, good steps have
> > been made recently to make it easier to identify the documentation source
> > file so it is easier to find and make the corrections or additions.
> >
> > If you have any trouble let me know and I'll try help - I think I'm
> > getting the hang of it.
> >
> > Hope you are well
> >
> > Kind regards
> >
> > Stephen
> >
> > ps i use
> >
> https://blog.racket-lang.org/2017/09/tutorial-contributing-to-racket.html
> &
> > lots of kind guidance from other racketeers :0
> > pps: if you make a successful pr you get credit in the frankly wonderful
> > racket news https://racket-news.com/2020/06/racket-news-issue-32.html
> >
> > On Tue, Jun 2, 2020 at 3:13 PM Hendrik Boom 
> wrote:
> >
> > > In the Typed Racket Reference, List* is defined as follows:
> > >
> > > (List* t t1 ... s)
> > >
> > > is equivalent to (Pairof t (List* t1 ... s)).
> > >
> > > Following this definition down, we get
> > >
> > > (List* a b c)
> > >  -> (Pairof a (List* b c))
> > >  -> (Pairof a (Pairof b (List* c)))
> > >
> > > But what's (List* c) ?
> > >
> > > I see no explanatory examples.
> > >
> > > -- hendrik
> > >
> > > P.S.  I'm also unsure what 'bound' is supposed to do in
> > >
> > > (List t ... trest ... bound)
> > >
> > > It says "where bound must be an identifier denoting a type variable
> > > bound with ..." but I don't undestand what this is referring to.
> > >
> > > There are no examples of this in the document, just as there are no
> > > examples of List*.
> > >
> > > -- hendrik
> > >
> > > --
> > > 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/20200602141347.3z7igvzbjyikhfn4%40topoi.pooq.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-LsML%2BeOnt_BUBWmRM5vU6GtovyaNr-JHOQPzoMCL2NTQ%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/20200603194902.27zjystdhecumoup%40topoi.pooq.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/CANy33qkhzs-fEkORpdQ3dH3qcu%2BoXRrOpAxM5%3DffLn6kwpXTFQ%40mail.gmail.com.


Re: [racket-users] Why am I not fully releasing this SSL listener?

2020-07-24 Thread Ryan Culpepper
If you create the ssl-listener with reuse?=true instead, like this

  (define listener (ssl-listen port 5 #f #t ctx))

does the problem go away? If so, the error might happen because the OS
reserves the port number for a while after the listener is closed; see the
paragraph about TIME_WAIT in the tcp-listener docs. If that's the issue,
I'm a little confused why the TCP version would succeed, though.

I believe SSL_shutdown is completely unrelated to the state of the TCP
ports. Think of it like a "Connection: close" HTTP header; it announces
your intention to close the TCP connection soon, but it has no actual
effect on the transport layer.

Ryan


On Fri, Jul 24, 2020 at 6:19 PM Sage Gerard  wrote:

> I'm trying to understand how I am failing to shut down an ssl-listener on
> v7.7.0.5.
>
> https://gist.github.com/zyrolasting/bc5477bfa60d7185d0f53a5142545f88
> shows my use of ssl-* procedures to transmit data using test.pem. The
> problem is that I cannot run the test submodule twice in a row because the
> listening port is still occupied on subsequent runs. I added ssl-close on
> top of a custodian shutdown and that problem reproduces.
>
> For comparison,
> https://gist.github.com/zyrolasting/3feb0ff4ecdf0b49bcf3e0ed8b630a06
> avoids the ssl-* procedures and just uses vanilla TCP. I can run the tests
> fine then.
>
> But in looking at mzssl.rkt in the source, it looks like shutdown requires
> calling a foreign function via SSL_shutdown.
> https://github.com/racket/racket/blob/master/racket/collects/openssl/mzssl.rkt#L1417
>
> Do I have to call ports->ssl-ports out of band just so closing them sends
> a shut down as a side-effect? Or is keeping the port occupied between test
> runs a bug?
>
> *~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/EclLZhgUYlzvOx_uS0Ec154iNVVwXxNeZWcTIDzd72lwkA3M2OhVf8AW_cVMVUudM50kLuLVvnnnmiRGvZDvz5tPSUVOqFkC2LVI-2LY18Q%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/CANy33qmLM6wfYhedVzR-PjmETNf-TXioTtww94u1%2Bot4SsFHZQ%40mail.gmail.com.


Re: [racket-users] How can I increase expansion+compilation speed?

2020-07-20 Thread Ryan Culpepper
One thing to check is the size of the resulting bytecode file. When I
compiled it, I got a 911 KB .zo file. So the most likely reason is that
your macros are just producing a lot of code.

You can run the macro profiler (eg, `raco macro-profiler aw-schema.rkt`) to
get a summary of what macros contribute most to the compiled code size. See
https://docs.racket-lang.org/macro-debugger/index.html#(part._.Macro_.Profiler)
for more details. I also gave a talk about the macro profiler called "The
Cost of Sugar" a few years ago at RacketCon. The slides are at
http://www.ccs.neu.edu/home/ryanc/talks/racket18-sugar.pdf, and there
should be a recording online somewhere.

The usual fix is to use helper functions. There are some examples in the
slides.

Ryan


On Mon, Jul 20, 2020 at 2:08 AM Ryan Kramer 
wrote:

> Using DrRacket, the following file takes 18 seconds to compile without
> debugging, or about 40 seconds to compile with debugging:
> https://raw.githubusercontent.com/default-kramer/plisqin-tutorials/e844825b48137553246c64e73516d880b9068825/define-schema-answer-key/aw-schema.rkt
>
> When I say "compile", I mean that I click "Run" in DrRacket and wait for
> it to give me REPL access. But that file just defines and provides a slew
> of functions, it doesn't really do anything at runtime.
>
> (Using the command-line `racket that-file.rkt` takes only 7 seconds, which
> is OK. But many people, myself included, primarily use DrRacket.)
>
> Admittedly, this is 612 dense lines of code. So it might just be a case of
> "yeah, that's about how long it takes." But it's also possible (or
> probable?) that I have some inefficient macros somewhere. Are there any
> tools/techniques I can use to help me reduce the compilation time?
>
> --
> 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/40e40eff-a0be-4850-9360-c9648cb5b8d9o%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/CANy33q%3D1d1ojXVrcsM1mYCa2%2BcLkN2-x7x0WM197BukAA%3DRuzA%40mail.gmail.com.


Re: [racket-users] resumable exceptions (or: How can I break myself?)

2020-12-29 Thread Ryan Culpepper
I would suggest avoiding exceptions and continuations and have a separate
parameter[*] that holds the current unexpected character handler. You'll
still have to figure out what kind of thing it returns (void, or a
replacement character, or a new input port?), but you have to do that
anyway.

The handler can raise an ordinary, non-continuable exception if it can't
repair the problem. Or it could do weird continuation stuff like capture
the part of the continuation since the handler was installed and apply it
to multiple characters to see if one works (but that would not work well
with stateful objects like input ports).

Ryan

[*] or argument, if that turns out to fit your code better


On Tue, Dec 29, 2020 at 11:27 AM je...@lisp.sh  wrote:

> I'm working on a tokenizer for that involves some level of "self-healing":
> if the input port contains an unexpected character, an error token is to be
> emitted, but computation isn't over -- we are to continue by substituting
> the bad character with a good one, emitting that, too (thereby recovering),
> and keep rolling.
>
> When the tokenizer encounters an unexpected character, what I'd like to do
> is similar to raising/throwing an exception, but what's going on isn't (in
> my understanding) quite the same as raising an exception, because I don't
> want to just have some ambient exception handler deal with the error, since
> my understanding is that exceptions don't have enough information to simply
> resume the computation. I guess I'd like to install a prompt, but when
> control goes back to the prompt, I'd like it to be possible to resume the
> computation.
>
> An old discussion here from 2015, with John Carmack ("continuing after a
> user break"), comes close to what I have in mind. It's about setting up a
> handler for breaks. I guess what I have in mind are breaks, but what's not
> clear to me is how to raise them in my code. It seems like `break-thread`
> is the only way to do that? The discussion of breaks in the docs involves a
> lot of talk about threads and user interaction. But what I'm doing isn't
> really about threads at all (I'm making a tokenizer, not a REPL or other
> interactive program), so it leaves me feeling uncertain that I want breaks
> after all. And even if breaks are a technically viable solution, I wonder
> if there are any performance penalties or other gotchas that could be
> avoided by using some other continuation forms.
>
> Here's some pseudo-Racket that gets at what I'm looking for:
>
> ; compute a list of tokens
> ; -> (listof (char? or eof))
> (define (handle-many)
> (watch-for-break (lambda (e) (handle-break e))
> (match (handle-one)
> [(? eof-object?) '(eof)]
> [(? char? c) (cons c (handle-one))])))
>
> ; -> char? or eof
> (define (handle-one)
> (define c (peek-char))
> (match c
> [(? eof-object?) eof]
> [#\f
> (break-with c) ; pass the unexpected character to the caller...
> (read-char in) ; ...but after that, resume here!
> #\a]
> [else
> (read-char in)
> #\b]))
>
> Any suggestions?
>
> Thanks,
>
> Jesse
>
> --
> 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/e455208d-0ac9-41d6-ad08-dd3d08e12baan%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/CANy33qmgzGafKVDXp%3Do9Kqb5nOJ11Ys9K%3D9Ay%2BH24YgxaWddaA%40mail.gmail.com.


Re: [racket-users] Using expr/c within one syntax class?

2020-12-17 Thread Ryan Culpepper
Based on what you have written so far, the `versions` macro has no
sub-expressions, so you shouldn't use `expr/c` at all. It requires version
bounds to be in the form of literal strings. So you could describe the
macro using a grammar as follows:

  Expression ::=  | (versions Version ...)
  Version ::= VersionBound | (VersionBound VersionBound)
  VersionBound ::= String

I think what you want to do is refine VersionBound so that it only accepts
strings of a certain form. The best way to do that is with a separate
syntax class that matches a string and then puts additional side-conditions
on it (using `#:when`, etc). That is, you check the `valid-version?`
predicate at compile-time.

By the way, you should also avoid treating the literal strings that your
macro receives as if they were also expressions. A syntax object containing
a literal string is *not necessarily* a string-valued expression. Once your
macro views and validates something as a literal string, the proper way to
convert it to a run-time expression is to explicitly quote it. Consider the
following test case:

(let-syntax ([#%datum (lambda (stx) #'(exit '0))]) (versions ("7.0"
"7.7.0.5") "6.5"))

If your macro produces eg (list (make-version-range (quote "7.0") (quote
"7.7.0.5")) (quote "6.5")), then it's fine; if it produces (list
(make-version-range "7.0" "7.7.0.5") "6.5"), then it would exit. This
particular example is unlikely to happen in practice, but I think it is
useful to think clearly about how interpret each argument of a macro. Treat
it as a literal string or as an expression, but not both.

A different design would be to say that VersionBound is an expression that
produces a string. That would cause problems with your current grammar,
because you couldn't tell whether `(f "1.2.3")` was a single version (whose
value is produced by a function call) or by a range (whose lower bound is
the variable f). But you could change the grammar to avoid that problem.
Then you could use `expr/c` to wrap the expressions to check that at run
time they produced strings of the proper form.

Ryan


On Thu, Dec 17, 2020 at 12:55 AM Sage Gerard  wrote:

> Typos:
>
> - "*" remove a bound ==> "*" removes a bound
> - All examples should read (versions ...), not (version ...)
>
> *~slg*
>
>
> ‐‐‐ Original Message ‐‐‐
> On Wednesday, December 16, 2020 6:27 PM, Sage Gerard 
> wrote:
>
> I'm trying to learn how to write syntax classes. My intended macro
> expresses a set of Racket versions, either as inclusive intervals or as
> exact versions. In an interval, "*" remove a bound.
>
>- (version "6.5") means exactly version "6.5", as does (version ("6.5"
>"6.5"))
>- (versions ("7.0" "7.7.0.5")) means the inclusive interval between
>version 7.0 and 7.7.0.5
>- (versions ("7.0" "7.7.0.5") "6.5"): union of the above two items
>- (versions ("6.0" "*")): all Racket versions >= 6.0
>- (versions "*"), (versions ("*" "*")): all Racket versions
>
> I was able to define the syntax class without much issue:
>
> (define-syntax-class racket-version-selection
>   #:attributes (min max)
>   (pattern (min:string max:string))
>   (pattern (~and (~var v string)
>  (~bind [min #'v]
> [max #'v]
>
> Now I want each attribute-bound expression V to satisfy (or
> (valid-version? V) (equal? V "*")). Where I'm stuck is how I can use
> #:declare with (expr/c) here. From what I understand, expr/c does not
> really mean much because it accepts an expression (as in the expr
> syntax-class), not attributes.
>
> The only way I can think to fix this is to perform an additional
> syntax-parse so that I can use the attributes in an expression for expr/c
> to consume. But is it possible to do everything I'm thinking of in just one
> syntax class?
>
> *~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/syiNcw0zJpSyA16fO8OkClrQmXFOC4qZEwrBm3JwETX-bGJGlALnP6Apn4ttCbIzMZUoobO7AT4MyRDm9ID0oUA648nXXSAZ1nvaCaj2NbI%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/nfmcqQmNc3_H9zeCyS49LELvXomDYQF2sJbmyrJchu0kiWG8CXJiyS932ZfQ_eSW3cnEYTTzOwqakNlKL4FF_KR4F7HnAARLdQLDVEGxSI0%3D%40sagegerard.com
> 

Re: [racket-users] Using expr/c within one syntax class?

2020-12-18 Thread Ryan Culpepper
Right, I would generally recommend against using `raise-syntax-error`
within syntax classes. syntax-parse has heuristics to convert the "most
specific" pattern failure into a syntax error, and it's usually better to
work within that framework (as your code using `~fail` does). To make that
work, you should also generally avoid catch-all clauses like the one in
your second example.

Ryan


On Fri, Dec 18, 2020 at 3:47 AM Sage Gerard  wrote:

> Fantastic, thank you for getting me on my way. I followed your advice
> where I do not use string-producing expressions and ended up with a follow
> up question.
>
> New syntax classes are below for those reading.
>
> (define (unbounded? v)
>   (equal? "*" v))
>
> (define-syntax-class racket-version-or-*
>   (pattern (~var bound string)
>#:when (let ([v (syntax-e #'bound)])
> (or (unbounded? v)
> (valid-version? v)
>
> (define-syntax-class racket-version-selection
>   #:attributes (min max)
>   (pattern (~and (min:racket-version-or-* max:racket-version-or-*)
>  (~fail #:unless (let ([min-v (syntax-e #'min)] [max-v
> (syntax-e #'max)])
>  (or (unbounded? min-v)
>  (unbounded? max-v)
>  (version<=? min-v max-v)))
> "minimum Racket version cannot exceed maximum
> Racket version")))
>   (pattern (~and (~var v racket-version-or-*)
>  (~bind [min #'v] [max #'v]
>
>
> Note the condition set in racket-version-selection that checks for
> backwards ranges. From what I understand, it only raises a pattern failure,
> which means I only see the ~fail error message for:
>
>  (syntax-parse #'(("8.4" "8.3"))
>   [(v:racket-version-selection ...) #t])
>
> but not
>
>  (syntax-parse #'(("8.4" "8.3"))
>   [(v:racket-version-selection ...) #t]
>   [_ #f])
>
> In this case, is it better form to use raise-syntax-error in a #:when
> pattern directive for a syntax class, or beneath a clause of syntax-parse?
> I suspect that syntax classes should not have an opinion about flow control.
>
> *~slg*
>
>
> ‐‐‐ Original Message ‐‐‐
> On Thursday, December 17, 2020 4:52 AM, Ryan Culpepper <
> rmculpepp...@gmail.com> wrote:
>
> Based on what you have written so far, the `versions` macro has no
> sub-expressions, so you shouldn't use `expr/c` at all. It requires version
> bounds to be in the form of literal strings. So you could describe the
> macro using a grammar as follows:
>
>   Expression ::=  | (versions Version ...)
>   Version ::= VersionBound | (VersionBound VersionBound)
>   VersionBound ::= String
>
> I think what you want to do is refine VersionBound so that it only accepts
> strings of a certain form. The best way to do that is with a separate
> syntax class that matches a string and then puts additional side-conditions
> on it (using `#:when`, etc). That is, you check the `valid-version?`
> predicate at compile-time.
>
> By the way, you should also avoid treating the literal strings that your
> macro receives as if they were also expressions. A syntax object containing
> a literal string is *not necessarily* a string-valued expression. Once your
> macro views and validates something as a literal string, the proper way to
> convert it to a run-time expression is to explicitly quote it. Consider the
> following test case:
>
> (let-syntax ([#%datum (lambda (stx) #'(exit '0))]) (versions ("7.0"
> "7.7.0.5") "6.5"))
>
> If your macro produces eg (list (make-version-range (quote "7.0") (quote
> "7.7.0.5")) (quote "6.5")), then it's fine; if it produces (list
> (make-version-range "7.0" "7.7.0.5") "6.5"), then it would exit. This
> particular example is unlikely to happen in practice, but I think it is
> useful to think clearly about how interpret each argument of a macro. Treat
> it as a literal string or as an expression, but not both.
>
> A different design would be to say that VersionBound is an expression that
> produces a string. That would cause problems with your current grammar,
> because you couldn't tell whether `(f "1.2.3")` was a single version (whose
> value is produced by a function call) or by a range (whose lower bound is
> the variable f). But you could change the grammar to avoid that problem.
> Then you could use `expr/c` to wrap the expressions to check that at run
> time they produced strings of the proper form.
>
> Ryan
>
>
> On Thu, Dec 17, 2020 at 12:55 AM 

Re: [racket-users] TLS via make-ssl-connect@?

2020-12-11 Thread Ryan Culpepper
`make-ssl-connect@` automatically uses whatever versions of TLS the OpenSSL
library supports, including TLS 1.3 for recent versions of OpenSSL.

Ryan


On Fri, Dec 11, 2020 at 1:47 AM Sage Gerard  wrote:

> I've seen articles say "SSL" when they mean "TLS". When I read the docs
> for make-ssl-connect@, it does not clarify what algorithm backs use of
> HTTPS. Only that OpenSSL is used.
>
> Does make-ssl-connect@ track current recommendations like TLS 1.2 or 1.3,
> or is it fixed to some version of SSL?
>
> *~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/t-JBfoazXqCWIYKge0qFCn9IYCYEdzkSQD9F6IrFWT8VcrziFFcgHVz_tZolCnyFd7yq26lpLahbKBNg9Pt_mIBkwMZfjL2iGQw4bZDAVe0%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/CANy33qk-Xzz3TGgDENY0KC_C29AWDPT2VmVhfYRf%3D_GrKpNSTQ%40mail.gmail.com.


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

2021-01-03 Thread Ryan Culpepper
It's the consequence of two design goals:

1. The `module` form is separate from the `#%module-begin` syntax hook so
that the module's initial language can pick the hook macro that controls
the entire module body.

2. Racket's primitive syntax is designed so that it can be re-expanded.
(The `expand` operation should be idempotent.) Some of Racket's tools (for
example, debugging support) work by expanding code, instrumenting it, and
then re-expanding, compiling, and running the result. But a
`#%module-begin` hook macro can transform the module body in non-idempotent
ways, so that hook macro should only be called once. So the answer to "have
I already run the module's `#%module-begin` hook?" must be reflected in the
fully-expanded syntax of the module.

Ryan


On Sun, Jan 3, 2021 at 8:40 AM Michael MacLeod 
wrote:

> 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
>>> 
>>> .
>>>
>> --
> 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
> 
> .
>

-- 
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/CANy33qmm57T3jFZW_saSQ_g%3Der5BNRdARuAjtSJ%2BsMsaQnQo%3DA%40mail.gmail.com.


[racket-users] synchronization with ffi/unsafe/os-thread

2021-01-26 Thread Ryan Culpepper
I'm trying to figure out how to use ffi/unsafe/os-thread to call a
long-running foreign function in an OS thread to avoid blocking other
Racket threads. I want to communicate the result of the foreign call to the
original Racket thread and have it wake up when the call completes.
Normally I could use a channel, but OS threads are not allowed to use
Racket synchronization primitives (channels, semaphores, etc). I can't use
a spinlock, because the docs for call-in-os-thread say that mutations are
allowed but their visibility is unspecified except as synchronized by
os-semaphores. The docs for os-semaphore-wait say that if it is called by a
Racket thread (ie, not a restricted OS thread), then waiting blocks all
Racket threads, which I want to avoid.

Places already have to solve the problem of bridging OS threads and Racket
synchronization. So here's my best idea so far: use a variable (or box)
protected by an os-semaphore for communicating the result, but use a place
channel for the synchronization. The code looks like this:

(define result #f)
(define os-sema (make-os-semaphore))
(define-values (c1 c2) (place-channel))
(call-in-os-thread
 (lambda ()
   (set! result (...))
   (os-semaphore-post os-sema)
   (place-channel-put c1 'ready)))
(void (sync c2))
(os-semaphore-wait os-sema)
result

This "works", but is it reliably safe to use place-channel-put from an OS
thread? Or is there a better way to do this?

Ryan

-- 
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/CANy33qnFo1hYcasdNm%2BN29bW3HbqtuYG8X-cCkgoZpJw%3DqKDWw%40mail.gmail.com.


Re: [racket-users] synchronization with ffi/unsafe/os-thread

2021-01-26 Thread Ryan Culpepper
On Tue, Jan 26, 2021 at 1:23 PM Matthew Flatt  wrote:

> At Tue, 26 Jan 2021 10:25:42 +0100, Ryan Culpepper wrote:
> > This "works", but is it reliably safe to use place-channel-put from an OS
> > thread?
>
> No. It's not intended to work from an arbitrary OS thread, and because
> `place-channel-put` touches the thread scheduler to enter atomic mode,
> I can imagine that it might go wrong either now or with some small
> future change.
>
> > Or is there a better way to do this?
>
> Probably the only way currently is to use `unsafe-poller`. See
> "rktrl.rkt" in "readline" for an example. It would make sense to make
> that part of `ffi/unsafe/thread` or a new `ffi/unsafe` library. (It
> would also be good to add `unsafe-make-signal-received` to
> `ffi/unsafe/schedule`.)
>

Thanks for the pointer! Those sound useful, but in the spirit of maximum
caution, is there a guarantee that the write to the box from the new OS
thread will be visible to the original Racket OS thread when the poller
tries to read it? Is `box-cas!` or one of the memory-order operations
needed?

Ryan

-- 
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/CANy33qm9Fu%3DxPWSG%2BPRoG9Pbfddo0FJQLnb_CWr8isvCmGNSfQ%40mail.gmail.com.


Re: [racket-users] synchronization with ffi/unsafe/os-thread

2021-01-26 Thread Ryan Culpepper
On Tue, Jan 26, 2021 at 3:06 PM Matthew Flatt  wrote:

> At Tue, 26 Jan 2021 14:49:22 +0100, Ryan Culpepper wrote:
> > Thanks for the pointer! Those sound useful, but in the spirit of maximum
> > caution, is there a guarantee that the write to the box from the new OS
> > thread will be visible to the original Racket OS thread when the poller
> > tries to read it? Is `box-cas!` or one of the memory-order operations
> > needed?
>
> I think enough synchronization is implied by `(signal-received)` and
> the way it interacts with the scheduler. That is, there's no guarantee
> that the waiting thread sees a box change right away, but signaling the
> waiting thread will imply a barrier on both the signaling side and
> waiting side, so that the next poll iteration after receiving the
> signal will definitely see the update at the latest. If that sounds
> right, we could make that a guarantee for signaling and polling.
>

That sounds reasonable. Thanks!

Ryan

-- 
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/CANy33q%3DETxYur_5VNFmdROjqg69u_gRWgqwmNq%3DW5cFQKnEOPQ%40mail.gmail.com.


Re: [racket-users] Injecting local contracts for prefab constructors

2021-05-09 Thread Ryan Culpepper
I'm not clear on what constraints you're working under with respect to
modules, but hopefully you can adapt this to your needs.

One option is to use a combination of `define-module-boundary-contract` (or
`define/contract`) and `define-match-expander` to bind a name that can be
used as a contracted constructor and as a match pattern. (If you want to
extend the struct type, though, you still need to use the real one.)

Another option would be to "forge" a new compile-time struct-info based on
the original struct-info but replacing the constructor.

Minimally tested sample implementations attached.

Ryan


On Mon, May 10, 2021 at 12:23 AM Sage Gerard  wrote:

> I have a project with 57 prefab structure types. I need to construct
> instances using a *local* contract (module level contracts do not fit my
> needs here). Since I cannot define guards, the solution is easy enough.
> (struct foo (num) #:prefab)
> (define/contract make-foo (-> real? foo?) foo)
>
> Problem: I already have a few hundred constructor calls without contracts.
> I could either A) rewrite them all to use contracted constructors, or B)
> attach local contracts in a sweet spot so that I don't have to rewrite
> anything else.
>
> I prefer option B, but it doesn't look like I can attach a local contract
> to a constructor with `struct` alone, or even with an impersonator. When I
> hack around to rebind or hide the constructor's identifier, I break
> compatibility with `match` and `defstruct*`.
>
> If you were in my position, what would you do?
> --
>
> ~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/0a16cfbe-4789-a939-796e-5f6f9da21626%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/CANy33qmngGoVoAok6%2BR885jkh8MroMqYHpOd6XtjCSH7iiESQA%40mail.gmail.com.


prefab-contract.rkt
Description: Binary data


Re: [racket-users] macros in Racket repository

2021-05-09 Thread Ryan Culpepper
Here are the three most convenient ways I know of to find that information
(which is "$RACKET/collects/racket/private/qq-and-or.rkt" in this specific
case):

If you use DrRacket, then open a file that uses `and`, right-click on an
occurrence of `and`, and choose "Open Defining File" (which changes to
"Jump to Definition (in Other File)" once DrRacket opens the file.

If you use Emacs with racket-mode, go to an occurrence of `and` and hit
"M-." (that is, hold down Meta/Alt and press the period key). You can also
use "M-x racket-visit-definition". That opens the defining module and jumps
to the definition.

If you have the `whereis` package installed, run the command `raco whereis
-b racket/base and` and it will print the path of the defining file.

Ryan


On Sun, May 9, 2021 at 3:26 PM Tim Meehan  wrote:

> Where in the repository are macros like "and" and "or" defined?
> I tried searching for "and" and "or" ... but you probably know how that
> worked out.
>
> Thanks folks!
>
> --
> 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/CACgrOxK6S8EOAGk_rPbE%2B_wMLJiSbpwMhVd4AeRL8C9%2BDW3mgg%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/CANy33q%3DsLEH-ooUJxTay6pG1GNcRLZDUotNJ23L1HRTC1XqHwA%40mail.gmail.com.


Re: [racket-users] Tell require where to find C libraries ?

2021-05-07 Thread Ryan Culpepper
Sorry, I did miss those emails.

What do you see if you try (require taglib) after starting Racket with
logging for "ffi-lib"? For example:

  $ PLTSTDERR="debug@ffi-lib" racket
   unrelated logging 
  > (require taglib)
  ???

If it lists the file you pointed to in your email and says "(exists)", then
the problem is probably that loading fails because libtag_c.so.0 depends on
another shared library, and the dependency couldn't be found. On Linux, I
would inspect shared library dependencies with the ldd command, but I don't
know what to use on OpenBSD.

---

I see that setting LD_LIBRARY_PATH worked for you. The difference between
Racket's search path (reported by get-lib-search-dirs) and the OS search
path (which LD_LIBRARY_PATH extends) is that Racket's search path only
applies to shared libraries loaded directly from Racket using ffi-lib; it
doesn't apply to any other shared libraries that they depend on.

Ryan


On Fri, May 7, 2021 at 5:03 PM krs...@gmail.com  wrote:

> Thanks for your help all!
> I think you didn't see my last 2 replies.
>
> I compiled taglib locally and set the library include path as seen in the
> racket REPL output.
> I shouldn't need to do the symlink because my version is now the exact
> same file name as the REPL says cant be found.
> (I it anyway, and it says same error file doesnt exist)
>
> Also I ran:
> (get-lib-search-dirs)
> '(#
>   #
>   #)  <-- LOOK AT THE DIR
>
> The actaul file name that it says it cannot find is in that directory.
> wise@dug:/home/wise$ ls -1 /home/wise/root/lib/   <--
> THIS IS IN MY "lib-search-dirs"
>
>
> libtag.a
> libtag.so.1
> libtag.so.1.18.0
> libtag_c.a
> libtag_c.so.0   <-- THIS IS THE FILE IT SAYS CANNOT BE FOUND
> libtag_c.so.0.0.0
> pkgconfig
>
>
> > (require taglib)
> ; ffi-lib: could not load foreign library
> ;   path: libtag_c.so.0   <-- SAYS IT CANNOT FIND THIS FILE
> ;   system error: File not found
>
>
>
> On Friday, May 7, 2021 at 10:29:21 AM UTC-4 rmculp...@gmail.com wrote:
>
>> It looks like there are two issues. One is the shared library's
>> directory, but the other is that the Racket library is looking for
>> "libtag_c.so.0", and you have "libtag_c.so.3.0". That is, it's looking for
>> a version suffix of "0", not "3.0" (see
>> https://github.com/takikawa/taglib-racket/blob/master/taglib/taglib.rkt#L83
>> ).
>>
>> One fix would be to change the Racket code to try "3.0" also. Maybe
>> conditioned on the OS, since on Ubuntu I also get the library with suffix
>> "0".
>>
>> An alternative would be to copy or link /usr/local/lib/libtag_c.so.3.0 to
>> Racket's lib directory with the file name the Racket code is trying to load:
>>
>>   ln -s /usr/local/lib/libtag_c.so.3.0
>> ~/.local/share/racket/7.9/lib/libtag_c.so.0
>>
>> Note: that assumes that the library versions are actually compatible;
>> otherwise, the Racket code is likely to misbehave, even if it loads the
>> library. Loading the shared library might still fail if the shared library
>> itself has dependencies that are not in the default OS search path. (In
>> that case, Nate's point about LD_LIBRARY_PATH might help.)
>>
>> Ryan
>>
>>
>> On Fri, May 7, 2021 at 3:12 PM krs...@gmail.com  wrote:
>>
>>> I know it sees my custom dir, I ran this in racket:
>>> > (require setup/dirs)
>>> > (get-lib-search-dirs)
>>> '(#
>>>   #
>>>   #)
>>>
>>>
>>> On Friday, May 7, 2021 at 8:08:26 AM UTC-4 krs...@gmail.com wrote:
>>>
 I'm so close :)

 I installed taglib locally to /home/wise/root/lib, so I *have* the file
 exactly as racket is complaining about:
 /home/wise/root/lib/libtag_c.so.0

 I used your config example to edit (as root) /etc/racket/config.rktd
 I added the "lib-search-dirs" line, so it looks like:
 ;; generated by unixstyle-install
 #hash(
   (doc-dir . "/usr/local/share/doc/racket")
   (lib-dir . "/usr/local/lib/racket")
   (share-dir . "/usr/local/share/racket")
   (include-dir . "/usr/local/include/racket")
   (bin-dir . "/usr/local/bin")
   (apps-dir . "/usr/local/share/applications")
   (man-dir . "/usr/local/man")
   (absolute-installation? . #t)
   (build-stamp . "")
   (doc-search-url . "
 https://download.racket-lang.org/releases/7.9/doc/local-redirect/index.html
 ")
   (catalogs . ("
 https://download.racket-lang.org/releases/7.9/catalog/;))
   (lib-search-dirs . (#f "/home/wise/root/lib"))
 )

 I still get the error:
 Welcome to Racket v7.9 [cs].

 > (require taglib)
 ; ffi-lib: could not load foreign library
 ;   path: libtag_c.so.0
 ;   system error: File not found
 ; [,bt for context]

 I'm still poking at it, thanks again for the help.

 On Thursday, May 6, 2021 at 11:41:03 PM UTC-4 krs...@gmail.com wrote:

> Thanks for the help!
> I was sure that was going to be it but it's not :(
>
> This is what is on my 

Re: [racket-users] Tell require where to find C libraries ?

2021-05-07 Thread Ryan Culpepper
It looks like there are two issues. One is the shared library's directory,
but the other is that the Racket library is looking for "libtag_c.so.0",
and you have "libtag_c.so.3.0". That is, it's looking for a version suffix
of "0", not "3.0" (see
https://github.com/takikawa/taglib-racket/blob/master/taglib/taglib.rkt#L83
).

One fix would be to change the Racket code to try "3.0" also. Maybe
conditioned on the OS, since on Ubuntu I also get the library with suffix
"0".

An alternative would be to copy or link /usr/local/lib/libtag_c.so.3.0 to
Racket's lib directory with the file name the Racket code is trying to load:

  ln -s /usr/local/lib/libtag_c.so.3.0
~/.local/share/racket/7.9/lib/libtag_c.so.0

Note: that assumes that the library versions are actually compatible;
otherwise, the Racket code is likely to misbehave, even if it loads the
library. Loading the shared library might still fail if the shared library
itself has dependencies that are not in the default OS search path. (In
that case, Nate's point about LD_LIBRARY_PATH might help.)

Ryan


On Fri, May 7, 2021 at 3:12 PM krs...@gmail.com  wrote:

> I know it sees my custom dir, I ran this in racket:
> > (require setup/dirs)
> > (get-lib-search-dirs)
> '(#
>   #
>   #)
>
>
> On Friday, May 7, 2021 at 8:08:26 AM UTC-4 krs...@gmail.com wrote:
>
>> I'm so close :)
>>
>> I installed taglib locally to /home/wise/root/lib, so I *have* the file
>> exactly as racket is complaining about:
>> /home/wise/root/lib/libtag_c.so.0
>>
>> I used your config example to edit (as root) /etc/racket/config.rktd
>> I added the "lib-search-dirs" line, so it looks like:
>> ;; generated by unixstyle-install
>> #hash(
>>   (doc-dir . "/usr/local/share/doc/racket")
>>   (lib-dir . "/usr/local/lib/racket")
>>   (share-dir . "/usr/local/share/racket")
>>   (include-dir . "/usr/local/include/racket")
>>   (bin-dir . "/usr/local/bin")
>>   (apps-dir . "/usr/local/share/applications")
>>   (man-dir . "/usr/local/man")
>>   (absolute-installation? . #t)
>>   (build-stamp . "")
>>   (doc-search-url . "
>> https://download.racket-lang.org/releases/7.9/doc/local-redirect/index.html
>> ")
>>   (catalogs . ("
>> https://download.racket-lang.org/releases/7.9/catalog/;))
>>   (lib-search-dirs . (#f "/home/wise/root/lib"))
>> )
>>
>> I still get the error:
>> Welcome to Racket v7.9 [cs].
>>
>> > (require taglib)
>> ; ffi-lib: could not load foreign library
>> ;   path: libtag_c.so.0
>> ;   system error: File not found
>> ; [,bt for context]
>>
>> I'm still poking at it, thanks again for the help.
>>
>> On Thursday, May 6, 2021 at 11:41:03 PM UTC-4 krs...@gmail.com wrote:
>>
>>> Thanks for the help!
>>> I was sure that was going to be it but it's not :(
>>>
>>> This is what is on my system:
>>> /usr/local/lib/libtag_c.so.3.0
>>>
>>> racket is looking for libtag_c.so.0
>>>
>>> So i'm not sure what to do next.
>>>
>>> On Thursday, May 6, 2021 at 7:21:10 PM UTC-4 johnbclements wrote:
>>>
 It looks to me like you probably need to edit your “config.rktd” file:


 https://docs.racket-lang.org/raco/config-file.html?q=config.rktd#%28idx._%28gentag._67._%28lib._scribblings%2Fraco%2Fraco..scrbl%29%29%29

 On my machine (macOS using macports), for instance I have do do this
 for every new installation of drracket:

 - edit /config.rktd to contain
 (lib-search-dirs . (#f "/opt/local/lib”))

 Let me know if I misunderstood your situation!

 John Clements


 > On May 6, 2021, at 3:54 AM, krs...@gmail.com 
 wrote:
 >
 >
 > Hi!,
 >
 > I am doing: (require taglib) and I get:
 > > (require taglib)
 > ; ffi-lib: could not load foreign library
 > ; path: libtag_c.so.0
 > ; system error: File not found
 > ; [,bt for context]
 >
 > I am on OpenBSD and that file is at:
 > /usr/local/lib/libtag_c.so.3.0
 >
 > How can I change my search path for C libs to be /usr/local ?
 >
 > --
 > 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...@googlegroups.com.
 > To view this discussion on the web visit
 https://groups.google.com/d/msgid/racket-users/b8425f0a-6d45-4954-9e32-df51aa5151cbn%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/59a44f94-5931-46cd-ba3b-039c02a47076n%40googlegroups.com
> 
> .
>

-- 
You received this message 

Re: [racket-users] Re: Do I need to explicitly enable readline support for the REPL?

2021-03-13 Thread Ryan Culpepper
Yes, since version 6.7 Racket automatically loads xrepl, which
automatically loads readline support (or libedit support, if readline-gpl
is not installed).

Ryan


On Sat, Mar 13, 2021 at 8:39 AM Tim Lee  wrote:

> Is it possible that the documentation is outdated?
>
> According to
> https://docs.racket-lang.org/readline/index.html#%28part._.Normal_.Use_of_.Readline%29
> :
>
> > You can also put (require readline) in your "~/.racketrc", so that Racket
> > automatically loads Readline support in interactive mode.
>
> Is this unnecessary now?
>
> --
> 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/20210313073934.blz7pstpqv7wvraq%40home-guest
> .
>

-- 
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/CANy33qkLRtZLDMoG8ODJV%3DMTZ90OE%3DH0bAE_wtwDaDOB1L4o8Q%40mail.gmail.com.


Re: [racket-users] Parenthesizing infix expressions in Redex renderings?

2021-02-24 Thread Ryan Culpepper
The `binary-rw` function from unstable/gui/redex library has some support
for optionally parenthesizing its arguments.

Ryan


On Wed, Feb 24, 2021 at 11:07 AM David Thrane Christiansen <
da...@davidchristiansen.dk> wrote:

> Hello all,
>
> I'm working on coding up a little language model in Redex, and I'd like to
> get it to render things in the form that my colleagues are used to. This
> means some infix operators as well as dealing with parenthesizing based on
> operator precedence.
>
> Here's a boiled-down sample of what I'm up to:
>
> #lang racket
>
> (require redex pict)
>
> (define-language L
>   (C success (then C C) (or C C)))
>
> (with-compound-rewriters
>   (['or (match-lambda [(list _ _ x y _) (list "" x " or " y "")])]
>['then (match-lambda [(list _ _ x y _) (list "" x " then " y "")])])
>   (vl-append
>20
>(render-language L)
>(render-term L (then (or success success) success
>
> I've attached the result. The resulting rendering of L looks appropriate,
> but the nesting of then and or in the rendered term does not indicate the
> nesting. I'd like to be able to specify precedence and associativity and
> have parentheses inserted appropriately; failing that, a reasonable backup
> would be parenthesizing sub-expressions that are not atomic.
>
> Can anyone point me at the right resource to use to figure out how to do
> this?
>
> Thank you!
>
> David
>
> --
> 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/CAF_itEtHuJP6i%3DR3_ggKTn1%3DRDmswZfCiFMYJqBwcHqpXB7fpw%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/CANy33qmAv_KzhBj_%2B3NezyXgt6vAzL_M6dF0J9S%3DRZkQyA1HSQ%40mail.gmail.com.


Re: [racket-users] How do I, a client, get a copy of an untrusted server certificate?

2021-04-12 Thread Ryan Culpepper
Racket does not provide a way to do that.

You can use `openssl s_client -showcerts -connect host:port < /dev/null` to
get the server's certificate chain in PEM form (with other logs around it).
Of course, an attacker could intercept the connection and send you their CA
certificate instead. It would be safer if example.com published their
certificate in a (standardly) trusted location.

If you do something like this, consider mitigating the danger by having the
user add the certificate to a separate location managed by your application
rather than the OS trust store. You can extend the
`ssl-default-verify-sources` parameter to point to a file containing
additional root certificates.

Ryan


On Mon, Apr 12, 2021 at 3:20 PM Sage Gerard  wrote:

> When ssl-connect fails due to an untrusted certificate, this error is
> raised:
>
> ssl-connect: connect failed (error:1416F086:SSL
> routines:tls_process_server_certificate:certificate verify failed)
>
> I'd like to give the user a more helpful error, like this:
>
> Could not connect due to an untrusted certificate. In many cases, it is
> not advisable to proceed. However, if you trust the server at
> example.com, add /tmp/example.com.cert to your trusted certificates
> using this guide: 
>
> How can I get a copy of the offending certificate so that I can do this?
>
> --
> ~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/8a55256d-71ed-b47f-5b92-c958438c5659%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/CANy33qnnqy9HFW3UyOZ%3DiqO_Xz%3DSuVJ%2BZ%2Bv_paOFSKD7M%3Dgqpw%40mail.gmail.com.


Re: [racket-users] How do I, a client, get a copy of an untrusted server certificate?

2021-04-12 Thread Ryan Culpepper
Yes, that's right.

Ryan


On Mon, Apr 12, 2021 at 4:23 PM Sage Gerard  wrote:

> Understood, thank you. By "trusted location," do you mean a server with a
> certificate that operating systems already trust?
> On 4/12/21 10:15 AM, Ryan Culpepper wrote:
>
> Racket does not provide a way to do that.
>
> You can use `openssl s_client -showcerts -connect host:port < /dev/null`
> to get the server's certificate chain in PEM form (with other logs around
> it). Of course, an attacker could intercept the connection and send you
> their CA certificate instead. It would be safer if example.com published
> their certificate in a (standardly) trusted location.
>
> If you do something like this, consider mitigating the danger by having
> the user add the certificate to a separate location managed by your
> application rather than the OS trust store. You can extend the
> `ssl-default-verify-sources` parameter to point to a file containing
> additional root certificates.
>
> Ryan
>
>
> On Mon, Apr 12, 2021 at 3:20 PM Sage Gerard  wrote:
>
>> When ssl-connect fails due to an untrusted certificate, this error is
>> raised:
>>
>> ssl-connect: connect failed (error:1416F086:SSL
>> routines:tls_process_server_certificate:certificate verify failed)
>>
>> I'd like to give the user a more helpful error, like this:
>>
>> Could not connect due to an untrusted certificate. In many cases, it is
>> not advisable to proceed. However, if you trust the server at
>> example.com, add /tmp/example.com.cert to your trusted certificates
>> using this guide: 
>>
>> How can I get a copy of the offending certificate so that I can do this?
>>
>> --
>> ~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/8a55256d-71ed-b47f-5b92-c958438c5659%40sagegerard.com
>> .
>>
> --
> ~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/8edbd1fd-715d-a730-5659-3731518c5fba%40sagegerard.com
> <https://groups.google.com/d/msgid/racket-users/8edbd1fd-715d-a730-5659-3731518c5fba%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/CANy33qm0ZGX4MviFJZVq9x8Ax7Cx7yW9nNTZbWu2ha2r72LPRg%40mail.gmail.com.


Re: [racket-users] Obtaining the path of the application program?

2021-08-26 Thread Ryan Culpepper
Usually, if you want to refer to data files etc relative to the current
module's file, a good solution is to use `define-runtime-path`. It uses
`#%variable-reference` as the basis for its implementation, but adds other
features like cooperation with `raco exe` (see docs for
`define-runtime-path` near "an executable creator").

Ryan


On Thu, Aug 26, 2021 at 4:51 PM Jeff Henrikson  wrote:

> Racket users,
>
> Many software applications use their location in the filesystem to
> establish filesystem relationships between their executable file, their
> configuration and their data.  For this purpose, C provides the first
> element of the string array provided to main, python provides __file__,
> bash provides ${BASH_SOURCE[0]}, etc.
>
> Racket strips said value before current-command-line-arguments receives
> the subsequent command-line arguments from the operating system.
>
> A related value can be pulled from syntax-source as follows:
>
> (define-syntax (get-current-source stx)
>   (datum->syntax
>(quote-syntax here)
>(syntax-source stx)
>stx))
>
> Macro get-current-source works as intended if called at program startup
> and the program is compiled on the fly with:
>
> racket program.rkt
>
> However get-current-source has the unintended property of memorizing the
> original source location if the program is compiled with raco exe (and then
> moved).
> Is there a way in racket to obtain the path of the application program?
>
>
> Jeff Henrikson
>
>
> --
> 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/a076dfa2-d1a5-3cda-72ae-a30cdb91dc31%40gmail.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/CANy33q%3D-suP4a_GKtBeBYWUS6P%3D-WNvDo5mFa1cAgFWUi6bEYQ%40mail.gmail.com.


Re: [racket-users] How to set up rackunit tests to test the REPL?

2021-09-09 Thread Ryan Culpepper
This is one of the few (IMO) legitimate uses of `eval`.

Your test suite should create a namespace, set it up by requiring your
language's module, and then eval interactions expressed as quoted
S-expressions or syntax objects. Here's a basic example for testing `match`:

#lang racket/base
(require syntax/strip-context rackunit)

(define test-ns (make-base-empty-namespace))
(parameterize ((current-namespace test-ns))
  (namespace-require 'racket/base)
  (namespace-require 'racket/match))

;; test-eval : (U Syntax S-expr) -> Any
(define (test-eval expr)
  (parameterize ((current-namespace test-ns))
(eval `(#%top-interaction
. ,(cond [(syntax? expr)
  (namespace-syntax-introduce
   (strip-context expr))]
 [else expr])

(check-equal? (test-eval
   '(match (list 1 2 3)
  [(cons x ys) x]
  [_ #f]))
  1)

(void (test-eval '(define null? zero?))) ;; !!!

(check-equal? (test-eval
   #'(match 0
   [(? null?) 'ok]
   [_ 'no]))
  'ok)

The call to `strip-syntax` is necessary in the second test to make `null?`
refer to the redefinition in the testing namespace instead of the normal
binding visible to the testing module.

Ryan


On Thu, Sep 9, 2021 at 3:31 AM Kuang-Chen Lu 
wrote:

> Hi,
>
> What are the recommended ways to create unit tests that test *both* run
> *and* REPL (#%top-interaction)?
>
> *Background:* I created a custom language and have some unit tests. My
> updated language passed all unit tests. After delivery, a client ran into a
> bug that only happens in REPL. I could have found the bug if the REPL was
> also tested.
>
> Thanks,
>
> KC
>
> --
> 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/e768fbf6-81db-4bb9-9195-6e3ce74a2d55n%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/CANy33q%3D-exnqEROJ1SDngO54T4erg7NUMTSZWagG-KdYO67HzA%40mail.gmail.com.


<    1   2