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


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


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


[racket-users] CFP: 4th Workshop on Meta-Programming Techniques and Reflection (Meta'19), Co-located with SPLASH 2019

2019-07-15 Thread Ryan Culpepper



   Call for Papers

  4th Workshop on Meta-Programming Techniques and Reflection (Meta’19)

 Co-located with SPLASH 2019
October 20, 2019, Athens, Greece

   https://2019.splashcon.org/track/meta-2019
  Follow us on twitter @MetaAtSPLASH



The Meta’19 workshop aims to bring together researchers working
on metaprogramming and reflection, as well as users building
applications, language extensions and/or software tools using
them.

The challenges which metaprogramming faces are manifold. They
start with formal reasoning about reflective programs, continue
with performance and tooling, and reach into the empirical field
to understand how metaprogramming is used and how it affects
software maintainability.

While industry accepted metaprogramming on a wide scale with
Ruby, Scala, JavaScript, R and others, there is still a long road
ahead to bring the same level of convenience, tooling, and
understanding as for direct programming styles.

Contributions to the workshop are welcome on a wide range of
topics related to the design, implementation, and application of
metaprogramming techniques, as well as empirical studies and
formal methods for such systems and languages.

### Topics of Interest

The workshop is a venue for all approaches that embrace
metaprogramming, from static to dynamic techniques:

- reflection, meta-level architectures, staging, open language
  runtimes applications to middleware, frameworks, and DSLs
- optimization techniques
- contract systems, or typing of reflective programs
- reflection and metaobject protocols to enable tooling
- case studies and evaluation of such techniques, e.g., to build
  applications, language extensions, or tools
- empirical evaluation of metaprogramming solutions
- security in reflective systems and capability-based designs
- meta-level architectures and reflective middleware for modern
  runtime platforms (e.g. IoT, cyber-physical systems,
  mobile/cloud/grid computing, etc)
- surveys, conceptualization, taxonomization, and formalization
  of existing approaches

### Workshop Format and Submissions

This workshop welcomes the presentation of new ideas and emerging
problems as well as mature work as part of a mini-conference
format.  Furthermore, we plan interactive brainstorming and
demonstration sessions between the formal presentations to enable
an active exchange of ideas.

Papers submitted by the first deadline will be considered for
publication in the ACM DL, if not requested otherwise by the
authors. Thus, they will be part of SPLASH workshop proceedings.

For all papers, use of the SIGPLAN acmart style is mandatory:

  http://www.sigplan.org/Resources/Author/

Please use the provided double-column templates for Latex or Word.

  technical paper: max. 8 pages, excluding references
  position and work-in-progress paper: 1-4 pages, excluding references
  technology demos or a posters: 1-page abstract

Demos, posters, position and work-in-progress papers can be
submitted on a second, later deadline to discuss the latest
results and current work, but will not be considered for
publication in the ACM DL.

For the submission, please use the submission system at:

  https://meta19.hotcrp.com/


### Important Dates

26 Jul 2019  - Abstract Submission
 2 Aug 2019  - Paper Submission (considered for ACM DL)
23 Aug 2019  - Notification
28 Aug 2019  - Demo, position or work-in-progress paper submission
20 Sep 2019  - Demo, position or work-in-progress paper notification

### Steering Committee

Elisa Gonzalez Boix, Vrije Universiteit Brussel
Stefan Marr, University of Kent

### Organizing Committee

Guido Chari, Czech Technical University
Christophe Scholliers, Ghent University

### Program Committee

Nada Amin, University of Cambridge, UK
Edwin Brady, University of St Andrews, UK
Andrei Chis, Feenk, Switzerland
David Thrane Christiansen, Galois, Portland, Oregon, USA
Tom Van Cutsem, Bell Labs, Belgium
Ryan Culpepper, Czech Technical University, Prague, Czechia
Jennifer Hacket, University of Nottingham, UK
Robert Hirschfield, Hasso Plattner Institute, Germany
James Noble, Victoria University Wellington, New Zealand
Bruno C. d. S. Oliveira, The University of Hong Kong
Cyrus Omar, University of Chicago, USA
Guillermo Polito, Inria Lille, France
Eric Tanter, Universidad de Chile, Chile

### Contact Information

For further inquiries, do not hesitate to contact the organizers
via meta-at-splash19 AT googlegroups.com

http://2019.splashcon.org/track/meta-2019

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

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] Racket SIGSEGV during FFI call

2019-06-26 Thread Ryan Culpepper

On 6/26/19 6:34 AM, Christopher Howard wrote:
Hi, I have a project going to make Racket bindings to the libhackrf C 
library installed on my Debian 9 system. I have successfully made and 
used bindings to around a dozen procedures in the library. However, when 
I get to the first really important one, my call is crashing with a 
SIGSEGV. I have this procedure defined:


(define-hackrf hackrf_start_rx (_fun (_cpointer 'hackrf_device)
  (_fun _pointer -> _int)
  _pointer -> _int))

This procedure takes a pointer to a device, a callback function, and 
another pointer (which I won't go into but is supposed to be null 
usually). Internally, hackrf_start_rx is a C procedure which generates a 
pthread which repeatedly calls the callback function while receiving 
data, while the original thread returns 0.


It's not safe to call Racket procedures from other OS-level threads, but 
you can tell the Racket FFI to work around that restriction by using the 
`#:async-apply` argument to the inner `_fun` type.


If the callback function is simple and doesn't rely on being run in any 
particular thread (for example, it doesn't use any parameters like the 
current output port), then you can try changing the inner function type 
to the following:


  (_fun #:async-apply (lambda (p) (p)) _pointer -> _int)

If that doesn't work, I think you'll have to do something more 
complicated with Racket threads. Maybe someone knows a simple example?


Also, you might want to look at the `#:keep` argument. Racket's GC 
doesn't know about references held by foreign libraries, so you need to 
make sure that callback function doesn't get collected. (In your 
example, you made `cb` a top-level definition, which means that value 
won't be GC'd as long as the definition's namespace is still around.)


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/de844eb0-72db-c626-d901-f09eda0031b5%40ccs.neu.edu.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] exercise 1, racket school 2018

2019-06-17 Thread Ryan Culpepper

On 6/17/19 4:20 PM, Robert Girault wrote:

I was able to do the first half of exercise 1 (see sources at the end
of this message) --- write a macro computing some information at
run-time.  The second half is to write the same macro, but computing
some information at compile-time --- I couldn't do this one.  I'm
looking for some directions on how to achieve this.

(*) Context

; Syntax -> Syntax
; (define-world* name ...) defines all name ... to stand for a string
(define-syntax (define-world* stx)
   (syntax-parse stx
 ((_ x:id ...)
  #'(define-values (x ...) (values (begin 'x "world") ...)

(*) Exercise 1

Exercise 1. Modify define-world* so that it binds each given
identifier to its place in the sequence. We start counting at 0 so
that

(define-world* x y z)

binds x to 0, y to 1, and so on.


Hint 1: If you were going to translate this one example by hand, here's 
one way to do it:


  (define-values (x y z) (values 0 1 2))

Hint 2: Here's another way to do it:

  (begin (define x 0) (define y 1) (define z 2))

Why might the first version be "better" than the second version (from a 
macro-writer's point of view, at least)?


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/9aa7b28d-97db-43aa-46a4-336683cce65f%40ccs.neu.edu.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Getting JSON to work with the DB module

2019-04-23 Thread Ryan Culpepper
It is not possible, unfortunately. You must do the conversion to and 
from strings yourself.


I've thought about adding a hook for additional conversions based on 
declared types, but there's no declared type information at all for 
parameters, and the declared type for results is fragile: a column name 
has a declared type but no other kind of expression does.


Ryan


On 4/23/19 20:03, David Storrs wrote:
tl;dr  I'm having trouble getting JSON support working in the db module 
when using SQLite and would really appreciate some direction, or 
confirmation that it's impossible.  I suspect that it's impossible, 
since the docs list the accepted Racket types as exact-integer?, real?, 
string?, and bytes?.  I was hoping that having the JSON extension in 
would add conversion ability to this, but it looks like not.



Longer:
SQLite does not natively support JSON, but there's an extension that can 
be dynamically- or statically linked. https://sqlite.org/json1.html


When working with a Postgres database, the DB module will handle 
transforming things (e.g. hashes) to and from JSON on insert/select, 
which is insanely useful and convenient.  I'd like to get the same 
behavior in SQLite, especially since that would let me use the json_agg 
function which would be a reasonable replacement for Pg's ARAAY_AGG 
feature, of which I make heavy use.




Here's what I've done so far:

0. I've read the docs on the db module carefully, which has me concerned 
about whether this is possible at all.  Still, optimism!

1. I've compiled the JSON1 extension into the libsqlite.* files
2. I've verified that JSON is working via the sqlite CLI client (i.e., 
not the Racket db module)
3. I've put the libsqlite.* files in my /Applications/Racket_v7.1/lib 
directory (one of the entries in (get-lib-search-dirs)).


At this point I tried this:

 > (require json db)
 > (define db (sqlite3-connect #:database "foo.db"))
 > (query db "create temporary table blogsnort (id integer primary key, 
data json))

(simple-result '((insert-id . #f) (affected-rows . 0)))

 > (query db "insert into blogsnort (data) values ($1)" (hash 'a 1))
; query: cannot convert given value to SQL type
;   given: '#hash((a . 1))
;   type: parameter
;   dialect: SQLite
; [,bt for context]

I tried setting the storage class on the 'data' column to TEXT (I wasn't 
sure if the JSON extension added a 'JSON' type but figured it was worth 
trying), but that made no difference.


Am I right that it's simply impossible and that I'll need to manually 
convert to/from strings?




--
You received this message because you are subscribed to the Google 
Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to racket-users+unsubscr...@googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] how do I clear this FFI-related build error?

2019-04-23 Thread Ryan Culpepper

On 4/23/19 23:14, Matthew Butterick wrote:

Some code relies on the `harfbuzz` library, like so:

(define-runtime-lib harfbuzz-lib
   [(unix) (ffi-lib "libharfbuzz" '("1" ""))]
   [(macosx) (ffi-lib "libharfbuzz.0.dylib")]
   [(windows) (ffi-lib "libharfbuzz-0.dll")])


Though this works on my Mac machines, the doc server throws an error: [1]

raco setup:   ffi-obj: couldn't get "hb_buffer_add_codepoints" from 
"libharfbuzz.so" (/usr/lib/x86_64-linux-gnu/libharfbuzz.so: undefined symbol: 
hb_buffer_add_codepoints)


The `hb_buffer_add_codepoints` function was added in Harfbuzz 0.9.31, 
but according to Racket's readme, it ships with Harfbuzz 1.7.6 [2]


Judging by the Harfbuzz path in the error message, I wonder if I'm 
inadvertently invoking some local copy of Harfbuzz (which is out of 
date) rather than the one that ships with Racket (which isn't). But if 
so, I don't know how to change the `define-runtime-lib` incantation to 
make it work.


It looks like natipkg Racket includes libharfbuzz.so.0, not 
libharfbuzz.so.1 (see [1]). So try changing the unix line to


[(unix) (ffi-lib "libharfbuzz" '("0" ""))]

instead.

Ryan

[1] 
https://github.com/racket/libs/tree/master/draw-x86_64-linux-natipkg-3/racket/draw


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] db module 'query' does not return insert-id

2019-04-23 Thread Ryan Culpepper

On 4/22/19 20:36, David Storrs wrote:

 > (require db)
 > (define db (postgresql-connect  ...args...))
 > (simple-result-info (query db "insert into collaborations (name) 
values ('foojalskdsfls')"))

'((insert-id . #f) (affected-rows . 1))

 From the docs on the 'simple-result' struct:

"Represents the result of a SQL statement that does not return a 
relation, such as an INSERT or DELETE statement.


The info field is an association list, but its contents vary based on 
database system and may change in future versions of this library (even 
new minor versions). The following keys are supported for multiple 
database systems:


#

'insert-id: If the value is a positive integer, the statement was an 
INSERT statement and the value is a system-specific identifier for the 
inserted row. For PostgreSQL, the value is the row’s OID, if the table 
has OIDs (for an alternative, see the INSERT ... RETURNING statement). 
For MySQL, the value is the same as the result of last_insert_id 
 
function—that is, the value of the row’s AUTO_INCREMENT field. If there 
is no such field, the value is #f. For SQLite, the value is the same as 
the result of the last_insert_rowid 
 
function—that is, the ROWID 
 of the inserted row."



I get the same results with a SQLite connection -- the insert-id is 
always #f.  I know that it says the contents may change and that it 
varies per database, but it also specifically calls out 'insert-id as a 
thing that is supported for both of these DBs.  What am I missing?


On PostgreSQL, my guess is that your table was created without the "WITH 
OIDS" clause. For example:


  > (define c (dsn-connect 'pg))
  > (query c "create table words (t text)")
  (simple-result '())
  > (query c "insert into words (t) values ('hello')")
  (simple-result '((insert-id . #f) (affected-rows . 1)))

and here's a example for a table with "WITH OIDS":

  > (query c "create table names (t text) with oids")
  (simple-result '())
  > (query c "insert into names (t) values ('Alice')")
  (simple-result '((insert-id . 105197) (affected-rows . 1)))

On SQLite, there is a bug in the db library that suppresses insert-id if 
it is the same as the last reported insert-id (for a different table, 
for example). I'll fix that. But you should see it otherwise. For example:


  > (define c (sqlite3-connect #:database 'memory))
  > (query c "create table words (t text)")
  (simple-result '((insert-id . #f) (affected-rows . 0)))
  > (query c "insert into words (t) values ('hello')")
  (simple-result '((insert-id . 1) (affected-rows . 1)))

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] db module + SQLite driver + 'ON CONFLICT' = syntax error

2019-04-19 Thread Ryan Culpepper

On 4/18/19 23:53, David Storrs wrote:



On Thu, Apr 18, 2019 at 5:42 PM Ryan Culpepper <mailto:ry...@ccs.neu.edu>> wrote:


Use "INSERT OR IGNORE" instead. See
https://sqlite.org/lang_conflict.html, 3rd paragraph.


Yep.  Unfortunately, this was a simplified case of wanting to use OR DO 
UPDATE to make this actually an upsert.  When I started seeing this 
issue I backed it out to OR DO NOTHING in order to simplify the syntax.


Ah, okay. Try putting a recent version of the libsqlite3 shared library 
in one of the paths returned by


  (begin (require setup/dirs) (get-lib-search-dirs))

Ryan



On 4/18/19 23:28, David Storrs wrote:
 >
 >
 > On Thu, Apr 18, 2019 at 4:48 PM Jon Zeppieri mailto:zeppi...@gmail.com>
 > <mailto:zeppi...@gmail.com <mailto:zeppi...@gmail.com>>> wrote:
 >
 >     It might well be the SQLlite version. This is a pretty new
feature.
 >     It's possible that the db library is using an older version than
 >     your CLI client.
 >
 >
 > Got it.  Is there any way for me to address the situation aside from
 > "Don't use that SQL"?
 >
 >
 >     - Jon
 >
 >
 >     On Thu, Apr 18, 2019 at 4:03 PM David Storrs
mailto:david.sto...@gmail.com>
 >     <mailto:david.sto...@gmail.com
<mailto:david.sto...@gmail.com>>> wrote:
 >
 >         I'm having trouble with using the the 'ON CONFLICT'
clause with
 >         a SQLite database.  Example:
 >
 >          > (query-exec db "drop table if exists peers")
 >          > (query-exec db "create table if not exists peers (name
text)")
 >          > (query-exec db "INSERT INTO peers ( name ) VALUES
($1)" "hqwt")
 >          > (query-rows db "SELECT * FROM peers")
 >         '(#("hqwt"))
 >          > (query-exec db "INSERT INTO peers ( name ) VALUES ($1) ON
 >         CONFLICT DO NOTHING" "hqwt")
 >         ; query-exec: near "ON": syntax error
 >         ;   error code: 1
 >         ; [,bt for context]
 >
 >         I thought maybe there was some issue with the column not
being
 >         marked UNIQUE, so I did that.  No effect:
 >
 >          > (query-exec db "drop table if exists peers")
 >          > (query-exec db "create table if not exists peers (name
text
 >         UNIQUE)")
 >          > (query-exec db "INSERT INTO peers ( name ) VALUES
($1)" "hqwt")
 >          > (query-exec db "INSERT INTO peers ( name ) VALUES
($1)" "hqwt")
 >         ; query-exec: abort due to constraint violation
 >         ;   error code: 2067
 >         ;   SQL: "INSERT INTO peers ( name ) VALUES ($1)"
 >         ; [,bt for context]
 >          > (query-exec db "INSERT INTO peers ( name ) VALUES ($1) ON
 >         CONFLICT DO NOTHING" "hqwt")
 >         ; query-exec: near "ON": syntax error
 >         ;   error code: 1
 >         ; [,bt for context]
 >
 >         I've been through the SQLite documentation on the INSERT
 >         statement multiple times, and that last statement sure looks
 >         syntactically valid to me.  Furthermore, it works fine if
I use
 >         it in the OSX 10.11.6 sqlite3 CLI client.
 >
 >         What am I missing?
 >
 >         --
 >         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
<mailto:racket-users%2bunsubscr...@googlegroups.com>
 >         <mailto:racket-users+unsubscr...@googlegroups.com
<mailto:racket-users%2bunsubscr...@googlegroups.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
<mailto:racket-users%2bunsubscr...@googlegroups.com>
 > <mailto:racket-users+unsubscr...@googlegroups.com
<mailto:racket-users%2bunsubscr...@googlegroups.com>>.
 > For more options, visit https://groups.google.com/d/optout.

--
You received this message 

Re: [racket-users] db module + SQLite driver + 'ON CONFLICT' = syntax error

2019-04-19 Thread Ryan Culpepper
Use "INSERT OR IGNORE" instead. See 
https://sqlite.org/lang_conflict.html, 3rd paragraph.


Ryan


On 4/18/19 23:28, David Storrs wrote:



On Thu, Apr 18, 2019 at 4:48 PM Jon Zeppieri > wrote:


It might well be the SQLlite version. This is a pretty new feature.
It's possible that the db library is using an older version than
your CLI client.


Got it.  Is there any way for me to address the situation aside from 
"Don't use that SQL"?



- Jon


On Thu, Apr 18, 2019 at 4:03 PM David Storrs mailto:david.sto...@gmail.com>> wrote:

I'm having trouble with using the the 'ON CONFLICT' clause with
a SQLite database.  Example:

 > (query-exec db "drop table if exists peers")
 > (query-exec db "create table if not exists peers (name text)")
 > (query-exec db "INSERT INTO peers ( name ) VALUES ($1)" "hqwt")
 > (query-rows db "SELECT * FROM peers")
'(#("hqwt"))
 > (query-exec db "INSERT INTO peers ( name ) VALUES ($1) ON
CONFLICT DO NOTHING" "hqwt")
; query-exec: near "ON": syntax error
;   error code: 1
; [,bt for context]

I thought maybe there was some issue with the column not being
marked UNIQUE, so I did that.  No effect:

 > (query-exec db "drop table if exists peers")
 > (query-exec db "create table if not exists peers (name text
UNIQUE)")
 > (query-exec db "INSERT INTO peers ( name ) VALUES ($1)" "hqwt")
 > (query-exec db "INSERT INTO peers ( name ) VALUES ($1)" "hqwt")
; query-exec: abort due to constraint violation
;   error code: 2067
;   SQL: "INSERT INTO peers ( name ) VALUES ($1)"
; [,bt for context]
 > (query-exec db "INSERT INTO peers ( name ) VALUES ($1) ON
CONFLICT DO NOTHING" "hqwt")
; query-exec: near "ON": syntax error
;   error code: 1
; [,bt for context]

I've been through the SQLite documentation on the INSERT
statement multiple times, and that last statement sure looks
syntactically valid to me.  Furthermore, it works fine if I use
it in the OSX 10.11.6 sqlite3 CLI client.

What am I missing?

-- 
You received this message because you are subscribed to the

Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from
it, send an email to racket-users+unsubscr...@googlegroups.com
.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google 
Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to racket-users+unsubscr...@googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Help with evaluation of examples in Scribble

2019-03-11 Thread Ryan Culpepper

On 3/10/19 4:16 PM, Matt Jadud wrote:

Oh! Thank you, Matthew.

I see. So, I'm running into the sandbox... as in, the sandbox is doing 
what it should, and as a result, it is preventing the networked accesses 
that I've added to my documentation. That's awfully obvious (now that it 
is put that way), but it wasn't obvious from the error message.


I'll think about faking it for doc build. I'll add it to the issue 
tracker for the package. I'm still learning basic things about 
scribbling docs, but will likely stub something in to simplify the doc 
build at some point. Thanks, Robby.


You might find `make-log-based-eval` useful for writing your examples. 
It lets you run the examples once (for example, on your development 
machine where your credentials are installed, etc) and save the results, 
so other people can build the docs using the recorded interactions.


For example, it's used by the db library documentation; see config.rkt 
(defines `make-pg-eval` using `make-log-based-eval`) and using-db.scrbl 
(uses `make-pg-eval`, `interaction`, and `eval:alts`) in 
https://github.com/racket/db/blob/master/db-doc/db/scribblings/.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How do I (de)serialize PKI keys for storage?

2018-12-18 Thread Ryan Culpepper

On 12/18/18 23:36, David Storrs wrote:
I'm trying to persist public/private keys to our database and having 
some trouble:



Welcome to Racket v6.11.
 > (require crypto crypto/gcrypt)
 > (crypto-factories gcrypt-factory)
 > (define key (generate-private-key 'rsa))
 > key
(object:gcrypt-rsa-key% ...)
 > (define pub (pk-key->public-only-key key))
 > pub
(object:gcrypt-rsa-key% ...)
 > (public-key=? key pub)
#t
 > (public-key=? key (datum->pk-key (pk-key->datum key 
'OneAsymmetricKey) 'OneAsymmetricKey))

#f
 > (public-key=? key (datum->pk-key (pk-key->datum key 'RSAPrivateKey) 
'RSAPrivateKey))

#f
 > (public-key=? key (datum->pk-key (pk-key->datum key 'rkt-private) 
'rkt-private))

#f

The docs state that GCrypt does not have the ability to recompute a 
public key component form the data in a 'PrivateKeyInfo format, so 
that's no good.


pk-keys are objects, not structs, and there doesn't appear to be any way 
to say "here's a private key and a public key, composite them".


This has to be a thing that people do, so what am I missing?


The bug is in public-key=?. The serialization and deserialization are 
okay; if you try, you should see that the original and deserialized keys 
can verify each other's signatures, for example.


I've pushed a fix. Thanks for the report!

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Creating truly unique instances of structure types?

2018-11-06 Thread Ryan Culpepper

On 11/6/18 11:31 AM, Alexis King wrote:

On Nov 5, 2018, at 20:01, Ryan Culpepper  wrote:

You could use a chaperone to prohibit `struct-info`


Good point! I had forgotten that `struct-info` is a chaperoneable operation. 
This isn’t ideal, though, since I don’t think `struct-info` is ever actually 
supposed to raise an error, it’s just supposed to return #f, instead. It’s 
possible to call `struct-info` on absolutely anything, even things like 
numbers, and get a result:

> (struct-info 3)
#f
#t

If I understand correctly, this is because all values in Racket are “morally 
structures”, and reflective operations on values that are not actually 
implemented with structures should behave identically to reflective operations 
on values for which you do not have a sufficiently powerful inspector to 
inspect.

Unfortunately, it isn’t possible to regain this behavior with 
`impersonate-struct`, since `impersonate-struct` does not allow you to 
impersonate `struct-info`.


One solution is to delay the error by having `struct-info` return a 
chaperoned struct-type (using `chaperone-struct-type`) that makes 
`struct-type-make-constructor` raise an error. The struct-type chaperone 
should also prevent the creation of substruct instances (say, by adding 
a guard that always raises an error).


It seems like it should also be reasonable to let the `struct-info` 
interposition replace a struct type with #f, since that represents less 
information at the level of the *interpretation* of the operation. So 
it's morally a projection wrt the information ordering for the 
`struct-info` operation, even though it's not a projection wrt the 
generic information ordering for Racket values.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Creating truly unique instances of structure types?

2018-11-05 Thread Ryan Culpepper

On 11/5/18 5:26 PM, Alexis King wrote:

To my knowledge, there are two main techniques for creating unique values in 
Racket: `gensym` and structure type generativity. The former seems to be 
bulletproof — a value created with `gensym` will never be `equal?` to anything 
except itself – but the latter isn’t. Using reflective operations, it’s 
possible to circumvent the encapsulation afforded by the module system.

To provide an example, `racket/contract` exports a value called 
`the-unsupplied-arg`, which is created using the usual structure type 
generativity trick:

(define-struct the-unsupplied-arg ())
(define the-unsupplied-arg (make-the-unsupplied-arg))
(provide the-unsupplied-arg)

The constructor is not exported, and this value is intended to be unique. 
However, if we can arrange for the contract library to be loaded on our terms, 
we can thwart this encapsulation by supplying it with a weaker inspector:

#lang racket/base

(define the-unsupplied-arg
  (parameterize ([current-inspector (make-inspector)])
(dynamic-require 'racket/contract 'the-unsupplied-arg)))

(define-values [info skipped?] (struct-info the-unsupplied-arg))

(define another-unsupplied-arg ((struct-type-make-constructor info)))

(equal? the-unsupplied-arg another-unsupplied-arg) ; => #t
(eq? the-unsupplied-arg another-unsupplied-arg); => #f

Perhaps this isn’t the end of the world, as after all, we can’t do anything 
especially nefarious with this value, and we wouldn’t be able to do it in the 
first place if we didn’t have complete control of the inspector hierarchy. 
Still, it seems a little unsatisfying.

So, my question: is there any way to create a structure type for which there 
can truly ever only be one instance? If not, is there a fundamental reason why 
not?


You could use a chaperone to prohibit `struct-info`:

  (define the-unsupplied-arg
(chaperone-struct (make-the-unsupplied-arg)
  struct:unsupplied-arg
  struct-info (lambda _ (error "not allowed"

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Compilation/Embedding leaves syntax traces

2018-09-25 Thread Ryan Culpepper

On 9/25/18 1:11 PM, Alexis King wrote:

[] Personally, I would appreciate a way to ask
Racket to strip all phase ≥1 code and phase ≥1 dependencies from a
specified program so that I can distribute the phase 0 code and
dependencies exclusively. However, to my knowledge, Racket does not
currently include any such feature.


`raco demod -g` seems to do that, but the `-g` option is marked with a 
warning.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Using match on hash tables with optional keys

2018-08-31 Thread Ryan Culpepper

On 8/31/18 4:28 AM, Greg Hendershott wrote:

A general trick for optional values with match is something like (or
pat (app (λ _ default-value) pat)). But that doesn't work for
hash-table which uses [pat path] for each mapping. (At least I
couldn't see how.)

Here's _a_ way you could write this as a match pattern:

(define ((hash-has-keys? keys) ht)
  (for/and ([key (in-list keys)])
(hash-has-key? ht key)))

(match (hash 'a 0 'b 1)
  [(? (hash-has-keys? '(a b))
  (app (λ (ht)
 (values (hash-ref ht 'a)
 (hash-ref ht 'b)
 (hash-ref ht 'c 'c-default)))
   a b c))
   (list a b c)])

[I really don't like the hash-has-keys? business, and the resulting
double lookups. But (=> id) is available only to bodies, and
`failure-cont` didn't work for me. So I don't know how else to handle
the case where it should _not_ match.]

Obviously the above is tedious. But, it works solely in term of match
patterns, and it could be the kind of syntax that a
define-match-expander emits for some nicer surface syntax. Where each
mapping is either required [k v], or, optional and you must supply a
default [k v d]. []


Here's an implementation:

  (define not-found (gensym 'not-found))
  (define (not-not-found? x) (not (eq? x not-found)))

  (begin-for-syntax
(define-syntax-class kvpat
  #:description "hash key-value pattern"
  ;; Note: be careful to evaluate key expr only once!
  (pattern [key:expr value-pattern]
   #:with pattern
   #'(app (lambda (h) (hash-ref h key not-found))
  (? not-not-found? value-pattern)))
  (pattern [key:expr value-pattern default:expr]
   #:with pattern
   #'(app (lambda (h) (hash-ref h key (lambda () default)))
  value-pattern

  (define-match-expander hash-table*
(syntax-parser
  [(_ kv:kvpat ...)
   #'(? hash? kv.pattern ...)]))

  (match (hash 'a 1 'b 2)
[(hash-table* ['a a] ['c c 3])
 (+ a c)])
  ;; => 4

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Where to put scribblings in 'multi package?

2018-08-29 Thread Ryan Culpepper

On 08/29/2018 12:37 PM, Erich Rast wrote:

I have a preliminary scribbling for the manual
of a multi source package, but it doesn't show up in Racket's main
documentation when I install the package locally.

Here is the directory structure:

appy
|
|--info.rkt
|--appy
|
|--
|--scribblings
   |
   |--manual.scrbl

And "info.rkt" looks like this:

#lang info
(define version "0.1")
(define pkg-desc "a framework for cross-platform end-user applications
and their deployment")
(define collection 'multi)
(define distribution-preference 'source)
(define pkg-authors '("Erich Rast"))
(define scribblings '(("scribblings/manual.scrbl" main-doc
main-doc-root (library) "APPY: a framework for writing end-user GUI
applications")))

Raco install in the appy directory reports no errors, the package is
installed locally, but the "manual.scrblr" does not show up and does not
seem to be compiled. I've changed the path to
"appy/scribblings/manual.scrbl" without effect.

What's the correct way to set up the documentation? Related to this,
will raco pkg install report an error if my scribbling doesn't compile?


There are pkg-level info keys (like version, pkg-desc, collection, etc) 
and collects-level info keys (like scribblings, compile-omit-paths, 
etc). For single-collection layouts (ie, the collections key is a string 
instead of 'multi) they're combined into a single info.rkt file, but for 
multi-collection packages they're in different places.


Create a new info.rkt file in the apply *collection* directory (the same 
one that has the source files and the scribblings subdirectory) and move 
the scribblings definition there.


For an example of this organization in the main distribution, see the 
redex repository at https://github.com/racket/redex. In particular, look 
at the redex-doc (pkg) directory. It has a pkg-level info.rkt file, and 
the redex collection subdirectory has a collection-level info.rkt file 
with a scribblings entry.


(Actually, I believe any subdirectory can have an info file with keys 
like scribblings, compile-omit-paths, etc; just not the pkg root 
directory of a multi-collection package.)


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] FFI Trouble (file streams, variadic functions)

2018-08-27 Thread Ryan Culpepper
I didn't know before I tried it either. It occurred to me as a candidate 
because I've seen many warnings about conflating ordinary pointers and 
function pointers (although usually the warning is that they are not 
guaranteed to have the same size). I only discovered that note in the 
docs afterwards.


Ryan


On 08/27/2018 03:08 PM, Philip McGrath wrote:
Thanks for the very quick reply—using `_fpointer` seems to work for me, 
too. I don't think I'd noticed it in the docs before, though, even if I 
had, I don't think it would have been obvious to me that it was the 
solution to this problem.


-Philip


On Mon, Aug 27, 2018 at 8:03 AM Ryan Culpepper <mailto:ry...@ccs.neu.edu>> wrote:


On 08/27/2018 02:13 PM, Philip McGrath wrote:
 > I am hoping for some help debugging a problem I'm having writing FFI
 > bindings for libxml2.
 >
 > I am trying to use the function `xmlValidateDtd`, which
(predictably)
 > validates an XML document against a DTD. To support error
reporting, the
 > first argument to the function is a pointer to an `xmlValidCtxt`
struct
 > (documented at
http://xmlsoft.org/html/libxml-valid.html#xmlValidCtxt,
 > though note that the last two fields are listed twice because
whatever
 > extracted the docs didn't understand a processor directive). My
wrapper
 > code needs to allocate the `xmlValidCtxt` (via
`xmlNewValidCtxt`), set
 > the first field to a `FILE*` for writing obtained via `fopen`,
set the
 > second and third fields to pointers to `fprintf`, and then call
 > `xmlValidateDtd` with the instance. I have a little function in C
that
 > does this work:
 > https://github.com/LiberalArtist/libxml2-ffi/blob/master/myvalidate.c
 >
 > Of course, I want to write this in Racket, not C, but my attempt
to do
 > this via the FFI
 >
(https://github.com/LiberalArtist/libxml2-ffi/blob/master/segfault.rkt)
 > causes a segfault. The problem is something in the way I'm
initializing
 > the `xmlValidCtxt` struct. If I run my Racket version with a valid
 > document, so that the error reporting isn't used, it works just
fine.
 > Likewise, if I don't initialize the first three fields of the
 > `xmlValidCtxt` struct, instead leaving them as null pointers, the
 > default error behavior (writing to standard error) works, though it
 > isn't useful for my purposes. The segfault only happens if I
initialize
 > the fields as described and a validation error actually tries to
use the
 > fields.
 >
 > I've also confirmed that my C version works. If I compile it to a
shared
 > library and load it with the FFI, it works just as desired with both
 > valid and invalid documents:
 >
https://github.com/LiberalArtist/libxml2-ffi/blob/master/use-my-so.rkt
 >
 > I don't see anything different between my attempt to initialize the
 > `xmlValidCtxt` struct from Racket and the way I'm doing it in C, but
 > obviously there is some difference. Any debugging suggestions
would be
 > appreciated.

It works for me if I change the definition of `_fprintf-ptr` to this:

    (define _fprintf-ptr _fpointer)

The docs say that compared to `_pointer`, `_fpointer` skips a level of
indirection on symbol lookups. (This also might explain a problem I had
in the past getting the right value for a symbol whose value is an
array
of pointers to structs. IIRC, I got the pointer to the first struct
instead.)

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] FFI Trouble (file streams, variadic functions)

2018-08-27 Thread Ryan Culpepper

On 08/27/2018 02:13 PM, Philip McGrath wrote:
I am hoping for some help debugging a problem I'm having writing FFI 
bindings for libxml2.


I am trying to use the function `xmlValidateDtd`, which (predictably) 
validates an XML document against a DTD. To support error reporting, the 
first argument to the function is a pointer to an `xmlValidCtxt` struct 
(documented at http://xmlsoft.org/html/libxml-valid.html#xmlValidCtxt, 
though note that the last two fields are listed twice because whatever 
extracted the docs didn't understand a processor directive). My wrapper 
code needs to allocate the `xmlValidCtxt` (via `xmlNewValidCtxt`), set 
the first field to a `FILE*` for writing obtained via `fopen`, set the 
second and third fields to pointers to `fprintf`, and then call 
`xmlValidateDtd` with the instance. I have a little function in C that 
does this work: 
https://github.com/LiberalArtist/libxml2-ffi/blob/master/myvalidate.c


Of course, I want to write this in Racket, not C, but my attempt to do 
this via the FFI 
(https://github.com/LiberalArtist/libxml2-ffi/blob/master/segfault.rkt) 
causes a segfault. The problem is something in the way I'm initializing 
the `xmlValidCtxt` struct. If I run my Racket version with a valid 
document, so that the error reporting isn't used, it works just fine. 
Likewise, if I don't initialize the first three fields of the 
`xmlValidCtxt` struct, instead leaving them as null pointers, the 
default error behavior (writing to standard error) works, though it 
isn't useful for my purposes. The segfault only happens if I initialize 
the fields as described and a validation error actually tries to use the 
fields.


I've also confirmed that my C version works. If I compile it to a shared 
library and load it with the FFI, it works just as desired with both 
valid and invalid documents: 
https://github.com/LiberalArtist/libxml2-ffi/blob/master/use-my-so.rkt


I don't see anything different between my attempt to initialize the 
`xmlValidCtxt` struct from Racket and the way I'm doing it in C, but 
obviously there is some difference. Any debugging suggestions would be 
appreciated.


It works for me if I change the definition of `_fprintf-ptr` to this:

  (define _fprintf-ptr _fpointer)

The docs say that compared to `_pointer`, `_fpointer` skips a level of 
indirection on symbol lookups. (This also might explain a problem I had 
in the past getting the right value for a symbol whose value is an array 
of pointers to structs. IIRC, I got the pointer to the first struct 
instead.)


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Confusion about attributes of struct-id

2018-08-16 Thread Ryan Culpepper

On 08/16/2018 06:04 PM, David Storrs wrote:
The struct-id syntax class from syntax/parse/class/struct-id is puzzling 
me.  Given this preamble:



(require (for-syntax syntax/parse/class/struct-id
  syntax/parse
  syntax/parse/experimental/template
  ))

(struct person (name age height) #:transparent)

This works fine:

(define-syntax show-descript
   (syntax-parser
     [(_ id:struct-id) (template id.descriptor-id)]))
(show-descript person)



This is a compile-time error:

(define-syntax show-num-fields
   (syntax-parser
     [(_ id:struct-id) (template id.num-fields)]))
(show-num-fields person)

test.rkt:74:32: id.num-fields: attribute contains non-syntax value
   value: 3
   in: id.num-fields
   context...:
    /Applications/Racket_v6.11/collects/syntax/wrap-modbeg.rkt:46:4
    standard-module-name-resolver

I've played around with various versions of 'attribute', 
'datum->syntax', and 'quasitemplate / untemplate' but been unable to 
sort it out.  Can someone explain it for me?


The `id.num-fields` attribute is bound to a number, so it is a 
"non-syntax-valued attribute" and it can't be used directly within 
`syntax`, `template`, etc.


Use `attribute` to get the number and use `quote` to turn the number 
into an expression:


  > (define-syntax show-num-fields
  (syntax-parser
[(_ id:struct-id) #`(quote #,(attribute id.num-fields))]))
  > (show-num-fields person)
  3

The docs for attributes are here: 
http://docs.racket-lang.org/syntax/stxparse-specifying.html#(tech._attribute). 
I'll add an example that involves creating syntax from a 
non-syntax-valued attribute.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] ssax:make-parser

2018-05-16 Thread Ryan Culpepper

On 05/15/2018 11:36 PM, John Clements wrote:

Interestingly, it looks like this change is a deliberate one, made by Ryan 
Culpepper back in 2011. Here’s the relevant commit:

commit 738bf41d106f4ecd9111bbefabfd78bec8dc2202
Author: Ryan Culpepper <ry...@racket-lang.org>
Date:   Tue Nov 22 02:46:32 2011 -0700

 bypass ssax/ssax module
 trim exports from main (breaks backwards compat!)

diff --git a/main.rkt b/main.rkt
index bf3530d..89f27d3 100644
--- a/main.rkt
+++ b/main.rkt
@@ -27,5 +27,11 @@
  (provide (all-from-out "modif.rkt"))
  (provide (all-from-out "serializer.rkt"))
  
-(require "ssax/ssax.rkt")

-(provide (all-from-out "ssax/ssax.rkt"))
+(require "ssax/multi-parser.rkt"
+ "ssax/sxpathlib.rkt"
+ "ssax/SXML-tree-trans.rkt"
+ "ssax/SSAX-code.rkt")
+(provide ssax:multi-parser
+ (all-from-out "ssax/sxpathlib.rkt")
+ pre-post-order
+ ssax:xml->sxml)

Ryan, do you know why you put ssax:multi-parser in, but not ssax:make-parser?


Sorry, I don't remember. My guess is that either leaving it out was just 
an oversight, or that I thought it was only an internal helper function 
for something else.


Ryan




Cheers!

John



On May 15, 2018, at 6:42 AM, N. Raghavendra <nyraghu27...@gmail.com> wrote:

I was trying out Oleg Kiselyov's example

http://okmij.org/ftp/Scheme/remove-markup.scm

which illustrates the use of `ssax:make-parser'.  I have a couple of
questions:

1. To call ssax-make-parser, I had to require both sxml and
sxml/ssax/ssax.  Is that the correct way of doing it?

2. It seems an important function, and I was wondering why the sxml
module does not provide it, the way it does ssax:xml->sxml, so that one
doesn't need to further require sxml/ssax/ssax.  I see that sxml
provides ssax:multi-parser.  Is it similar to ssax:make-parser?

Thanks,
Raghu.

--
N. Raghavendra <ra...@hri.res.in>, http://www.retrotexts.net/
Harish-Chandra Research Institute, http://www.hri.res.in/

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.






--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Jupyter Racket Kernel - iracket

2018-05-03 Thread Ryan Culpepper

On 05/01/2018 09:33 PM, Graham Dean wrote:

PR submitted :)


PR merged. 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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] how to match unbound identifier as literal in `syntax-parse`?

2018-04-03 Thread Ryan Culpepper

Here's one way:

  (~and z:id
   (~fail #:unless (free-identifier=? #'z #'zeta)
  "expected the identifier `zeta`"))

Another way is to make a syntax class (either specifically for `zeta` or 
parameterized by the identifier) that does the same check.


Ryan


On 4/3/18 8:33 AM, Matthew Butterick wrote:

Consider the difference in results below. How would I persuade `syntax-parse` 
to match literal identifiers in the `free-identifier=?` sense that 
`syntax-case` does? (and thereby allow unbound identifiers to be compared also)

IIUC, `#:literals` is too strict, as it insists that every listed identifier 
have a binding; `#:datum-literals` is too lenient, as it does not compare 
bindings at all, but rather just the symbol.

;

#lang racket
(require math rackunit)

(module mod racket
  (require (for-syntax syntax/parse))
  (define-syntax (mac stx)
(syntax-parse stx
  #:literals () ;; <- can't put `zeta` here, produces an error
  #:datum-literals (zeta)
  [(_ zeta) #''match]
  [else #''nope]))
  (provide mac))
(require 'mod)

(check-equal? (mac zeta) 'match)


(module mod2 racket
  (require (for-syntax syntax/parse))
  (define-syntax (mac2 stx)
(syntax-case stx (zeta)
  [(_ zeta) #''match]
  [else #''nope]))
  (provide mac2))
(require 'mod2)

(check-equal? (mac2 zeta) 'nope)



--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Behavior of nested ellipses

2018-03-27 Thread Ryan Culpepper

On 03/27/2018 11:46 PM, Ryan Culpepper wrote:

On 03/27/2018 10:01 PM, Justin Pombrio wrote:
I'm surprised by the behavior of using a pattern variable under one 
set of ellipses in the pattern, and under two sets of ellipses in the 
template:

[...]


BTW, it looks like Macro-By-Example[1] describes the behavior that you 
expected. See the definitions in the second column of page 4.


Ryan

[1] "Macro-By-Example: Deriving Syntactic Transformations from their 
Specifications" by Eugene Kohlbecker and Mitchell Wand. 
ftp://www.cs.indiana.edu/pub/techreports/TR206.pdf


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Behavior of nested ellipses

2018-03-27 Thread Ryan Culpepper

On 03/27/2018 10:01 PM, Justin Pombrio wrote:
I'm surprised by the behavior of using a pattern variable under one set 
of ellipses in the pattern, and under two sets of ellipses in the template:


|
#lang racket

(require(for-syntax syntax/parse))

(define-syntax (test stx)
(syntax-parse stx
[(_ (x y ...)...)#''(top (list (x y) ...) ...)]))

(test (a 123)
(b 456)
(c 789))
|

I would expect this to produce:

|
'(top (list (a 1) (a 2) (a 3))
       (list (b 4) (b 5) (b 6))
       (list (c 7) (c 8) (c 9)))
|

But instead, it produces:

|
'(top (list (a 1) (b 2) (c 3))
       (list (a 4) (b 5) (c 6))
       (list (a 7) (b 8) (c 9)))
|

I'm surprised by this for two reasons:
- What I thought was the obvious implementation for 
matching/substituting with ellipses produces the top answer.

- It breaks some properties that I would expect ellipses to have, such as:

|
(define-syntax-rule (test (P ...))(list Q ...))
(test (T1 T2))
===
(define-syntax-rule (test P P*)(list Q Q*))
(test T1 T2)

;forall patterns P andtemplates Q andterms T1 andT2,whereP*andQ*are a 
renamed version of P andQ.

|


This has extra parens or is missing dots or something. As it is, the top 
test takes 1 argument and the bottom test takes two.



Is this the expected behavior? And is there a good reason for it?


A variable must participate in as many of the implicit maps in the 
template as its ellipsis depth from the *pattern* (call that depth D). 
If it occurs at a greater depth in the template, there are three obvious 
choices: participate in the outermost D maps, participate in the 
innermost D maps, or reject the template. At some point, someone decided 
to go with the innermost maps.


It's actually more complicated that that, because a variable can occur 
at multiple depths in the same template. Consider this example:


  > (with-syntax ([(x ...) #'(1 2 3)])
  #'((x x ...) ...))
  #

Instead of the property you were expecting, you get the following 
property: If T is a "fully-saturated" template (all variables occur wrt 
T at a depth >= their binding depths), then T always produces the same 
output, even when you put it in a larger template with more ellipses.


I think it might have been helpful back in the R5RS days, when 
"portable" macros were limited to syntax-rules, and this decision made a 
very limited system slightly more flexible. (To clarify, I'm not sure 
that R5RS specified this behavior, but I think it was a common extension 
to syntax-rules, whereas with-syntax was not.)


Nowadays, I would rather rewrite the macro to use with-syntax than rely 
on this "feature". I've implemented it twice, and I still have to stop 
and think through it.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Storing JSON into PostgreSQL 10

2018-03-16 Thread Ryan Culpepper

On 03/16/2018 11:28 PM, David Storrs wrote:
I'm noticing that when I store jsexpr?s into PostgreSQL 10 I end up with 
them as strings, not as actual JSONB data.  I've read the docs and tried 
every combination of typecasting / methods of writing that I can think 
of but nothing ends up working.  Can anyone point me to the right way?


Here's an example:

  (require db)
  (define c (dsn-connect 'pg))
  (query c "create temporary table foo (i integer, j jsonb)")
  (query-exec c "insert into foo (i,j) values ($1,$2)"
  1 "hello")
  (query-exec c "insert into foo (i,j) values ($1,$2)"
  2 (hash 'a 1 'b 2))
  (query-rows c "select * from foo")
  ;; => '(#(1 "hello") #(2 #hasheq((a . 1) (b . 2
  (query-rows c "select i, j->'b' from foo")
  ;; => '(#(1 #) #(2 2))

It's a little trickier if you have json that's already in string form 
and want it to be parsed on the PostgreSQL side:


  (query-value c "select cast($1 as jsonb)" "{\"a\":1}") ;; WRONG
  ;; => "{\"a\":1}"
  (query-value c "select cast($1::text as jsonb)" "{\"a\":1}") ;; RIGHT
  ;; => '#hasheq((a . 1))
  (query-value c "select $1::text::json" "{\"a\":1}") ;; RIGHT
  ;; => '#hasheq((a . 1))

The inner "cast" (::) actually gets interpreted as a type ascription for 
the parameter.


Finally, PostgreSQL treats (some?) type names as conversion functions, 
so you can also do this:


  (query-value c "select json($1::text)" "{\"a\":1}") ;; RIGHT
  ;; => '#hasheq((a . 1))

I hope that helps. Let me know if you have an example that isn't working 
as you expect.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Output Port Shenanigans

2018-03-14 Thread Ryan Culpepper

On 03/14/2018 06:16 PM, Lehi Toskin wrote:


On Wednesday, March 14, 2018 at 10:10:20 AM UTC-7, Matthew Butterick wrote:


probably it requires a combination of peek + read, or copying the
port.


That may be true, but I've been messing around getting *anything* to 
print from inside that function. I'm beginning to think it's never 
actually being run, which leads me to believe this may be a bug.


According to the docs, special-filter is only applied to values written 
using `write-special`. So it is never run on ordinary text.


`write-special` is part of the machinery that lets you, for example, 
`display` a pict in DrRacket and have an image show up in the 
interactions window. Most ports do not support specials; it doesn't make 
sense for ports that connect to the outside world (file ports, TCP 
ports, etc).


Your original solution using `make-output-port` was probably the right one.

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] syntax/parse is not hygienic

2018-03-05 Thread Ryan Culpepper

On 03/04/2018 09:40 PM, Alexis King wrote:

[... context ...]

Still, with all this context out of the way, my questions are
comparatively short:

   1. Is this lack of hygiene well-known? I did not find anything in
  Ryan’s dissertation that explicitly dealt with the question, but I
  did not look very hard, and even if it isn’t explicitly mentioned
  there, I imagine people have thought about it before.

   2. Are there some fundamental, theoretical obstacles to making a
  syntax class-like thing hygienic that I have not foreseen? Or would
  it really be as simple as performing the usual scope-flipping that
  macroexpansion already performs?

   3. If it is possible, is the unhygienic nature of syntax classes
  desirable frequently enough that it outweighs the benefits of
  respecting hygiene? That seems unlikely to me, but maybe I have not
  fully considered the problem. The semantics of syntax classes
  cannot be changed now, of course, for backwards compatibility
  reasons, but were that not a problem, would it make sense to make
  them hygienic?  If not, why not?


1. Yes. To me, at least :) That aspect of hygiene is triggered by a 
macro expansion step, and the macro expansion step also defines the 
boundary of its effect. In other words, the expansion of a macro 
introduces a scope, but syntax classes do not. Compare with the 
following examples:


   (define x 'old)

   (begin-for-syntax
 (define (get-def)
   #'(define x 'new))
 (define (get-use)
   #'x))
   (define-syntax (m1 stx)
 #`(begin #,(get-def) #,(get-use)))
   (m1) ;; => 'new

   (define-syntax (m2 stx)
 (let ([expr #'x])
   #`(let ([x 'new]) #,expr)))
   (m2) ;; => 'new

Contrast with systems like MetaML, which strictly enforce lexical 
scoping but don't actually give you macros.


2. I think the main technical challenge is finding all of the syntax 
objects to flip the scope on, given that syntax classes allow attributes 
to have arbitrary values (like opaque structures and closures), not just 
syntax objects. We have a similar problem with syntax properties, which 
are invisible to the hygiene algorithm.


It might be easier in a macro system like Andre van Tonder's system, as 
Matthew and Sam mentioned.


3. Maybe. Half-baked musings follow:

There are two good ideas in opposition here. One is hygiene. The other 
is the availability of pure abstractions.


As a new grad student, I spent some time playing with plain R5RS-style 
syntax-rules macros. My first presentation in grad school was on an 
EOPL-style interpreter I wrote using nothing but syntax-rules macros. It 
did integer arithmetic (using a unary encoding of integers as 
parentheses), it did closures, it did continuations... all at compile 
time. But I discovered that there were things I couldn't express the way 
I wanted because the only available abstraction mechanism (the macro 
definition) was tangled up with the hygiene effect. I don't remember the 
exact situations, but they had the following form: I needed 
macro-generated-macro X to produce exactly identifier Y, but it could 
only produce Y with a mark. Of course, most of these "macros" were 
really implementation fragments of something else; I was forced to break 
them out into separate pieces because of the limitations of the language 
I chose to work in.


Hygienic macros are impure abstractions. (Other examples of impure 
abstractions: Javascript functions, if you do reflection on the current 
activation record, and Prolog predicates, which delimit the effect of a 
cut.) They still win, because despite being impure at the syntax object 
level, they approximate this nice lexical scoping property one level up, 
the level of interpreting the syntax objects as expressions, 
definitions, etc. (I say "approximate" because of the examples I gave in 
part 1.) But I think the win depends on the placement of the hygiene 
boundaries. My interpreter experience makes me think that too many 
boundaries within the implementation of a macro can be bad.


So another framing of the question is where should the boundaries go?[*] 
The one that corresponds to a macro expansion step is nice because macro 
expansion occurs at expression (or more precisely, "form") positions, 
and that connects the hygiene boundary with the interpretation level 
where lexical scoping is defined. Are there other "meaningful" places to 
put hygiene boundaries? Do syntax classes necessarily correspond with 
meaningful boundaries? Or are meaningful boundaries not actually that 
important?


([*] Matthew and I had a similar problem regarding syntax certificates, 
which evolved into the current dye pack and tainting system. We couldn't 
find a good way to identify anchors in the source code that represented 
discrete macro implementations that could be automatically protected, so 
we left it to the programmer to call syntax-protect explicitly. (Or use 
syntax-rules.) The problem is 

Re: [racket-users] Generating automatic testsuites using a macro

2018-02-23 Thread Ryan Culpepper

On 2/23/18 3:36 PM, 'Paulo Matos' via Racket Users wrote:


On 23/02/18 15:13, 'Paulo Matos' via Racket Users wrote:

That's true, thanks for pointing it out. I only just noticed you could
generate test-suites and test-cases at runtime with make-testcase and
make-testsuite. Therefore I will actually be doing this without a macro.
However, it's always very useful to attempt this macro katas. :)



I will take that back. There is a make-test-suite but not a
make-test-case. Since test-case is syntax, I don't think there's a way
to programmatically create a list of test-cases, put them in a test
suite and later run them.

I tried
#lang racket

(require rackunit)

(define (make-suite n)
  (make-test-suite
   (format "Testsuite of ~a tests" n)
   (for/list ([i (in-range n)])
 (test-case (format "test ~a" i)
(check = i i)

(define s (make-suite 100))

(require rackunit/text-ui)
(run-tests s)

But this doesn't actually work. I think I really need to stick to the
macro stuff.


You can write `make-suite` like this:

  (define (make-suite n)
(test-suite
  (format "Testsuite of ~a tests" n)
  (for ([i (in-range n)])
(test-case (format "test ~a" i)
  (check = i i)

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] whither `splicing-parameterize`? or am I doing it wrong?

2018-01-24 Thread Ryan Culpepper
It might make sense to `(set! new-parameterization #f)` at the end so 
that the parameterization (and the values it holds) can be GC'd sooner 
when splicing-parameterize is used at top level or module level.


Ryan


On 1/24/18 6:00 AM, Alexis King wrote:

Here is an implementation of a version of splicing-parameterize that
uses local-expand, a la other forms in racket/splicing:

#lang racket

(require (for-syntax syntax/kerncase)
 (for-meta 2 racket/base)
 syntax/parse/define)

(begin-for-syntax
  (define-syntax (syntax/loc/props stx)
(syntax-case stx ()
  [(_ src-expr template)
   #`(let ([src src-expr])
   (datum->syntax (quote-syntax #,stx)
  (syntax-e (syntax template))
  src
  src))])))

(define-syntax-parser splicing-parameterize
  [(_ ([{~var param (expr/c #'parameter?)} value:expr] ...)
  body ...)
   (if (eq? (syntax-local-context) 'expression)
   #'(parameterize ([param.c value] ...)
   body ...)
   #'(begin
   (define new-parameterization
 (parameterize ([param.c value] ...)
   (current-parameterization)))
   (do-splicing-parameterize new-parameterization body)
   ...))])

(define-syntax-parser do-splicing-parameterize
  [(_ parameterization:expr body:expr)
   (syntax-parse (local-expand #'body (syntax-local-context)
   (kernel-form-identifier-list))
 #:literal-sets [kernel-literals]
 [(begin new-body ...)
  (syntax/loc/props this-syntax
(begin
  (do-splicing-parameterize parameterization new-body)
  ...))]
 [(define-values ids rhs)
  (syntax/loc/props this-syntax
(define-values ids
  (call-with-parameterization parameterization
  (thunk rhs]
 [({~or begin-for-syntax define-syntaxes module module*
#%require #%provide #%declare}
   . _)
  this-syntax]
 [expr
  (syntax/loc/props this-syntax
(call-with-parameterization parameterization
(thunk expr)))])])

I have not extensively tested it, but it seems to work okay for simple
programs. For example, given the following program:

(define my-param (make-parameter #f))

(splicing-parameterize ([my-param #t])
  (my-param)
  (define x (my-param))
  (define (f) (my-param)))

x
(f)

...the output is:

#t
#t
#f

...which I believe makes sense, since the dynamic adjustment of my-param
does not affect its use within the internal definition of a procedure.

Additionally, mutating a parameter does the right thing, so this
program:

(splicing-parameterize ([my-param #t])
  (my-param 42)
  (my-param))

(my-param)

...produces:

42
#f

This seems like something that would make sense in racket/splicing,
though it’s different from the other forms, since they are all lexical
binding forms (even splicing-syntax-parameterize), whereas parameterize
is not.

Alexis



--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Cryptography routines in Racket

2017-12-31 Thread Ryan Culpepper
I have a crypto library in progress that I haven't released yet. The 
repo is at https://github.com/rmculpepper/crypto, but the repo is 
missing a lot of local commits and I won't be able to fix it until 
mid-January.


If you want to try out the old version, you'll also need asn1-lib from 
rmculpepper/asn1 at commit a32ee72.


Ryan


On 12/31/17 10:33 AM, Christopher Lemmer Webber wrote:

Hello all,

So I've been making a lot of progress in porting my tooling over to
Racket, and it's been a blast.  Horray!  However, I do a lot of work on
stuff that involves using quite a bit of cryptography, and it doesn't
seem that there's a general purpose cryptography library available for
Racket.  Am I right in that?  Particularly, I need to use asymmetric
(public key) cryptography tooling for encryption/signatures and also
HMAC signatures.

I'm guessing I probably need to write one.  My thoughts are that I
should probably use the Racket FFI library and use openssl (maybe
gnutls?) but I'm not really sure.  I haven't touched the FFI yet...

However, it does look like Racket already ships with some of the right
bits.  racket/collects/openssl/ contains a swath of relevant openssl
tooling, just apparently not all the bits for general public key
cryptography and etc.

I'm happy to dive into hacking... the purpose of this email is mostly to
check if work has already been done here other than what I found above
and what I should coordinate with :)

Thanks!
 - Christopher Lemmer Webber



--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] confused about raco check-requires error

2017-11-21 Thread Ryan Culpepper

On 11/21/17 2:57 AM, Alex Harsanyi wrote:

I'm trying to use the "raco check-requires" command to determine which
requires I should remove from my source files, and the command fails when I
include one of my files (the application compiles and runs fine).

I managed to reproduce the case as follows:

;; Save this in "file1.rkt"
#lang racket/base
(require racket/class)

(define foo%
  (class object%
(init-field name)
(super-new)
))

(provide foo%)

;; Save this in "file2.rkt"
#lang racket/base
(require "file1.rkt")

When running check requires ("raco check-requires file2.rkt"), I would
expect
that "file1.rkt" to be reported as a useless include, instead I get the
following error:

$ raco check-requires file2.rkt
derivation-parser: error on token #280:  .
#)>
(file "file2.rkt"):
ERROR in (file "file2.rkt")

Interestingly, if I compile the files using "raco make file2.rkt", the
check-requires command works fine:

$ raco make file2.rkt
$ raco check-requires file2.rkt
(file "file2.rkt"):
DROP "file1.rkt" at 0

Could someone clarify what is "check-requires" complaining about in the
first
case?  Is this command only supposed to be run after the code was compiled?


That's an internal error in the implementation of check-requires, which 
reuses parts of the macro stepper. When compiled/file1_rkt.zo doesn't 
exist, expanding file2.rkt causes file1.rkt to be compiled (but not 
saved as a .zo file). Macro stepper "events" are supposed to be emitted 
in expand mode but not in compile mode, but during the compilation of 
file1.rkt, some events are getting emitted anyway (that's the real bug), 
and that confuses the event parser.


I've committed a workaround that should fix this particular problem, but 
the underlying problem will probably be more difficult.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] okay for the stepper to blanket disarm all syntax?

2017-10-16 Thread Ryan Culpepper

On 10/16/2017 12:38 PM, 'John Clements' via users-redirect wrote:

I’m in the process of trying to update the stepper to handle check-random, and 
I’m somewhat baffled by the amount of difficulty I’m running into in and around 
‘syntax-disarm’.

It occurs to me that it would probably be simpler just to walk over the 
expanded syntax tree and reformulate it by disarming all syntax and rebuilding 
the tree using

(datum->syntax (syntax-disarm old-stx inspector) rebuilt) new-stx old-stx 
old-stx)

.. at every syntax wrapper, with recursive calls for every compound form. This 
seems like an awfully big hammer, though; is it likely to bite me, or have 
unexpected consequences? I would be sad if the stepper created security 
vulnerabilities.

Many thanks for any advice.


IIRC, the usual pattern for processing fully-expanded code looks like this:

  (begin-for-syntax
;; transform : Syntax[Form] -> Syntax[Form]
(define (transform stx)
  (define disarmed-stx (syntax-disarm stx privileged-inspector))
  (define transformed-stx ( disarmed-stx ))
  (syntax-rearm transformed-stx stx)))

You might do

  (syntax-arm _ privileged-inspector #t)

before, after, or instead of `syntax-rearm` if you want to protect the 
integrity of the code your transformation generates too.


I think the pattern you're proposing would look like this:

  (begin-for-syntax
;; transform : Syntax[Form] -> Syntax[Form]
;; Neither disarms nor re-arms.
(define (transform stx) )

;; transform-top : Syntax[Top-Level-Form] -> Syntax[Top-Level-Form]
(define (transform-top stx)
  (define disarmed-stx
(recursively-disarm-form stx privileged-inspector))
  (define transformed-stx ( disarmed-stx ))
  (syntax-arm transformed-stx privileged-inspector #t)))

I think that's fine *if* `recursively-disarm-form` recurs along the 
structure of fully-expanded Racket syntax. If it recurred naively 
through syntax-objects, then you might disarm something inside of a 
`quote-syntax` expression that shouldn't be disarmed. (And I didn't 
realize that subtlety until I started typing up the wrong answer, so I 
might be missing something else.)


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Re: code reflection

2017-10-14 Thread Ryan Culpepper

On 10/14/2017 05:01 AM, George Neuner wrote:


On 10/14/2017 3:00 AM, Jack Firth wrote:


So is there a way ... from normal code ... to get at the locals of
functions higher in the call chain?  Or at least the immediate
caller?
Some reflective capability that I haven't yet discovered?


I'm not sure if there's a way to do that, but I'm wondering if what 
you want to do can be achieved more simply with plain functions and a 
very small macro wrapper. In particular, I suspect putting too much 
logic in the macro is what led you to eval which is the root of all 
evil. From what I can tell there shouldn't be any need at all for eval 
or any sort of dynamic runtime compilation to do things like what 
you're describing. Could you give a few more details about your use 
case? Ideally with some example code illustrating the problem?


Basically, this is a sort of Unix at-like function for flexible 
scheduling.  It takes an expression containing dates, times, certain 
keywords and arbitrary numeric expressions, and it produces seconds 
since the epoch.  Code is attached - hope it survives posting to the 
list.  It should be runnable as is.


What led me to eval originally was wanting to reference arbitrary 
functions/variables from the runtime environment.  I'd like to be able 
to say

things like:

    (let [(y 42)] (schedule (at now + y mins) ...))

and similar involving top-level defined functions [which already works 
with eval].


I know that eval is not needed if I generate inline code rather than 
having the macro invoke a normal function.  But that is complicated by 
having to deal with free form expressions: they can have internal 
references between things which are not necessarily adjacent.  It is 
doable, but at some expense and not very cleanly.


I started out going the "compile" route - just generating inline code.  
But as more functionality was added, that became unwieldy. So I switched 
to a runtime function. Right now the assoc list code is overly complex 
[so please ignore it] - it is there as a debugging tool until I get 
everything working exactly right.


Your example above shows that you want the `at` macro to accept a 
mixture of Racket expressions and syntax that you interpret. If you want 
to accept Racket expressions, you must leave them as syntax objects. 
Once you flatten them with `syntax->datum`, there is *no way* to 
*correctly* recover their meaning.


Here's my attempt to adapt the HtDP design recipe to a scaled-down 
version of this problem.


First, let's think about the syntax (grammar) that `at` should accept. 
Let's call it a Time. What are some reasonable Times?


  now
  now + 30 ;; means 30 seconds
  today
  tomorrow + 20 mins
  now + x mins + (/ ms 1000) secs
  "2017-10-14 1:17:25" + 30 mins

But there are also some terms that are nonsense as Times:

  12
  today + tomorrow
  now mins

Let's say (as a place to start) that a Time consists of an absolute 
reference point (like now or today) and some number of offsets. Here's a 
grammar:


  ;; Time = TimeBase {+ TimeExt}*
  ;; TimeBase = now | today | String[Date]
  ;; TimeExt = Expr[Real] MaybeUnit
  ;; MaybeUnit =  | secs | mins

Let's call the *meaning* of a Time a TimeVal, and let's represent it as 
a real number of seconds, using the same epoch as (current-seconds).


  ;; A TimeVal is a real number of seconds
  ;; using the same epoch as (current-seconds)

The meaning of TimeBase is also a TimeVal. The meanings of TimeExt and 
MaybeUnit are both Real (they are duration and durations scales; they 
have no epoch).


Now to translate that plan to Racket.

First, turn keywords like `now` into "illegal use" macro definitions:

  (begin-for-syntax
(define (at-keyword stx)
  (raise-syntax-error #f "illegal use of `at` keyword" stx)))
  (define-syntax now at-keyword)
  (define-syntax today at-keyword)
  (define-syntax secs at-keyword)
  (define-syntax mins at-keyword)

Then define syntax classes for the nonterminals in the grammar. I'll 
also define an `expr` attribute to compute the meaning of each term. For 
example, the syntax class for TimeBase is


  (begin-for-syntax
(define-syntax-class TimeBase
  #:attributes (expr) ;; expression of TimeVal
  #:literals (now today)
  (pattern now
   #:with expr #'(current-seconds))
  (pattern today
   #:with expr #'(today-fun))
  (pattern s:str
   #:with expr #'(parse-date-string s

To avoid complicating the syntax class and also to avoid making the 
expansion bigger than necessary, factor run-time behavior out into 
helper functions, like `today-fun`:


  ;; today-fun : -> TimeVal
  (define (today-fun)
(define today (current-date))
(find-seconds 0 0 0 (date-day today) (date-month today) (date-year 
today)))


Here's the syntax class for TimeExt. It uses `expr/c` to make sure the 
given Racket expression actually produces a number.


  (begin-for-syntax

Re: [racket-users] syntax-parse attributes in macro-generated macros

2017-09-18 Thread Ryan Culpepper

On 09/17/2017 01:00 AM, Philip McGrath wrote:

[...]

I have a macro like `example-macro`, but more complicated and with many, 
many more potential keyword arguments, so I wanted to write a macro that 
would let me define `example-macro` with a more declarative syntax, like 
this:


(define-example-macro/working generated-example-macro
   [#:a 'default-a symbol?]
   [#:b "default-b" string?])

My initial attempt looked something like this:

(define-syntax (define-example-macro/buggy stx)
   (define-syntax-class arg-clause
 (pattern [kw:keyword default:expr contract:expr]))
   (syntax-parse stx
 [(_ name clause:arg-clause ...+)
  ;#:with (arg ...) (generate-temporaries #'(clause.kw ...))
  ;#:with (arg.c ...) (generate-temporaries #'(clause.kw ...))
  #`(define-syntax name
  (syntax-parser
[(_ (~alt (~optional
   (~seq clause.kw (~var arg (expr/c #'clause.contract)))
   #:defaults ([arg.c #'clause.default]))
  ...)
(... ...))
 #`(list arg.c ...)]))]))

which raises a syntax error "syntax: no pattern variables before 
ellipsis in template".


The problem seems to be that `arg.c` is not recognized as a pattern 
variable derived from `arg`. I tried several variants on this, none of 
which allowed me to refer to `arg.c`. For example, if I uncomment the 
two `#:with` lines, I get the error "~optional: attribute bound in 
defaults but not in pattern".


If you uncomment the two "#:with" lines and look at the first expansion 
step of your example, you get the following:


  (define-example-macro generated-example-macro
[#:a 'default-a symbol?]
[#:b "default-b" string?])
=>
  (define-syntax generated-example-macro
 (syntax-parser
  ((_
(~alt
 (~optional
  (~seq #:a (~var a5 (expr/c #'symbol?)))
  #:defaults
  ((a7 #''default-a)))
 (~optional
  (~seq #:b (~var b6 (expr/c #'string?)))
  #:defaults
  ((b8 #'"default-b"
...)
   #`(list a7 b8

The problem is that a7 and b8 need to be a5.c and b6.c, respectively. So 
rather than two independent calls to generate-temporaries, you should 
build the arg.cs from the args:


  #:with (arg ...) (generate-temporaries #'(clause.kw ...))
  #:with (arg.c ...) (map (lambda (arg)
(format-id arg "~a.c" arg))
  (syntax->list #'(arg ...)))

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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Efficient & "nice" communication mechanism between Racket and other languages

2017-09-08 Thread Ryan Culpepper

On 09/07/2017 12:11 PM, Brian Adkins wrote:

I'm considering having a group of programmers create micro-services in various 
programming languages to be glued together into a single application. I would 
like a communication mechanism with the following characteristics:

* Already supported by Racket, or relatively trivial to add
* More efficient than HTTP
* Nicer to program than raw sockets

Someone suggested ZeroMQ, so I searched for support in Racket and found 4 
packages, but 3 of them have failing tests, and I *think* two of them comprise 
a single logical package, so one of the two has failing tests.


The package server lists them as having failing tests because the 
machine it runs on does not have libzmq installed, and none of the 
packages has done the somewhat complicated remedy. The zeromq-r tests 
succeed on my machine.



Has anyone had success with any of the ZeroMQ packages?


As the author of zeromq-r, I recommend zeromq-r :) It's got basic tests 
and it's used by the iracket package. On the other hand, it's only a 
month or two old, so there are probably some untested corners.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Generate function defintions at compile time

2017-08-22 Thread Ryan Culpepper

On 08/22/2017 05:29 PM, hiph...@openmailbox.org wrote:

Hello,

I am writing a Racket library which will make it possible to control the
Neovim text editor using Racket. People will be able to use Racket to
control Neovim, as well as write plugins for Neovim in Racket.
https://gitlab.com/HiPhish/neovim.rkt

So far it looks good, but I am stuck on macros. There is a hash table
which serves as a specification for which functions to generate, it is
stored in the file 'nvim/api/specification.rkt'. This table has the key
"functions" which contains a vector of more hash tables.

I need this information to generate function definitions for users to be
able to call Neovim procedures from Racket. So instead of writing
something like

   (api-call "nvim_command" '#("echo 'hello world'"))

users should be able to write

   (require nvim/api)
   (command "echo 'hello world'")

For this I need to loop over the functions vector like this:

   (define functions (hash-ref api-info "functions"))
   (for ([function (in-vector functions)])
 (define name   (hash-ref function   "name"))
 (defien params (hash-ref function "parameters"))
 `(define (,(string->symbol name) ,@params)
(api-call ,name (vector ,@params

Reality is a bit more complicated because the parameters are not a list
but a vector of vectors, but that's besides the point. The question is:
how do I do this? A regular for-loop at runtime will not work, and
wrapping this in begin-for-syntax doesn't produce actual module-level
definitions.

I tried doing it with a macro:

   (define-syntax (api->func-def stx)
 (syntax-case stx ()
   [(_ api-name api-params)
(with-syntax ([name
(datum->syntax stx
  (string->symbol
(function-name (eval (syntax->datum #'api-name)]
  [arg-list
(datum->syntax stx
  (vector->list
(vector-map string->symbol (eval (syntax->datum 
#'api-params)])
  #`(define (name #,@#'arg-list)
  (api-call api-name (vector #,@#'arg-list]))

This *seems* to generate the proper definition, although I'm not really
sure. But how can I write the loop now so that it covers all function
definitions? I don't need to re-use the macro, I only need it once, so
if there was an easier solution like my for-loop above that does it in
place it would be even better.


Using `eval` is almost always the wrong (or at least suboptimal) 
solution unless the problem is "I need to evaluate some code supplied in 
text form by someone else".


You need the names of the functions you want to define at compile time, 
because Racket requires bindings to be settled at compile time. IIUC, 
you are doing argument/result checking and conversion at run time. So, 
assuming you want to keep the information in a single hash table in a 
single module, you need to require that module once for-syntax and once 
normally.


Here's an example solution to a simplified version of the problem. I've 
simplified the specification to just the function name and its argument 
types:


  ;; file "api-spec.rkt"
  #lang racket/base
  (provide functions)

  ;; A Type is (U 'String 'Number)

  ;; functions : (Listof (List Symbol (Listof Type)))
  ;; List of function names and types of arguments.
  (define functions
'((f (String String))
  (g (Number String

And here's the module that uses that information to define adapter 
functions:


  ;; file "api.rkt"
  #lang racket/base
  (require (for-syntax racket/base))

  ;; Need api-spec at run time to create adapter
  (require "api-spec.rkt")

  ;; type->predicate : Type -> (Any -> Boolean)
  (define (type->predicate type)
(case type
  [(String) string?]
  [(Number) number?]))

  ;; make-adapter : Symbol -> Function
  (define (make-adapter function-name)
(define arg-types
  (cond [(assq function-name functions) => cadr]
[else (error 'make-adapter "unknown: ~s" function-name)]))
(define arg-preds (map type->predicate arg-types))
(define (wrapper . args)
  (for ([arg (in-list args)]
[pred (in-list arg-preds)]
[type (in-list arg-types)])
(unless (pred arg)
  (error function-name "expected ~a, got: ~e" type arg)))
  (printf "called ~s on ~v\n" function-name args))
(procedure-reduce-arity wrapper (length arg-types)))

  ;; Need api-spec at compile time for names to bind
  (require (for-syntax "api-spec.rkt"))

  (define-syntax (define-the-functions stx)
(syntax-case stx ()
  [(define-all-functions)
   (with-syntax ([(function-id ...)
  (for/list ([entry (in-list functions)])
(syntax-local-introduce
 (datum->syntax #'here (car entry])
 #'(begin (define function-id (make-adapter 'function-id)) ...
  (provide function-id 

Re: [racket-users] "Test did not clean up resources" message from GUI test runner

2017-08-21 Thread Ryan Culpepper

On 08/20/2017 09:28 PM, Alex Harsanyi wrote:

I just noticed that the GUI test runner displays "test did not clean up 
resources" messages on my tests, but it is not clear to me what resources are not 
being cleaned up.

I tried to reproduce the problem in the following test case:

 #lang racket
 (require rackunit rackunit/gui db)

 (define ts
   (test-suite
"test suite"
(test-case
 "test-case"
 (check-not-exn
  (lambda ()
(define db (sqlite3-connect #:database 'memory #:mode 'create))
(disconnect db))

 (test/gui ts)

Here, a sqlite database is created in memory than the connection is closed.  
The test runner complains that the data base connection is not cleaned up.  It 
also complains about a thread not being cleaned up, but the test does not 
create any threads (at least not explicitly).   See attached picture for 
details.

Can someone explain to me how to clean up properly in such a test?


The first entry is my fault: disconnecting a sqlite3 connection does not 
unregister the connection from its custodian. I'll push a fix soon.


The second entry looks like the finalizer thread for prepared 
statements. It looks like the db module loads that module lazily, only 
when the first connection function (like `sqlite3-connect`) is called, 
so its initial custodian is the test case custodian. I can fix that by 
having db/base depend strictly on the prepared statement module.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Anyone using MongoDB 3.2.15 with DrRacket 6.9?

2017-08-07 Thread Ryan Culpepper

On 08/06/2017 05:49 PM, Cecil McGregor wrote:

[...]
What are other people using for a NoSQL racket experience?


Are you looking for no schema or no ACID? If the latter, the git version 
of the db library now has experimental support for Apache Cassandra.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] chaining operations on bignum not scalable

2017-07-29 Thread Ryan Culpepper

On 07/29/2017 02:48 PM, rom cgb wrote:

Hi,

Probably due to all operations not being in-place, chaining operations on 
bignums is very costful.

for example, using bitwise-bit-field[1] on bignums is atrocious.

I also tried

   (define (reverse-bits n)
 (for/fold ([reversed 0])
   ([i (in-range (integer-length n))])
   (bitwise-ior (bitwise-arithmetic-shift-left reversed 1)
(or (and (bitwise-bit-set? n i) 1) 0


Here's a version that runs in about a sixth of the time for me.

First, parameterize your function by a "chunk length":

  ;; reverse-chunk : Nat Nat -> Nat
  ;; Return a natural from the lowest len bits of n, reversed.
  (define (reverse-chunk n len)
(for/fold ([reversed 0])
  ([i (in-range len)])
  (bitwise-ior (arithmetic-shift reversed 1)
   (if (bitwise-bit-set? n i) 1 0

Then create an outer loop that processes one chunk at a time:

  (define CHUNK 32)  ;; should be less than fixnum size

  ;; reverse-bits : Nat -> Nat
  (define (reverse-bits n)
(let loop ([n n] [nlen (integer-length n)])
  (cond [(< nlen CHUNK)
 (reverse-chunk n nlen)]
[else
 (bitwise-ior
  (loop (arithmetic-shift n (- CHUNK)) (- nlen CHUNK))
  (arithmetic-shift
   (reverse-chunk (bitwise-bit-field n 0 CHUNK) CHUNK)
   (- nlen CHUNK)))])))


[...] Having in-place operations would help

  (define (reverse-bits n)
(for/fold ([reversed 0])
  ([i (in-range (integer-length n))])
  (bitwise-arithmetic-shift-left! reversed 1)
  (bitwise-ior! reversed (or (and (bitwise-bit-set? n i) 1) 0

What do you think?


I believe the chunking version would still be faster than the in-place 
version. Both are quadratic: the chunking version constructs 
2*nlen/CHUNK intermediate bignums, and the in-place version would do 
nlen 1-bit left shifts. But the 2/CHUNK advantage in the constants is 
significant.


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.
For more options, visit https://groups.google.com/d/optout.
#lang racket/base
(provide (all-defined-out))

;; reverse-bits0 : Nat -> Nat
;; The original version (ported R6RS -> Racket)
(define (reverse-bits0 n)
  (for/fold ([reversed 0])
([i (in-range (integer-length n))])
(bitwise-ior (arithmetic-shift reversed 1)
 (if (bitwise-bit-set? n i) 1 0

;; 

;; reverse-chunk : Nat Nat -> Nat
;; Return an integer from the lowest len bits of n, reversed.
(define (reverse-chunk n len)
  (for/fold ([reversed 0])
([i (in-range len)])
(bitwise-ior (arithmetic-shift reversed 1)
 (if (bitwise-bit-set? n i) 1 0

;; 

(define CHUNK 32)

;; reverse-bits : Nat -> Nat
(define (reverse-bits n)
  (let loop ([n n] [nlen (integer-length n)])
(cond [(< nlen CHUNK)
   (reverse-chunk n nlen)]
  [else
   (bitwise-ior
(loop (arithmetic-shift n (- CHUNK)) (- nlen CHUNK))
(arithmetic-shift (reverse-chunk (bitwise-bit-field n 0 CHUNK) 
CHUNK)
  (- nlen CHUNK)))])))

;; Useful for REPL debugging
;; (define (b n) (number->string n 2))
;; (define (r s) (b (reverse-bits (string->number s 2

(define (test n)
  (unless (equal? (reverse-bits n)
  (string->number (list->string (reverse (string->list 
(number->string n 2 2))
(error 'test "failed on ~s" n)))

;; 

;; random-bignum : -> Nat
;; Make a bignum with size between 1 and 100 bytes.
(define (random-bignum)
  (define nbytes (+ 1 (random 100)))
  (for/fold ([n 0]) ([i (in-range nbytes)]) (+ (arithmetic-shift n 8) (random 
256

;; For deterministic testing:
(random-seed 17)

(define SIZE #e5e4)
(define ns (for/list ([_ (in-range SIZE)]) (random-bignum)))

;; Make sure reverse-bits is correct:
(for-each test ns)

;; Benchmarks:
(printf "Original version:\n")
(collect-garbage)
(for ([i 4]) (time (for-each reverse-bits0 ns)))

(printf "Chunking version:\n")
(collect-garbage)
(for ([i 4]) (time (for-each reverse-bits ns)))


Re: [racket-users] How do db handles interact with threads and parameters

2017-07-24 Thread Ryan Culpepper

On 7/24/17 9:11 AM, George Neuner wrote:

Hi David,

On 7/24/2017 8:18 AM, David Storrs wrote:

What happens in the following code?

(define dbh (postgresql-connect ...))

;; Use the DBH in a new thread
(thread (thunk
  (while ...some long-running condition...
(sleep 1) ; don't flood the DB
(query-exec dbh "insert into users ..."

;; And in the main thread
(query-exec dbh ...)

I now have a database object that's being shared between two threads,
yes?  Or is the object copied when the new thread is created and, if
so, what will that do to the underlying connection to the DB?


The single DBMS connection is being shared by the 2 threads.  That's a
recipe for disaster if both try to use it simultaneously.


To clarify "disaster": Connections are thread-safe, so the queries 
performed by the 2 threads will be interleaved in some order, which is 
fine if both threads are just doing reads. But the threads are not 
isolated ("session-safe" or "conversation-safe"?). For example, if one 
thread changes the time zone, it affects queries made by the other 
thread. If one thread starts and later rolls back a transaction, it 
might undo modifications made by the other thread. And so on.


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Struct declaration conflict if a file is required implicitly

2017-07-23 Thread Ryan Culpepper

On 07/23/2017 07:26 AM, Alejandro Sanchez wrote:

Hello everyone,

I am working on this project: https://gitlab.com/HiPhish/MsgPack.rkt/

I am writing test cases and I ran into a problem with my ‘ext’ structure. It is 
declared in the file ‘msgpack/main.rkt’, which is required in the file 
‘msgpack/pack.rkt’ (also in ‘msgpack/unpack.rkt’). For my test case the test 
file looks like this:


It looks like msgpack/pack.rkt requires "../main.rkt" rather than 
"main.rkt". There isn't a "../main.rkt" checked in, so maybe you have a 
stale file getting loaded? (It could be at "../main.rkt" or possibly 
"../compiled/main_rkt.zo".)


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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Catching syntax errors

2017-07-01 Thread Ryan Culpepper
Use `convert-syntax-error` from the `syntax/macro-testing` module: 
http://docs.racket-lang.org/syntax/macro-testing.html#(form._((lib._syntax%2Fmacro-testing..rkt)._convert-syntax-error))


Ryan


On 06/30/2017 04:47 PM, Sam Waxman wrote:

Hello,

I'm trying to test whether or not certain programs result in syntax errors. For 
example the program

#lang racket
a

will result in an unbound identifier error, even before runtime (you'll see the 
little error message at the bottom because it errored in phase 1).

I know how to catch runtime errors, but I haven't been able to catch these 
expansion time errors as of yet. I've tried doing roughly the same thing as 
catching runtime errors, but with begin-for-syntax, but it hasn't been working 
out for me.

Ideally, I want a macro like

(return-syntax-error stuff-to-expand ...)

that will run stuff-to-expand, and if runs into a syntax error, for it to be caught and 
returned (as the error struct #).

Any tips?

Many thanks in advance.



--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] break-thread + thread-wait can't be handled

2017-05-03 Thread Ryan Culpepper

On 5/3/17 10:41 PM, Eric Griffis wrote:

Hello,

I'm having trouble catching "terminate break" exceptions when combining 
break-thread with thread-wait.

MWE 1:

  (with-handlers ([exn:break:terminate? writeln])
(let ([t (thread (lambda () (thread-wait (current-thread])
  (break-thread t 'terminate)
  (thread-wait t)))


Threads do not inherit exception handlers. You need to move the 
`with-handlers` to the new thread:


  (let ([t (thread (lambda ()
 (with-handlers ([exn:break:terminate? writeln])
   (thread-wait (current-thread)])
(break-thread t 'terminate)
(thread-wait t))

Except that isn't quite right either, because , the main thread might 
(very likely) send the break to `t` before `t` is ready to catch it. So 
we need some additional synchronization:


  (define t-ready (make-semaphore 0))
  (let ([t (thread (lambda ()
 (with-handlers ([exn:break:terminate? writeln])
   (semaphore-post t-ready)
   (thread-wait (current-thread)])
(semaphore-wait t-ready)
(break-thread t 'terminate)
(thread-wait t))

That version should reliably print out the break exception.

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.
For more options, visit https://groups.google.com/d/optout.


  1   2   >