Re: [racket-users] Struct properties and recursion

2019-02-22 Thread Sam Tobin-Hochstadt
I think the issue is that there's genuinely a cycle here, and so you have
to take advantage of mutation or the implicit mutation of module
initialization. point-x has a reference to the point structure type, which
in turn has a reference to the table of properties, which contains the
writer function, which refers to point-x.

Sam

On Fri, Feb 22, 2019, 5:35 PM Jack Firth  wrote:

> Does it seem weird to anybody else that there's no way to set struct
> properties without mutual recursion?
>
> Say I'm defining a 2d point struct and want to set the prop:custom-write
> property to control how points print. I might start with this:
>
> (struct point (x y)
>   #:property prop:custom-write
>   (lambda (this out _)
> (write-string "(point " out)
> (write (point-x this) out)
> (write-string " " out)
> (write (point-y this) out)
> (write-string ")" out)))
>
> This works fine. But if I try to extract that lambda into a named function:
>
> (struct point (x y) #:property prop:custom-write write-point)
> (define (write-point pt out _) ...)
>
> That doesn't work, and the error complains that I'm using write-point
> before it's defined. This error makes sense to me. The property value is
> associated with the type, not with instances, and the struct form is
> essentially a macro that expands to a call to `make-struct-type` with a
> list of property values. So I understand that I need to define those
> properties before using them in the struct definition:
>
> (define (write-point pt out _) ...)
> (struct point (x y) #:property prop:custom-write write-point)
>
> All well and good. But then I decide that defining write-foo for every one
> of my struct types is tedious, so I define a make-list-type-writer helper
> function and try to use it:
>
> (define ((make-list-type-writer name . accessors) this out _)
>   (write-string "(" out)
>   (write-string name out)
>   (for ([accessor (in-list accessors)])
> (write-string " " out)
> (write (accessor this) out))
>   (write-string ")" out))
>
> (define write-point (make-list-type-writer "point" point-x point-y))
> (struct point (x y) #:property prop:custom-write write-point)
>
> And now we've got a problem. This doesn't work because I can't pass the
> point-x and point-y accessors as arguments to make-list-type-writer. They
> don't exist yet! So in order to make my property value, I need the struct
> defined. But in order to define the struct, I need the property value. A
> workable fix is to delay evaluation somewhere with lambdas:
>
> (define write-point
>   (make-list-type-writer
> "point"
> (lambda (this) (point-x this))
> (lambda (this) (point-y this
>
> This feels tedious and unnecessary. Looking at the underlying API of
> make-struct-type, I can't see any way to avoid this mutual recursion. Which
> is *weird* to me, because when else are you forced to use mutual
> recursion? Mutually recursive functions can be transformed into functions
> that accept the other function as an argument. Mutually recursive modules
> can (usually) be broken down into smaller modules that don't have any
> cyclic dependencies. But I can't seem to do the same for structs, which
> makes it difficult to write nice helper functions for building struct types
> in a first-class way.
>
> --
> You received this message because you are subscribed to the Google 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.


[racket-users] Struct properties and recursion

2019-02-22 Thread Jack Firth
Does it seem weird to anybody else that there's no way to set struct
properties without mutual recursion?

Say I'm defining a 2d point struct and want to set the prop:custom-write
property to control how points print. I might start with this:

(struct point (x y)
  #:property prop:custom-write
  (lambda (this out _)
(write-string "(point " out)
(write (point-x this) out)
(write-string " " out)
(write (point-y this) out)
(write-string ")" out)))

This works fine. But if I try to extract that lambda into a named function:

(struct point (x y) #:property prop:custom-write write-point)
(define (write-point pt out _) ...)

That doesn't work, and the error complains that I'm using write-point
before it's defined. This error makes sense to me. The property value is
associated with the type, not with instances, and the struct form is
essentially a macro that expands to a call to `make-struct-type` with a
list of property values. So I understand that I need to define those
properties before using them in the struct definition:

(define (write-point pt out _) ...)
(struct point (x y) #:property prop:custom-write write-point)

All well and good. But then I decide that defining write-foo for every one
of my struct types is tedious, so I define a make-list-type-writer helper
function and try to use it:

(define ((make-list-type-writer name . accessors) this out _)
  (write-string "(" out)
  (write-string name out)
  (for ([accessor (in-list accessors)])
(write-string " " out)
(write (accessor this) out))
  (write-string ")" out))

(define write-point (make-list-type-writer "point" point-x point-y))
(struct point (x y) #:property prop:custom-write write-point)

And now we've got a problem. This doesn't work because I can't pass the
point-x and point-y accessors as arguments to make-list-type-writer. They
don't exist yet! So in order to make my property value, I need the struct
defined. But in order to define the struct, I need the property value. A
workable fix is to delay evaluation somewhere with lambdas:

(define write-point
  (make-list-type-writer
"point"
(lambda (this) (point-x this))
(lambda (this) (point-y this

This feels tedious and unnecessary. Looking at the underlying API of
make-struct-type, I can't see any way to avoid this mutual recursion. Which
is *weird* to me, because when else are you forced to use mutual recursion?
Mutually recursive functions can be transformed into functions that accept
the other function as an argument. Mutually recursive modules can (usually)
be broken down into smaller modules that don't have any cyclic
dependencies. But I can't seem to do the same for structs, which makes it
difficult to write nice helper functions for building struct types in a
first-class way.

-- 
You received this message because you are subscribed to the Google 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] performance, json

2019-02-22 Thread WarGrey Gyoudmon Ju
I have tried my best to find the "best practice" to do Racket IO.

Here are some tips I found in writing CSV reader:
https://github.com/wargrey/schema/blob/master/digitama/exchange/csv/reader/port.rkt
With a MacBook Pro 15, 2013, it takes 3.5s to read a 70MB file.

I agreed that `read-char` is the first choice, but `peek-char` may be slow
somehow.
Instead, just read the `peek`ing chars and pass it or them as the leading
ones to the parsing routine.
This strategy may require a re-design of your parsing workflow
since every subroutine should accept another input argument and return one
more value.


On Sat, Feb 23, 2019 at 5:34 AM Jon Zeppieri  wrote:

> On a related (but not too related) note: is there an efficient way to skip
> multiple bytes in an input stream? It looks like there are two choices:
>   - You can read the bytes you want to skip, but that implies either
> allocating a useless byte array or keeping one around for this very purpose.
>   - You can use (I think?) port-commit-peeked, bit given the API, it seems
> like that was designed with a particular (and more complicated) use in mind.
>
>
> On Fri, Feb 22, 2019 at 3:35 PM Matthew Flatt  wrote:
>
>> I think the bigger bottleneck is the main parsing loop, which uses
>> `regexp-try-match` even more. Although `regexp-try-match` is
>> convenient, it's much slower than using `peek-char` directly to check
>> for one character. I'll experiment with improvements there.
>>
>> At 22 Feb 2019 13:36:20 -0500, "'John Clements' via Racket Users" wrote:
>> > I’m not that surprised :).
>> >
>> > My guess is that our json reader could be sped up quite a bit. This
>> looks like
>> > the heart of the read-json implementation:
>> >
>> > (define (read-json* who i jsnull)
>> >   ;; Follows the specification (eg, at json.org) -- no extensions.
>> >   ;;
>> >   (define (err fmt . args)
>> > (define-values [l c p] (port-next-location i))
>> > (raise-read-error (format "~a: ~a" who (apply format fmt args))
>> >   (object-name i) l c p #f))
>> >   (define (skip-whitespace) (regexp-match? #px#"^\\s*" i))
>> >   ;;
>> >   ;; Reading a string *could* have been nearly trivial using the racket
>> >   ;; reader, except that it won't handle a "\/"...
>> >   (define (read-string)
>> > (define result (open-output-bytes))
>> > (let loop ()
>> >   (define esc
>> > (let loop ()
>> >   (define c (read-byte i))
>> >   (cond
>> > [(eof-object? c) (err "unterminated string")]
>> > [(= c 34) #f]   ;; 34 = "
>> > [(= c 92) (read-bytes 1 i)] ;; 92 = \
>> > [else (write-byte c result) (loop)])))
>> >   (cond
>> > [(not esc) (bytes->string/utf-8 (get-output-bytes result))]
>> > [(case esc
>> >[(#"b") #"\b"]
>> >[(#"n") #"\n"]
>> >[(#"r") #"\r"]
>> >[(#"f") #"\f"]
>> >[(#"t") #"\t"]
>> >[(#"\\") #"\\"]
>> >[(#"\"") #"\""]
>> >[(#"/") #"/"]
>> >[else #f])
>> >  => (λ (m) (write-bytes m result) (loop))]
>> > [(equal? esc #"u")
>> >  (let* ([e (or (regexp-try-match #px#"^[a-fA-F0-9]{4}" i)
>> >(err "bad string \\u escape"))]
>> > [e (string->number (bytes->string/utf-8 (car e)) 16)])
>> >(define e*
>> >  (if (<= #xD800 e #xDFFF)
>> >  ;; it's the first part of a UTF-16 surrogate pair
>> >  (let* ([e2 (or (regexp-try-match
>> #px#"^u([a-fA-F0-9]{4})"
>> > i)
>> > (err "bad string \\u escape, ~a"
>> >  "missing second half of a UTF16
>> pair"))]
>> > [e2 (string->number (bytes->string/utf-8 (cadr
>> e2))
>> > 16)])
>> >(if (<= #xDC00 e2 #xDFFF)
>> >(+ (arithmetic-shift (- e #xD800) 10) (- e2
>> #xDC00)
>> > #x1)
>> >(err "bad string \\u escape, ~a"
>> > "bad second half of a UTF16 pair")))
>> >  e)) ; single \u escape
>> >(write-string (string (integer->char e*)) result)
>> >(loop))]
>> > [else (err "bad string escape: \"~a\"" esc)])))
>> >   ;;
>> >   (define (read-list what end-rx read-one)
>> > (skip-whitespace)
>> > (if (regexp-try-match end-rx i)
>> > '()
>> > (let loop ([l (list (read-one))])
>> >   (skip-whitespace)
>> >   (cond [(regexp-try-match end-rx i) (reverse l)]
>> > [(regexp-try-match #rx#"^," i) (loop (cons (read-one)
>> l))]
>> > [else (err "error while parsing a json ~a" what)]
>> >   ;;
>> >   (define (read-hash)
>> > (define (read-pair)
>> >   (define k (read-json))
>> >   (unless (string? k) (err "non-string value used for json object
>> key"))
>> >   (skip-whitespace)
>> >   

Re: [racket-users] Use cases for tables and records

2019-02-22 Thread Philip McGrath
On Fri, Feb 22, 2019 at 8:14 AM Matt Jadud  wrote:

> However, I'm happy to push to Github as well as Bitbucket (which
> apparently does not play well with the package distribution system?), so
> that it can be poked at by others.
>

On Fri, Feb 22, 2019 at 8:47 AM Sam Tobin-Hochstadt 
wrote:

> Bitbucket should work fine with the package system -- just provide the
> URL for the git repository as the source and everything should be good
> to go.


Just in case anyone got the idea that Bitbucket might not work well with
the package system from https://github.com/racket/racket/issues/2385, which
I opened, that issue does not appear to be related to BitBucket after all
and in any case only applies to private repositories.

I use Bitbucket with no problems to host public packages like
ricoeur-tei-utils .

-Philip

-- 
You received this message because you are subscribed to the Google 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] performance, json

2019-02-22 Thread Jon Zeppieri
On a related (but not too related) note: is there an efficient way to skip
multiple bytes in an input stream? It looks like there are two choices:
  - You can read the bytes you want to skip, but that implies either
allocating a useless byte array or keeping one around for this very purpose.
  - You can use (I think?) port-commit-peeked, bit given the API, it seems
like that was designed with a particular (and more complicated) use in mind.


On Fri, Feb 22, 2019 at 3:35 PM Matthew Flatt  wrote:

> I think the bigger bottleneck is the main parsing loop, which uses
> `regexp-try-match` even more. Although `regexp-try-match` is
> convenient, it's much slower than using `peek-char` directly to check
> for one character. I'll experiment with improvements there.
>
> At 22 Feb 2019 13:36:20 -0500, "'John Clements' via Racket Users" wrote:
> > I’m not that surprised :).
> >
> > My guess is that our json reader could be sped up quite a bit. This
> looks like
> > the heart of the read-json implementation:
> >
> > (define (read-json* who i jsnull)
> >   ;; Follows the specification (eg, at json.org) -- no extensions.
> >   ;;
> >   (define (err fmt . args)
> > (define-values [l c p] (port-next-location i))
> > (raise-read-error (format "~a: ~a" who (apply format fmt args))
> >   (object-name i) l c p #f))
> >   (define (skip-whitespace) (regexp-match? #px#"^\\s*" i))
> >   ;;
> >   ;; Reading a string *could* have been nearly trivial using the racket
> >   ;; reader, except that it won't handle a "\/"...
> >   (define (read-string)
> > (define result (open-output-bytes))
> > (let loop ()
> >   (define esc
> > (let loop ()
> >   (define c (read-byte i))
> >   (cond
> > [(eof-object? c) (err "unterminated string")]
> > [(= c 34) #f]   ;; 34 = "
> > [(= c 92) (read-bytes 1 i)] ;; 92 = \
> > [else (write-byte c result) (loop)])))
> >   (cond
> > [(not esc) (bytes->string/utf-8 (get-output-bytes result))]
> > [(case esc
> >[(#"b") #"\b"]
> >[(#"n") #"\n"]
> >[(#"r") #"\r"]
> >[(#"f") #"\f"]
> >[(#"t") #"\t"]
> >[(#"\\") #"\\"]
> >[(#"\"") #"\""]
> >[(#"/") #"/"]
> >[else #f])
> >  => (λ (m) (write-bytes m result) (loop))]
> > [(equal? esc #"u")
> >  (let* ([e (or (regexp-try-match #px#"^[a-fA-F0-9]{4}" i)
> >(err "bad string \\u escape"))]
> > [e (string->number (bytes->string/utf-8 (car e)) 16)])
> >(define e*
> >  (if (<= #xD800 e #xDFFF)
> >  ;; it's the first part of a UTF-16 surrogate pair
> >  (let* ([e2 (or (regexp-try-match
> #px#"^u([a-fA-F0-9]{4})"
> > i)
> > (err "bad string \\u escape, ~a"
> >  "missing second half of a UTF16
> pair"))]
> > [e2 (string->number (bytes->string/utf-8 (cadr
> e2))
> > 16)])
> >(if (<= #xDC00 e2 #xDFFF)
> >(+ (arithmetic-shift (- e #xD800) 10) (- e2
> #xDC00)
> > #x1)
> >(err "bad string \\u escape, ~a"
> > "bad second half of a UTF16 pair")))
> >  e)) ; single \u escape
> >(write-string (string (integer->char e*)) result)
> >(loop))]
> > [else (err "bad string escape: \"~a\"" esc)])))
> >   ;;
> >   (define (read-list what end-rx read-one)
> > (skip-whitespace)
> > (if (regexp-try-match end-rx i)
> > '()
> > (let loop ([l (list (read-one))])
> >   (skip-whitespace)
> >   (cond [(regexp-try-match end-rx i) (reverse l)]
> > [(regexp-try-match #rx#"^," i) (loop (cons (read-one)
> l))]
> > [else (err "error while parsing a json ~a" what)]
> >   ;;
> >   (define (read-hash)
> > (define (read-pair)
> >   (define k (read-json))
> >   (unless (string? k) (err "non-string value used for json object
> key"))
> >   (skip-whitespace)
> >   (unless (regexp-try-match #rx#"^:" i)
> > (err "error while parsing a json object pair"))
> >   (list (string->symbol k) (read-json)))
> > (apply hasheq (apply append (read-list 'object #rx#"^}" read-pair
> >   ;;
> >   (define (read-json [top? #f])
> > (skip-whitespace)
> > (cond
> >   [(and top? (eof-object? (peek-char i))) eof]
> >   [(regexp-try-match #px#"^true\\b"  i) #t]
> >   [(regexp-try-match #px#"^false\\b" i) #f]
> >   [(regexp-try-match #px#"^null\\b"  i) jsnull]
> >   [(regexp-try-match
> > #rx#"^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?" i)
> >=> (λ (bs) (string->number (bytes->string/utf-8 (car bs]
> >   [(regexp-try-match #rx#"^[\"[{]" i)
> >=> (λ 

Re: [racket-users] Re: How do I get (system-tzid) to return the correct value?

2019-02-22 Thread Jon Zeppieri
On Fri, Feb 22, 2019 at 11:36 AM Brian Adkins  wrote:

>
> It seems that not short circuiting would be a good idea regardless of
> other changes. It's not urgent for me, because the code in question won't
> run late in the evening where the problem occurs.
>
>
I have a proposed fix, if you care (or anyone else cares) to take a look
and comment: https://github.com/97jaz/tzinfo/pull/7

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


Re: [racket-users] performance, json

2019-02-22 Thread Matthew Flatt
I think the bigger bottleneck is the main parsing loop, which uses
`regexp-try-match` even more. Although `regexp-try-match` is
convenient, it's much slower than using `peek-char` directly to check
for one character. I'll experiment with improvements there.

At 22 Feb 2019 13:36:20 -0500, "'John Clements' via Racket Users" wrote:
> I’m not that surprised :).
> 
> My guess is that our json reader could be sped up quite a bit. This looks 
> like 
> the heart of the read-json implementation:
> 
> (define (read-json* who i jsnull)
>   ;; Follows the specification (eg, at json.org) -- no extensions.
>   ;;
>   (define (err fmt . args)
> (define-values [l c p] (port-next-location i))
> (raise-read-error (format "~a: ~a" who (apply format fmt args))
>   (object-name i) l c p #f))
>   (define (skip-whitespace) (regexp-match? #px#"^\\s*" i))
>   ;;
>   ;; Reading a string *could* have been nearly trivial using the racket
>   ;; reader, except that it won't handle a "\/"...
>   (define (read-string)
> (define result (open-output-bytes))
> (let loop ()
>   (define esc
> (let loop ()
>   (define c (read-byte i))
>   (cond
> [(eof-object? c) (err "unterminated string")]
> [(= c 34) #f]   ;; 34 = "
> [(= c 92) (read-bytes 1 i)] ;; 92 = \
> [else (write-byte c result) (loop)])))
>   (cond
> [(not esc) (bytes->string/utf-8 (get-output-bytes result))]
> [(case esc
>[(#"b") #"\b"]
>[(#"n") #"\n"]
>[(#"r") #"\r"]
>[(#"f") #"\f"]
>[(#"t") #"\t"]
>[(#"\\") #"\\"]
>[(#"\"") #"\""]
>[(#"/") #"/"]
>[else #f])
>  => (λ (m) (write-bytes m result) (loop))]
> [(equal? esc #"u")
>  (let* ([e (or (regexp-try-match #px#"^[a-fA-F0-9]{4}" i)
>(err "bad string \\u escape"))]
> [e (string->number (bytes->string/utf-8 (car e)) 16)])
>(define e*
>  (if (<= #xD800 e #xDFFF)
>  ;; it's the first part of a UTF-16 surrogate pair
>  (let* ([e2 (or (regexp-try-match 
> #px#"^u([a-fA-F0-9]{4})" 
> i)
> (err "bad string \\u escape, ~a"
>  "missing second half of a UTF16 pair"))]
> [e2 (string->number (bytes->string/utf-8 (cadr e2)) 
> 16)])
>(if (<= #xDC00 e2 #xDFFF)
>(+ (arithmetic-shift (- e #xD800) 10) (- e2 #xDC00) 
> #x1)
>(err "bad string \\u escape, ~a"
> "bad second half of a UTF16 pair")))
>  e)) ; single \u escape
>(write-string (string (integer->char e*)) result)
>(loop))]
> [else (err "bad string escape: \"~a\"" esc)])))
>   ;;
>   (define (read-list what end-rx read-one)
> (skip-whitespace)
> (if (regexp-try-match end-rx i)
> '()
> (let loop ([l (list (read-one))])
>   (skip-whitespace)
>   (cond [(regexp-try-match end-rx i) (reverse l)]
> [(regexp-try-match #rx#"^," i) (loop (cons (read-one) l))]
> [else (err "error while parsing a json ~a" what)]
>   ;;
>   (define (read-hash)
> (define (read-pair)
>   (define k (read-json))
>   (unless (string? k) (err "non-string value used for json object key"))
>   (skip-whitespace)
>   (unless (regexp-try-match #rx#"^:" i)
> (err "error while parsing a json object pair"))
>   (list (string->symbol k) (read-json)))
> (apply hasheq (apply append (read-list 'object #rx#"^}" read-pair
>   ;;
>   (define (read-json [top? #f])
> (skip-whitespace)
> (cond
>   [(and top? (eof-object? (peek-char i))) eof]
>   [(regexp-try-match #px#"^true\\b"  i) #t]
>   [(regexp-try-match #px#"^false\\b" i) #f]
>   [(regexp-try-match #px#"^null\\b"  i) jsnull]
>   [(regexp-try-match
> #rx#"^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?" i)
>=> (λ (bs) (string->number (bytes->string/utf-8 (car bs]
>   [(regexp-try-match #rx#"^[\"[{]" i)
>=> (λ (m)
> (let ([m (car m)])
>   (cond [(equal? m #"\"") (read-string)]
> [(equal? m #"[")  (read-list 'array #rx#"^\\]" read-json)]
> [(equal? m #"{")  (read-hash)])))]
>   [else (err (format "bad input~n ~e" (peek-bytes (sub1 
> (error-print-width)) 0 i)))]))
>   ;;
>   (read-json #t))
> 
> 
> … and my guess is that the JS performance would be similar, if the json 
> reader 
> in JS was written in JS. I think there are probably a lot of 
> provably-unneeded 
> checks, and you could probably get rid of the byte-at-a-time reading. 
> 
> It would be interesting to see how much faster (if at all) it is to run the 
> TR 
> version of this 

Re: [racket-users] big-step-stepper ==> tree-er?

2019-02-22 Thread Sorawee Porncharoenwase
I think Shriram and Preston have/had a plan similar to this. The top level
shows a function call tree, and users can focus on a node which will show
the usual stepper in that function.

On Fri, Feb 22, 2019, 11:18 AM 'John Clements' via Racket Users <
racket-users@googlegroups.com> wrote:

> Has anyone explored the idea of a “big-step stepper”? It wouldn’t be a
> “stepper” at all, of course, just a big tree, but you could imagine a
> learning tool that allows you to explore the evaluation of a term by
> unfolding parts of its big-step tree.  Generating the raw data for this
> tree would be a substantial simplification of the existing stepper. Has
> this been done already?
>
> John
>
> --
> You received this message because you are subscribed to the Google 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.


[racket-users] big-step-stepper ==> tree-er?

2019-02-22 Thread 'John Clements' via Racket Users
Has anyone explored the idea of a “big-step stepper”? It wouldn’t be a 
“stepper” at all, of course, just a big tree, but you could imagine a learning 
tool that allows you to explore the evaluation of a term by unfolding parts of 
its big-step tree.  Generating the raw data for this tree would be a 
substantial simplification of the existing stepper. Has this been done already?

John

-- 
You received this message because you are subscribed to the Google 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] performance, json

2019-02-22 Thread Greg Trzeciak

There is http://docs.racket-lang.org/tjson/index.html available (haven't 
checked how similar the code is though)

On Friday, February 22, 2019 at 7:36:23 PM UTC+1, johnbclements wrote:
>
>
>
> … and my guess is that the JS performance would be similar, if the json 
> reader in JS was written in JS. I think there are probably a lot of 
> provably-unneeded checks, and you could probably get rid of the 
> byte-at-a-time reading. 
>
> It would be interesting to see how much faster (if at all) it is to run 
> the TR version of this code. 
>
> John 
>
>
>
>

-- 
You received this message because you are subscribed to the Google 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] performance, json

2019-02-22 Thread 'John Clements' via Racket Users
I’m not that surprised :).

My guess is that our json reader could be sped up quite a bit. This looks like 
the heart of the read-json implementation:

(define (read-json* who i jsnull)
  ;; Follows the specification (eg, at json.org) -- no extensions.
  ;;
  (define (err fmt . args)
(define-values [l c p] (port-next-location i))
(raise-read-error (format "~a: ~a" who (apply format fmt args))
  (object-name i) l c p #f))
  (define (skip-whitespace) (regexp-match? #px#"^\\s*" i))
  ;;
  ;; Reading a string *could* have been nearly trivial using the racket
  ;; reader, except that it won't handle a "\/"...
  (define (read-string)
(define result (open-output-bytes))
(let loop ()
  (define esc
(let loop ()
  (define c (read-byte i))
  (cond
[(eof-object? c) (err "unterminated string")]
[(= c 34) #f]   ;; 34 = "
[(= c 92) (read-bytes 1 i)] ;; 92 = \
[else (write-byte c result) (loop)])))
  (cond
[(not esc) (bytes->string/utf-8 (get-output-bytes result))]
[(case esc
   [(#"b") #"\b"]
   [(#"n") #"\n"]
   [(#"r") #"\r"]
   [(#"f") #"\f"]
   [(#"t") #"\t"]
   [(#"\\") #"\\"]
   [(#"\"") #"\""]
   [(#"/") #"/"]
   [else #f])
 => (λ (m) (write-bytes m result) (loop))]
[(equal? esc #"u")
 (let* ([e (or (regexp-try-match #px#"^[a-fA-F0-9]{4}" i)
   (err "bad string \\u escape"))]
[e (string->number (bytes->string/utf-8 (car e)) 16)])
   (define e*
 (if (<= #xD800 e #xDFFF)
 ;; it's the first part of a UTF-16 surrogate pair
 (let* ([e2 (or (regexp-try-match #px#"^u([a-fA-F0-9]{4})" 
i)
(err "bad string \\u escape, ~a"
 "missing second half of a UTF16 pair"))]
[e2 (string->number (bytes->string/utf-8 (cadr e2)) 
16)])
   (if (<= #xDC00 e2 #xDFFF)
   (+ (arithmetic-shift (- e #xD800) 10) (- e2 #xDC00) 
#x1)
   (err "bad string \\u escape, ~a"
"bad second half of a UTF16 pair")))
 e)) ; single \u escape
   (write-string (string (integer->char e*)) result)
   (loop))]
[else (err "bad string escape: \"~a\"" esc)])))
  ;;
  (define (read-list what end-rx read-one)
(skip-whitespace)
(if (regexp-try-match end-rx i)
'()
(let loop ([l (list (read-one))])
  (skip-whitespace)
  (cond [(regexp-try-match end-rx i) (reverse l)]
[(regexp-try-match #rx#"^," i) (loop (cons (read-one) l))]
[else (err "error while parsing a json ~a" what)]
  ;;
  (define (read-hash)
(define (read-pair)
  (define k (read-json))
  (unless (string? k) (err "non-string value used for json object key"))
  (skip-whitespace)
  (unless (regexp-try-match #rx#"^:" i)
(err "error while parsing a json object pair"))
  (list (string->symbol k) (read-json)))
(apply hasheq (apply append (read-list 'object #rx#"^}" read-pair
  ;;
  (define (read-json [top? #f])
(skip-whitespace)
(cond
  [(and top? (eof-object? (peek-char i))) eof]
  [(regexp-try-match #px#"^true\\b"  i) #t]
  [(regexp-try-match #px#"^false\\b" i) #f]
  [(regexp-try-match #px#"^null\\b"  i) jsnull]
  [(regexp-try-match
#rx#"^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?" i)
   => (λ (bs) (string->number (bytes->string/utf-8 (car bs]
  [(regexp-try-match #rx#"^[\"[{]" i)
   => (λ (m)
(let ([m (car m)])
  (cond [(equal? m #"\"") (read-string)]
[(equal? m #"[")  (read-list 'array #rx#"^\\]" read-json)]
[(equal? m #"{")  (read-hash)])))]
  [else (err (format "bad input~n ~e" (peek-bytes (sub1 
(error-print-width)) 0 i)))]))
  ;;
  (read-json #t))


… and my guess is that the JS performance would be similar, if the json reader 
in JS was written in JS. I think there are probably a lot of provably-unneeded 
checks, and you could probably get rid of the byte-at-a-time reading. 

It would be interesting to see how much faster (if at all) it is to run the TR 
version of this code.

John


> On Feb 22, 2019, at 9:47 AM, Brian Craft  wrote:
> 
> I'm doing a few performance tests, just to get an idea of racket performance. 
> The following result surprised me a bit. Parsing 1M strings from a json 
> array, like
> 
> (define samples (time (read-json (open-input-file "test.json"
> 
> running with 'racket test.rkt'
> 
> Comparing to js, java, and clojure:
> 
> js 0.128s
> java 0.130s
> clojure 1.3s
> racket 10s
> 
> This is pretty slow. Is this typical? Are there other steps I should be 
> taking, for performance?
> 
> -- 
> You 

Re: [racket-users] Strip the lexical context from an identifier

2019-02-22 Thread Matthias Felleisen


And that’s better of course because you pick up the lexical scope, which 

  (let ([x 4]) [(my-macro x) 1 2])

shows. 



> On Feb 22, 2019, at 1:26 PM, Sam Caldwell  wrote:
> 
> You can also do this with syntax-local-introduce to remove x's use-site 
> scope*:
> 
> #lang racket
> 
> (require (for-syntax syntax/parse))
> 
> (define-syntax (my-macro stx)
>(syntax-parse stx
>  [(_ x:id)
>   #:with x- (syntax-local-introduce #'x)
>   #'(lambda (a b) x-)]))
> 
> ((my-macro a) 1 2)
> ;; 1
> 
> ((my-macro b) 1 2)
> ;; 2
> 
> (define x 3)
> ((my-macro x) 1 2)
> ;; 3
> 
> 
> 
> -Sam
> 
> * well, I think that's what's going on.
> 
> On Fri, Feb 22, 2019 at 1:21 PM Matthias Felleisen  
> wrote:
> 
> 
> > On Feb 22, 2019, at 1:08 PM, Stefano Lande  wrote:
> > 
> > Dear all,
> > 
> > first of all, I might being misusing the terminology. Sorry about it.
> > 
> > I would like to write a macro that gets an identifier and return its value 
> > in the new lexical scope created by the macro.
> > For example:
> > 
> > > (define-syntax (my-macro stx)
> >(syntax-parse stx
> >  [(_ x:id)  #'(lambda (a b) x) ]))
> > 
> > 
> > > ((my-macro a) 1 2) 
> > 1
> > 
> > >((my-macro b) 1 2) 
> > 2
> > 
> > 
> > 
> > my-macro as above of course would not work. Is possible to receive an 
> > identifier, strip the lexical context, and evaluate it in the context of 
> > (lambda (a b) body) ?
> 
> 
> Here is one way to get your macro: 
> 
> #lang racket
> 
> (require (for-syntax syntax/parse))
> (require (for-syntax racket/syntax))
> 
> (define-syntax (my-macro stx)
>   (syntax-parse stx
> [(_ x:id)
>  #:with a #'a
>  #:with y (datum->syntax #'a (syntax-e #'x))
>  #`(lambda (a b) y)]))
> 
> [(my-macro a) 1 2]
> [(my-macro b) 1 2]
> (define x 3)
> [(my-macro x) 1 2]
> 
> -- 
> You received this message because you are subscribed to the Google 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] Strip the lexical context from an identifier

2019-02-22 Thread Sam Caldwell
You can also do this with syntax-local-introduce to remove x's use-site
scope*:

#lang racket

(require (for-syntax syntax/parse))

(define-syntax (my-macro stx)
   (syntax-parse stx
 [(_ x:id)
  #:with x- (syntax-local-introduce #'x)
  #'(lambda (a b) x-)]))

((my-macro a) 1 2)
;; 1

((my-macro b) 1 2)
;; 2

(define x 3)
((my-macro x) 1 2)
;; 3



-Sam

* well, I think that's what's going on.

On Fri, Feb 22, 2019 at 1:21 PM Matthias Felleisen 
wrote:

>
>
> > On Feb 22, 2019, at 1:08 PM, Stefano Lande  wrote:
> >
> > Dear all,
> >
> > first of all, I might being misusing the terminology. Sorry about it.
> >
> > I would like to write a macro that gets an identifier and return its
> value in the new lexical scope created by the macro.
> > For example:
> >
> > > (define-syntax (my-macro stx)
> >(syntax-parse stx
> >  [(_ x:id)  #'(lambda (a b) x) ]))
> >
> >
> > > ((my-macro a) 1 2)
> > 1
> >
> > >((my-macro b) 1 2)
> > 2
> >
> >
> >
> > my-macro as above of course would not work. Is possible to receive an
> identifier, strip the lexical context, and evaluate it in the context of
> (lambda (a b) body) ?
>
>
> Here is one way to get your macro:
>
> #lang racket
>
> (require (for-syntax syntax/parse))
> (require (for-syntax racket/syntax))
>
> (define-syntax (my-macro stx)
>   (syntax-parse stx
> [(_ x:id)
>  #:with a #'a
>  #:with y (datum->syntax #'a (syntax-e #'x))
>  #`(lambda (a b) y)]))
>
> [(my-macro a) 1 2]
> [(my-macro b) 1 2]
> (define x 3)
> [(my-macro x) 1 2]
>
> --
> You received this message because you are subscribed to the Google 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] Strip the lexical context from an identifier

2019-02-22 Thread Matthias Felleisen



> On Feb 22, 2019, at 1:08 PM, Stefano Lande  wrote:
> 
> Dear all,
> 
> first of all, I might being misusing the terminology. Sorry about it.
> 
> I would like to write a macro that gets an identifier and return its value in 
> the new lexical scope created by the macro.
> For example:
> 
> > (define-syntax (my-macro stx)
>(syntax-parse stx
>  [(_ x:id)  #'(lambda (a b) x) ]))
> 
> 
> > ((my-macro a) 1 2) 
> 1
> 
> >((my-macro b) 1 2) 
> 2
> 
> 
> 
> my-macro as above of course would not work. Is possible to receive an 
> identifier, strip the lexical context, and evaluate it in the context of 
> (lambda (a b) body) ?
 

Here is one way to get your macro: 

#lang racket

(require (for-syntax syntax/parse))
(require (for-syntax racket/syntax))

(define-syntax (my-macro stx)
  (syntax-parse stx
[(_ x:id)
 #:with a #'a
 #:with y (datum->syntax #'a (syntax-e #'x))
 #`(lambda (a b) y)]))

[(my-macro a) 1 2]
[(my-macro b) 1 2]
(define x 3)
[(my-macro x) 1 2]

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


[racket-users] Strip the lexical context from an identifier

2019-02-22 Thread Stefano Lande
Dear all,

first of all, I might being misusing the terminology. Sorry about it.

I would like to write a macro that gets an identifier and return its value 
in the new lexical scope created by the macro.
For example:

> (define-syntax (my-macro stx)
   (syntax-parse stx
 [(_ x:id)  #'(lambda (a b) x) ]))


> ((my-macro a) 1 2) 
1

>((my-macro b) 1 2) 
2



my-macro as above of course would not work. Is possible to receive an 
identifier, strip the lexical context, and evaluate it in the context of 
(lambda (a b) body) ?

Best,
Stefano

-- 
You received this message because you are subscribed to the Google 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: Use cases for tables and records

2019-02-22 Thread James Platt
In R, I have extensively used the sqldf package, which allows you to execute 
SQL commands on one or more data frames and get the results back as another 
data frame.  You can connect it to different database engines to handle the 
SQL.  Although sqlite is the default, I mostly used PostgreSQL because of it's 
extensive features.  Windowing queries from PostgreSQL, for example, can be a 
really good solution in some circumstances.  

As far as I understand the term, I think this is a good example of language 
oriented programming.  It makes sense to me that Racket should have a way of 
using SQL to directly manipulate data structures.

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


[racket-users] performance, json

2019-02-22 Thread Brian Craft
I'm doing a few performance tests, just to get an idea of racket 
performance. The following result surprised me a bit. Parsing 1M strings 
from a json array, like

(define samples (time (read-json (open-input-file "test.json"

running with 'racket test.rkt'

Comparing to js, java, and clojure:

js 0.128s
java 0.130s
clojure 1.3s
racket 10s

This is pretty slow. Is this typical? Are there other steps I should be 
taking, for performance?

-- 
You received this message because you are subscribed to the Google 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: How do I get (system-tzid) to return the correct value?

2019-02-22 Thread Brian Adkins
On Friday, February 22, 2019 at 11:23:10 AM UTC-5, Jon Zeppieri wrote:
>
>
> On Fri, Feb 22, 2019 at 10:44 AM Brian Adkins  > wrote:
>
>>
>> Yes, I think we found the problem:
>>
>> $ ls -l /etc/localtime
>> lrwxrwxrwx 1 root root 36 Feb 21 21:45 /etc/localtime -> 
>> /usr/share/zoneinfo/America/New_York
>> deploy@ip-172-31-10-34:~$ ls -l /usr/share/zoneinfo/America/New_York
>> lrwxrwxrwx 1 root root 13 Jan  1 00:05 
>> /usr/share/zoneinfo/America/New_York -> ../posixrules
>>  
>>
>> $ racket
>> Welcome to Racket v7.1.
>> > (require racket/enter)
>> > (require tzinfo/private/zoneinfo)
>> > (enter! tzinfo/private/zoneinfo)
>> /tzinfo/tzinfo/private/zoneinfo> (define zi (make-zoneinfo-source))
>> /tzinfo/tzinfo/private/zoneinfo> (tzinfo-has-tzid? zi 
>> "America/New_York")
>> #t
>> /tzinfo/tzinfo/private/zoneinfo> (find-zoneinfo-directory 
>> default-zoneinfo-search-path)
>> "/usr/share/zoneinfo"
>> /tzinfo/tzinfo/private/zoneinfo> (detect-tzid/unix (zoneinfo-dir zi)
>>   
>>  (find-zoneinfo-directory default-zoneinfo-search-path)
>>   
>>  (tzinfo->all-tzids zi))
>> "posixrules"
>>
>>
> Well, that's one I haven't seen before -- a file that actually names a 
> time zone is a symlink to another file. (I see we're not the only people 
> who have run afoul of this [
> https://github.com/HowardHinnant/date/issues/252] 
> 
> ).
>
> We have a few options here.
> - Simply putting the /etc/timezone check before the /etc/localtime check 
> would solve the problem for you, though not for systems that use 
> /etc/localtime as a symlink but do not use /etc/timezone.
> - Similarly, not short-circuiting the various checks and only looking for 
> valid values after we've accumulated all the results of the tests would 
> work in your case, assuming that (tzid-from-/etc/timezone) returns the 
> right answer for you (which I assume it does).
> - Changing the implementation of the /etc/localtime check to use 
> readlink(2) to follow the symlink a single step is an option, though it 
> wouldn't help if someone linked directly from /etc/localtime to posixrules. 
> That sounds like a crazy scenario, but I would have said that linking 
> America/New_York to posixrules is unlikely. (I'd expect it to be the other 
> way around.) I guess the more general approach would be to use readlink(2) 
> until we find a path that names a time zone.
> - I could also abandon the symlink check altogether and always use the 
> slow path, which checks for file _content_ identity between /etc/timezone 
> and any file that names an IANA time zone in the zoneinfo tree.
>
> (Of course, all of this would be unnecessary if the tzid were actually 
> somewhere _in_ the tzfile(5) format somewhere.)
>
> If you need an immediate workaround, you can launch racket with the TZ 
> environment variable set to the contents of /etc/timezone. But I'll fix 
> this just as soon as I decide what the best approach is.
>
>
> By the way (and this question is for everyone), am I right that 
> readlink(2) functionality isn't already in the Racket standard library 
> anywhere? (I don't know if it has an analogue on Windows.)
>
>  - Jon
>
>
Yes, (tzid-from-/etc/timezone) returns the correct value:

/tzinfo/tzinfo/private/os/unix> (tzid-from-/etc/timezone)
"America/New_York" 

It seems that not short circuiting would be a good idea regardless of other 
changes. It's not urgent for me, because the code in question won't run 
late in the evening where the problem occurs.


-- 
You received this message because you are subscribed to the Google 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: How do I get (system-tzid) to return the correct value?

2019-02-22 Thread Jon Zeppieri
On Fri, Feb 22, 2019 at 11:22 AM Jon Zeppieri  wrote:

>
> - I could also abandon the symlink check altogether and always use the
> slow path, which checks for file _content_ identity between /etc/timezone
> and any file that names an IANA time zone in the zoneinfo tree.
>

Or. better, use file-or-directory-identity. (I didn't know this existed.)

- Jon

-- 
You received this message because you are subscribed to the Google 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: How do I get (system-tzid) to return the correct value?

2019-02-22 Thread Jon Zeppieri
On Fri, Feb 22, 2019 at 10:44 AM Brian Adkins  wrote:

>
> Yes, I think we found the problem:
>
> $ ls -l /etc/localtime
> lrwxrwxrwx 1 root root 36 Feb 21 21:45 /etc/localtime ->
> /usr/share/zoneinfo/America/New_York
> deploy@ip-172-31-10-34:~$ ls -l /usr/share/zoneinfo/America/New_York
> lrwxrwxrwx 1 root root 13 Jan  1 00:05
> /usr/share/zoneinfo/America/New_York -> ../posixrules
>
>
> $ racket
> Welcome to Racket v7.1.
> > (require racket/enter)
> > (require tzinfo/private/zoneinfo)
> > (enter! tzinfo/private/zoneinfo)
> /tzinfo/tzinfo/private/zoneinfo> (define zi (make-zoneinfo-source))
> /tzinfo/tzinfo/private/zoneinfo> (tzinfo-has-tzid? zi
> "America/New_York")
> #t
> /tzinfo/tzinfo/private/zoneinfo> (find-zoneinfo-directory
> default-zoneinfo-search-path)
> "/usr/share/zoneinfo"
> /tzinfo/tzinfo/private/zoneinfo> (detect-tzid/unix (zoneinfo-dir zi)
>
>  (find-zoneinfo-directory default-zoneinfo-search-path)
>
>  (tzinfo->all-tzids zi))
> "posixrules"
>
>
Well, that's one I haven't seen before -- a file that actually names a time
zone is a symlink to another file. (I see we're not the only people who
have run afoul of this [https://github.com/HowardHinnant/date/issues/252]).

We have a few options here.
- Simply putting the /etc/timezone check before the /etc/localtime check
would solve the problem for you, though not for systems that use
/etc/localtime as a symlink but do not use /etc/timezone.
- Similarly, not short-circuiting the various checks and only looking for
valid values after we've accumulated all the results of the tests would
work in your case, assuming that (tzid-from-/etc/timezone) returns the
right answer for you (which I assume it does).
- Changing the implementation of the /etc/localtime check to use
readlink(2) to follow the symlink a single step is an option, though it
wouldn't help if someone linked directly from /etc/localtime to posixrules.
That sounds like a crazy scenario, but I would have said that linking
America/New_York to posixrules is unlikely. (I'd expect it to be the other
way around.) I guess the more general approach would be to use readlink(2)
until we find a path that names a time zone.
- I could also abandon the symlink check altogether and always use the slow
path, which checks for file _content_ identity between /etc/timezone and
any file that names an IANA time zone in the zoneinfo tree.

(Of course, all of this would be unnecessary if the tzid were actually
somewhere _in_ the tzfile(5) format somewhere.)

If you need an immediate workaround, you can launch racket with the TZ
environment variable set to the contents of /etc/timezone. But I'll fix
this just as soon as I decide what the best approach is.


By the way (and this question is for everyone), am I right that readlink(2)
functionality isn't already in the Racket standard library anywhere? (I
don't know if it has an analogue on Windows.)

 - Jon

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


[racket-users] Re: Use cases for tables and records

2019-02-22 Thread Ryan Kramer
On the topic of tables, I recently thought "It would be nice if DrRacket 
had some awareness of tabular data, in the same way that picts and syntax 
objects get special treatment."

For my project, I just wrote a quick-and-dirty function to make an ASCII 
art table and moved on: 
https://github.com/default-kramer/plisqin/blob/3d48cacd3c4239aa0a3a96d712cfdef09272422c/private/rows-result-to-string.rkt#L80

But if we're all working with tables, perhaps it would be worth the time 
investment to enhance DrRacket so that tabular data is formatted better, 
copies well to a spreadsheet, and is scrollable in the case of larger data 
sets. Maybe more features I'm not thinking of.

I have no idea how much work this would be. But if this sounds like a good 
idea, and if someone could give me some guidance, I wouldn't mind making an 
attempt.

-- 
You received this message because you are subscribed to the Google 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] Use cases for tables and records

2019-02-22 Thread Greg Hendershott
The overall idea sounds great. I don't really understand the
motivation for "records" with #:keywords?

Maybe you could add a quick explanation about how/when/why they would
be preferred over "more Rackety" choices:

When the keys aren't known at compile time:

- hasheq hash-tables with symbol keys, like jsexprs
- association lists

When the keys are known at compile time:

- structs


p.s. None of the above isn't about the name. But about that: I'm not a
"classic Scheme" person but I think "record" ~= "struct" there so that
might be confusing?

On Thu, Feb 21, 2019 at 2:59 PM  wrote:
>
> Hi folks! I'm looking for use cases for a few small data structure libraries 
> I'm working on:
>
> - Records, which are dictionaries mapping keywords to values. Keys must be 
> keywords, which allows for more efficient behavior in various cases and 
> sometimes cooperates nicely with keyword arguments. Example:
>
> > (define rec (record #:person "Joe Schmoe" #:age 30 #:favorite-color 'blue))
> > (record-ref rec '#:age)
> 30
>
> - Tables, which are like a list of records that all have the same keywords. 
> Tables are similar to dataframes and are intended to make it easy to process 
> spreadsheet-like data such as CSV files. Example:
>
> (table (columns #:name #:population #:capital-city)
>  (row "Argentina" 4380 "Buenos Aires")
>  (row "Greece" 1080 "Athens")
>  (row "Nigeria" 19860 "Abuja")
>  (row "Japan" 12640 "Tokyo"))
>
> The libraries are really just bare-bones skeletons at the moment and are 
> missing a lot of core features. Still, if they seem like things that you 
> would use, please let me know how! Pointers to code "in the wild" where you 
> think these libraries would help are especially useful. Pointers to similar 
> libraries (like the data-frame package) and discussions about their 
> advantages / disadvantages are also helpful.
>
> --
> You received this message because you are subscribed to the Google 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] Re: How do I get (system-tzid) to return the correct value?

2019-02-22 Thread Brian Adkins
On Thursday, February 21, 2019 at 11:16:00 PM UTC-5, Jon Zeppieri wrote:
>
>
>
> On Thu, Feb 21, 2019 at 10:12 PM Brian Adkins  > wrote:
>
>> On Thursday, February 21, 2019 at 9:54:23 PM UTC-5, Jon Zeppieri wrote:
>>>
>>>
>>>
>>> On Thu, Feb 21, 2019 at 9:48 PM Brian Adkins  wrote:
>>>
 On Thursday, February 21, 2019 at 9:35:58 PM UTC-5, Brian Adkins wrote:
>
> On Thursday, February 21, 2019 at 9:26:07 PM UTC-5, Brian Adkins wrote:
>>
>> I'm using the (today) function from the gregor library. It was 
>> returning tomorrow instead of today, so I thought the problem was the 
>> timezone on my Ubuntu server. I configured the timezone to be US/Eastern 
>> via: sudo dpkg-reconfigure tzdata
>>
>> Now the date command returns:  Thu Feb 21 21:23:43 EST 2019   as 
>> expected.
>>
>> Unfortunately, (system-tzid) returns:  "Etc/UTC"
>>
>> So, gregor's (today) still returns tomorrow (since it's so late).
>>
>> Anyone know how to get (system-tzid) to return the correct value on 
>> Ubuntu?
>>
>
> Some more info:
>
> /etc/localtime is linked as:  localtime -> 
> /usr/share/zoneinfo/US/Eastern 
>

 I reinvoked sudo dpkg-reconfigure tzdata  and chose America/New_York  
 instead of  US/Eastern, but I still get the default "Etc/UTC" from 
 (system-tzid) 

>>>
>>>
>>> Huh. Could you do the following and tell me what you get?
>>>
>>> > (require tzinfo/private/generics)
>>> > (require tzinfo/private/zoneinfo)
>>> > (define zi (make-zoneinfo-source))
>>> > (zoneinfo-dir zi)
>>> "/usr/share/zoneinfo"
>>> > (detect-system-tzid zi)
>>> "America/New_York"
>>>
>>
>> > (require tzinfo/private/generics)
>> > (require tzinfo/private/zoneinfo)
>> > (define zi (make-zoneinfo-source))
>> > (zoneinfo-dir zi)
>> "/usr/share/zoneinfo"
>> > (detect-system-tzid zi)
>> #f
>>
>> Also:
>>
>> $ ls -l /etc/localtime
>> lrwxrwxrwx 1 root root 36 Feb 21 21:45 /etc/localtime -> 
>> /usr/share/zoneinfo/America/New_York
>>
>> $ cat /etc/timezone
>> America/New_York
>>  
>>
>
> Thanks.
>
> Okay, so first I figured that the problem was probably due to the weird 
> way that I try to discover the target of an /etc/timezone symlink. (Racket 
> doesn't provide that functionality, as far as I could tell at the time, and 
> I guess I wanted to avoid the FFI? Even though I used it for Windows? My 
> memory fails me.)
>
> But, if that method fails, it also tries getting the value from 
> /etc/timezone, which you noted, is set correctly. And that method of 
> getting the timezone is really simple. It just reads the file. So... hmm. 
> Okay, let's do this exhaustively.
>
> 1. Verify that (system-type) is 'unix. (Just to make sure we check 
> everything.)
>
> 2. In DrRacket, in the definitions window, put the following:
> ```
> #lang racket/base
>
> (require tzinfo/private/zoneinfo)
> ```
> 3. Right click on `tzinfo/private/zoneinfo` and select "Open zoneinfo.rkt."
>
> 4. In the new DrRacket window that contains the source of zoneinfo.rkt, 
> click "Run."
>
> 5. Then, in the interaction pane, do:
> > (define zi (make-zoneinfo-source))
> > (tzinfo-has-tzid? zi "America/New_York")
> #t
>
> If this is #f, that would be bad, and you can stop right there.
>
> 6. Next:
> > (find-zoneinfo-directory default-zoneinfo-search-path)
> "/usr/share/zoneinfo"
>
> If you don't get the same values for this, that would be odd.
>
> 7.
> > (detect-tzid/unix (zoneinfo-dir zi)
> (find-zoneinfo-directory default-zoneinfo-search-path)
> (tzinfo->all-tzids zi))
> "America/New_York"
>
> I expect you'll either get #f here or else you'll get a string but it 
> won't be a valid IANA time zone name.
>
> 8. Near the top of zoneinfo.rkt, you'll see a require line for 
> "os/unix.rkt." Right click that and open the file. Run it.
>
> 9. In the interactions pane:
> > (tzid-from-env)
> #f
>
> (If this isn't #f, and it also isn't an valid IANA time zone id, that 
> would be the problem.)
>
> 10.
> > (tzid-from-/etc/timezone)
> #f
>
> Based on what you wrote above, I expect you to get "America/New_York" 
> here. (I get #f, but I'm on OS X.)
>
> ===
>
> I think you'll have to get unexpected results from one of these, and that 
> should help us figure out the problem.
> My best guess right now is that detect-tzid/unix will return a string that 
> isn't a valid IANA tzid. And that might be because you have the TZ 
> environment variable set. 
>
> Thank you for helping me track down this bug. If my guess is correct, I 
> need to make a slight change to the code.
>
> (Summary: detect-tzid/unix tries a few different methods for determining 
> the system time zone, and it stops when any one of them is non-#f. But the 
> returned string is only validated against the list of IANA zones 
> afterwards, so if any of those methods returns a string that isn't a valid 
> time zone, it won't try any of the other methods.)
>
>
Yes, I think we found the problem:


Re: [racket-users] Use cases for tables and records

2019-02-22 Thread travis . hinkelman
The data-science package isn't focused on the table (or data frame) 
structure (it uses lists of lists) but it includes tooling that is useful 
for working with data stored in that type of structure such as "split -> 
apply -> combine", column indexing, subsetting, grouping, and aggregating.

https://github.com/n3mo/data-science

In particular, I find the documentation for that package very approachable 
for people coming from R/Matlab.



On Friday, February 22, 2019 at 5:47:33 AM UTC-8, Sam Tobin-Hochstadt wrote:
>
> Bitbucket should work fine with the package system -- just provide the 
> URL for the git repository as the source and everything should be good 
> to go. 
>
> Sam 
>
> On Fri, Feb 22, 2019 at 8:14 AM Matt Jadud > 
> wrote: 
> > 
> > On Thu, Feb 21, 2019 at 2:59 PM > 
> wrote: 
> >> 
> >> 
> >> - Tables, which are like a list of records that all have the same 
> keywords. Tables are similar to dataframes and are intended to make it easy 
> to process spreadsheet-like data such as CSV files. Example: 
> >> 
> > 
> > Everyone must be thinking the same things these past few months... 
> > 
> > https://bitbucket.org/jadudm/data-table 
> > 
> > I have been looking at Pyret's interface to tables, as well as the 
> data-frame package in the Racket pkg collection, and R's interface to 
> dataframes. My goal is something that is syntactically/conceptually simple 
> for students to use for EDA, and potentially scales well to more 
> interesting questions involving data. In the fall, I'll be doing work with 
> students around environmental sensing as part of their coursework, and I 
> want something for working with data that fits into the HtDP approach to 
> introducing students to thinking about designing programs. 
> > 
> > Right now, I'm still exploring, and haven't made significant progress on 
> documentation, largely because I've just lifted the library to a point that 
> I can start using it myself for some experimentation with data in a project 
> of my own. This has illustrated some things that are missing, are not as 
> clean as they could be, etc., so I'm going to circle around again on the 
> library as I explore. My thinking is that if I can simplify the interfaces 
> and operations on a project with a heavy data lift, I might be heading in 
> the right direction for small data projects as well. 
> > 
> > At the moment, I can import public spreadsheets from Google, slurp in 
> MySQL tables, SQLite tables, and CSV files. Although proprietary, I'll 
> probably add support for Airtable as an input as well, and will eventually 
> look at some of the MQTT dashboards for IoT (eg. io.adafruit.com). I have 
> not tested the living daylights out of the library, but nascent tests are 
> proceeding with development to watch for regressions as I explore. I can 
> insert, select, and sieve (filter) from tables, as I like the nomenclature 
> that Pyret uses for tables; I'm borrowing their ideas for the interface to 
> table operations for now. 
> > 
> > I like the interface you've proposed for quickly specifying columns 
> (although the rationale for keywords is unclear to me), but I'd personally 
> have to think about the role of types on those columns. I like Pyret's 
> sanitizers, which provide cleanliness guarantees that the user can specify, 
> thus protecting the programmer from ill-formatted data in the table. 
> > 
> > I suppose data-table is a usable library at this point, but it's highly 
> fragile while I'm working on it. However, I'm happy to push to Github as 
> well as Bitbucket (which apparently does not play well with the package 
> distribution system?), so that it can be poked at by others. 
> > 
> > Cheers, 
> > Matt 
> > 
> > 
> > -- 
> > You received this message because you are subscribed 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 . 
> > 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 generators from python land!

2019-02-22 Thread Matthias Felleisen



> On Feb 21, 2019, at 10:32 PM, Konrad Hinsen  
> wrote:
> 
>  The main difference, as has been pointed out before, is that Python 
> generators are more common as an idiom for solving problems that in Racket 
> would typically be approached differently.



[[ This is of course ironic in a way, given how much research the Scheme/PLT 
Scheme/Racket community did on continuations and friends and how many times 
this was motivated in the introductions to papers with “generators” 
“coroutines” “threads” and similar, now-modern ideas of control. But it’s 
better to learn and to improve than to stick with old ideas just for the heck 
of sticking with them. Use control when appropriate. ]] 

-- 
You received this message because you are subscribed to the Google 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] Use cases for tables and records

2019-02-22 Thread Sam Tobin-Hochstadt
Bitbucket should work fine with the package system -- just provide the
URL for the git repository as the source and everything should be good
to go.

Sam

On Fri, Feb 22, 2019 at 8:14 AM Matt Jadud  wrote:
>
> On Thu, Feb 21, 2019 at 2:59 PM  wrote:
>>
>>
>> - Tables, which are like a list of records that all have the same keywords. 
>> Tables are similar to dataframes and are intended to make it easy to process 
>> spreadsheet-like data such as CSV files. Example:
>>
>
> Everyone must be thinking the same things these past few months...
>
> https://bitbucket.org/jadudm/data-table
>
> I have been looking at Pyret's interface to tables, as well as the data-frame 
> package in the Racket pkg collection, and R's interface to dataframes. My 
> goal is something that is syntactically/conceptually simple for students to 
> use for EDA, and potentially scales well to more interesting questions 
> involving data. In the fall, I'll be doing work with students around 
> environmental sensing as part of their coursework, and I want something for 
> working with data that fits into the HtDP approach to introducing students to 
> thinking about designing programs.
>
> Right now, I'm still exploring, and haven't made significant progress on 
> documentation, largely because I've just lifted the library to a point that I 
> can start using it myself for some experimentation with data in a project of 
> my own. This has illustrated some things that are missing, are not as clean 
> as they could be, etc., so I'm going to circle around again on the library as 
> I explore. My thinking is that if I can simplify the interfaces and 
> operations on a project with a heavy data lift, I might be heading in the 
> right direction for small data projects as well.
>
> At the moment, I can import public spreadsheets from Google, slurp in MySQL 
> tables, SQLite tables, and CSV files. Although proprietary, I'll probably add 
> support for Airtable as an input as well, and will eventually look at some of 
> the MQTT dashboards for IoT (eg. io.adafruit.com). I have not tested the 
> living daylights out of the library, but nascent tests are proceeding with 
> development to watch for regressions as I explore. I can insert, select, and 
> sieve (filter) from tables, as I like the nomenclature that Pyret uses for 
> tables; I'm borrowing their ideas for the interface to table operations for 
> now.
>
> I like the interface you've proposed for quickly specifying columns (although 
> the rationale for keywords is unclear to me), but I'd personally have to 
> think about the role of types on those columns. I like Pyret's sanitizers, 
> which provide cleanliness guarantees that the user can specify, thus 
> protecting the programmer from ill-formatted data in the table.
>
> I suppose data-table is a usable library at this point, but it's highly 
> fragile while I'm working on it. However, I'm happy to push to Github as well 
> as Bitbucket (which apparently does not play well with the package 
> distribution system?), so that it can be poked at by others.
>
> Cheers,
> Matt
>
>
> --
> You received this message because you are subscribed to the Google 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] Use cases for tables and records

2019-02-22 Thread Matt Jadud
On Thu, Feb 21, 2019 at 2:59 PM  wrote:

>
> - Tables , which are
> like a list of records that all have the same keywords. Tables are similar
> to dataframes and are intended to make it easy to process spreadsheet-like
> data such as CSV files. Example:
>
>
Everyone must be thinking the same things these past few months...

https://bitbucket.org/jadudm/data-table

I have been looking at Pyret's interface to tables, as well as the
data-frame package in the Racket pkg collection, and R's interface to
dataframes. My goal is something that is syntactically/conceptually simple
for students to use for EDA, and potentially scales well to more
interesting questions involving data. In the fall, I'll be doing work with
students around environmental sensing as part of their coursework, and I
want something for working with data that fits into the HtDP approach to
introducing students to thinking about designing programs.

Right now, I'm still exploring, and haven't made significant progress on
documentation, largely because I've just lifted the library to a point that
I can start using it myself for some experimentation with data in a project
of my own. This has illustrated some things that are missing, are not as
clean as they could be, etc., so I'm going to circle around again on the
library as I explore. My thinking is that if I can simplify the interfaces
and operations on a project with a heavy data lift, I might be heading in
the right direction for small data projects as well.

At the moment, I can import public spreadsheets from Google, slurp in MySQL
tables, SQLite tables, and CSV files. Although proprietary, I'll probably
add support for Airtable as an input as well, and will eventually look at
some of the MQTT dashboards for IoT (eg. io.adafruit.com). I have not
tested the living daylights out of the library, but nascent tests are
proceeding with development to watch for regressions as I explore. I can
insert, select, and sieve (filter) from tables, as I like the nomenclature
that Pyret uses for tables; I'm borrowing their ideas for the interface to
table operations for now.

I like the interface you've proposed for quickly specifying columns
(although the rationale for keywords is unclear to me), but I'd personally
have to think about the role of types on those columns. I like Pyret's
sanitizers, which provide cleanliness guarantees that the user can specify,
thus protecting the programmer from ill-formatted data in the table.

I suppose data-table is a usable library at this point, but it's highly
fragile while I'm working on it. However, I'm happy to push to Github as
well as Bitbucket (which apparently does not play well with the package
distribution system?), so that it can be poked at by others.

Cheers,
Matt

-- 
You received this message because you are subscribed to the Google 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] "table" data structure in Racket

2019-02-22 Thread 'Paulo Matos' via Racket Users



On 22/02/2019 04:05, travis.hinkel...@gmail.com wrote:
> After posing the question yesterday, I spent a little time poking around
> in the Github repository for Apache Arrow and came to the same
> conclusion, i.e., large project presumably facilitated by corporate backing.
> 

True, they are large projects... maybe even facilitated by corporate
backing but someone got them started and they probably got started
without corporate backing. I would say that you should do it if you are
motivated to do it for fun or if you need it. Start small, maybe create
just a very small subset of bindings that solve a specific problem.
Document it, publicize it, allow people to contribute. Maybe one day,
corporate backing will come.


Good luck!

-- 
Paulo Matos

-- 
You received this message because you are subscribed to the Google 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.