Re: [racket-users] IO in racket is painful

2017-07-20 Thread Sorawee Porncharoenwase
Sorry for reviving an old thread. As someone who did a lot of programming 
competition in the past, I can totally see why IO in Racket is difficult. As 
mark.engelberg said, the goal is to solve as many problems as possible. After 
the competition is over, it's over. No one is going to care about 
maintainability or good coding practice if it makes coding slower. For this 
reason, I wouldn't use parsack if possible. While elegant, there's too much to 
write which is a waste of time.

Luckily, major programming competitions (say, Facebook Hacker Cup, Google Code 
Jam, early IOI, ACM-ICPC, etc.) usually have simple input format. Data are 
usually separated by spaces. Rarely spaces matter. rom gcb says that the input 
is:

  3
  [04, foo, 03.5]
  [05, bar, 04.6]
  [06, fun, 05.7]

but in these competitions, the input is more likely to be:

  3
  04 foo 03.5
  05 bar 04.6
  06 fun 05.7

What really gets in the way is that strings in the input could be something 
that Racket's (read) doesn't recognize. As an example, a string might be #asd. 
This would cause (read) to error "read: bad syntax `#a'".

Indeed, using (read-line) along with regex would solve the problem. The 
downside is that it requires a lot of writing and is heavily task-dependent. 
What I want is a uniform way to extract data easily like scanf.

I write the following module for this purpose. It's a lot of code, so it would 
be useless in closed competitions like ACM-ICPC. However, for online 
competitions like FB Hacker Cup, I find it pretty useful.


#lang racket

(provide (all-defined-out))

(define read-next
  (let ([buffer #f])
(lambda (#:to-eol [to-eol #f])
  (define (more!) (set! buffer (read-line)) (read-next #:to-eol to-eol))
  (match buffer
[(? string?)
 (cond
   [to-eol (let ([ret buffer]) (set! buffer #f) ret)]
   [else
(set! buffer (string-trim buffer #:right? #f))
(match (regexp-match #px"\\S+" buffer)
  [(list ret) (set! buffer (regexp-replace #px"^\\S+" buffer "")) 
ret]
  [#f (more!)])])]
[_ (more!)]

(define (%list n typ) (thunk (for/list ([_ n]) (typ
(define (%gets) (read-next #:to-eol #t))
(define (%num) (string->number (read-next)))
(define (%str) (read-next))
(define-syntax-rule (scan [v m] ...) (begin (define v (m)) ...))

(module+ test
  (require rackunit)
  (parameterize
  ([current-input-port
(open-input-string
 (string-append "2  3  \n"
"123\n"
"   4   5   6\n"
"   \n"
"  \n"
" \n"
"\n"
" '\"has-quotes\"' blah blah "))])
(scan [n %num]
  [m %num]
  [matrix (%list n (%list m %num))]
  [trailing-spaces %gets]
  [str-with-quotes %str]
  [line-with-space %gets])
(check-equal? n 2)
(check-equal? m 3)
(check-equal? matrix (list (list 1 2 3) (list 4 5 6)))
(check-equal? trailing-spaces "")
(check-equal? str-with-quotes "'\"has-quotes\"'")
(check-equal? line-with-space " blah blah ")))



For example, https://code.google.com/codejam/contest/6254486/dashboard#s=p1 can 
be solved as follows:

(scan [n %num])
(for ([i n])
  (scan [s %str])
  (define simp (regexp-replaces s '([#px"\\++" "+"] [#px"\\-+" "-"])))
  (define len (string-length simp))
  (printf "Case #~a: ~a\n"
  (add1 i)
  (match (list (string-ref simp 0) (even? len))
[(or (list #\+ #t) (list #\- #f)) len]
[(or (list #\+ #f) (list #\- #t)) (sub1 len)])))

-- 
You received this message because you are subscribed to the Google 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] Understanding compilation costs and creating persistent values

2017-07-20 Thread David Storrs
On Thu, Jul 20, 2017 at 2:56 PM, Matthew Flatt  wrote:

> Adding to other replies:
>
> At Thu, 20 Jul 2017 13:32:49 -0400, David Storrs wrote:
> > Will any of the above items be compiled away?
>
> You can compile a module with `raco make` and look at the compiled code
> with `raco decompile`. If I put your code in a module and try that, the
> output includes
>
> (define-values
>  (_foo)
>  (lambda ()
>
>(begin
>  (values (file-size '"/some/path"))
>  (let ((local22 (file-size '"/some/other/path")))
>(begin
>  (|_displayln:p@(lib "racket/private/misc.rkt")|
>   (#%sfs-clear local22))
>  '#t)
>
> So, you can see that the compiler discarded an addition that always
> produces 2, and it discarded the unused `bar` function. It also got rid
> of the unused `size` variable, but it preserved everything else as a
> run-time computation.
>

Brilliant.  Thank you Matthew, this is really useful to know.


>
> > Perl has the 'state' declaration, which says "Declare this as a local
> > variable, but keep it around with its value preserved after you exit the
> > function."
>
> Assuming that you really want to do that and you really want a `state`
> form:
>
>   (define-syntax (state stx)
> (syntax-parse stx
>   [(_ var:id rhs:expr)
>(with-syntax ([lifted-var (syntax-local-lift-expression #'rhs)])
>  #'(define-syntax var (make-rename-transformer #'lifted-var)))]))
>
>   (define (f v)
> (state accum 0)
> (set! accum (+ v accum))
> accum)
>
>   (f 1)
>   (f 2)
>
>
Man, Racket is amazing.




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

2017-07-20 Thread Lehi Toskin
Yes, my first question was definitely answered already.

-- 
You received this message because you are subscribed to the Google 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] Understanding compilation costs and creating persistent values

2017-07-20 Thread Matthew Flatt
Adding to other replies:

At Thu, 20 Jul 2017 13:32:49 -0400, David Storrs wrote:
> Will any of the above items be compiled away?

You can compile a module with `raco make` and look at the compiled code
with `raco decompile`. If I put your code in a module and try that, the
output includes

(define-values
 (_foo)
 (lambda ()
   
   (begin
 (values (file-size '"/some/path"))
 (let ((local22 (file-size '"/some/other/path")))
   (begin
 (|_displayln:p@(lib "racket/private/misc.rkt")|
  (#%sfs-clear local22))
 '#t)

So, you can see that the compiler discarded an addition that always
produces 2, and it discarded the unused `bar` function. It also got rid
of the unused `size` variable, but it preserved everything else as a
run-time computation.

> Perl has the 'state' declaration, which says "Declare this as a local
> variable, but keep it around with its value preserved after you exit the
> function."

Assuming that you really want to do that and you really want a `state`
form:

  (define-syntax (state stx)
(syntax-parse stx
  [(_ var:id rhs:expr)
   (with-syntax ([lifted-var (syntax-local-lift-expression #'rhs)])
 #'(define-syntax var (make-rename-transformer #'lifted-var)))]))

  (define (f v)
(state accum 0)
(set! accum (+ v accum))
accum)

  (f 1)
  (f 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.


Re: [racket-users] Understanding compilation costs and creating persistent values

2017-07-20 Thread Neil Van Dyke

David Storrs wrote on 07/20/2017 01:32 PM:


sub foo { state $x = 0;  say $x++; }
# $x is not visible in this scope
foo();
foo();
foo();


(define foo
  (let ((x 0))
(lambda ()
  (printf "~s~n" x)
  (set! x (add1 x)
; x is not visible in this scope
(foo)
(foo)
(foo)


Doing this with mutable variables is usually a bad idea.  For major 
historical example, an analogous practice resulted in a headache of 
"non-reentrant" C library functions when we started doing multithreaded 
programming.  And you're going to have to think about concurrency 
implications.


Of course, sometimes it's appropriate.  It's another of those things 
that people usually shouldn't do unless and until they know why it's 
usually a bad idea, they understand the possible alternative approaches, 
and they know why it's appropriate in this case.


It's more often a good idea if `x` is immutable.  Like, `x` is 
referenced only in that procedure, and has a constant value that you 
want to initialize at/after load time (e.g., constructing a value using 
info or code that's not available until load time).  Before Racket got 
`#rx` syntax, I'd sometimes use this to compile regular expressions, and 
just keep them "close to" the procedure that used them, 
readability/maintainability-wise.


--
You received this message because you are subscribed to the Google 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] Understanding compilation costs and creating persistent values

2017-07-20 Thread Leif Andersen
> Will any of the above items be compiled away?

To answer your first question, I would recommend taking a look at the
optimization coach. It can help you figure out what code was inlined
away and what wasn't. You can find it in:

View -> Show Optimization coach

> How many times will each thing be expanded and compiled -- is bar defined and 
> compiled five separate times, only once, or not at all?

Even if `bar` is not inlined, it will still only be compiled once.
However, it will close over 5 different sets of variables (containing
num, size, etc.)

> Is there a simple way to achieve the same thing in Racket?

Yes there is. Although I must state that if you find yourself doing
this, stop, and rethink things, because more often then not there is a
simpler way to write your code.

However, if this is one of the rare cases where `state` variables (so
to speak) are needed, I find using `(let () ...)` blocks to be
helpful. Take the following code:

(define inc
  (let ()
(define x 0)
(lambda ()
(set! x (+ x 1))
x)))

Here, `inc` is a function that takes no arguments, but has a so-called
`state` variable that increments with each call.

> (inc)
1
> (inc)
2
> (inc)
3
...

Again, when you find yourself doing that, I strongly recommend
stopping and rethinking your solution.

Hope that helps.



~Leif Andersen


On Thu, Jul 20, 2017 at 1:32 PM, David Storrs  wrote:
> Given this code:
>
> (define (foo)
>(define num (+ 1 1)); result
> of a function that is program-local
>(define size (file-size "/some/path"))   ; result of a
> function that touches the disk, but result never used
>(define other-size (file-size "/some/other/path")) ; result of function
> that touches disk, result is used
>(displayln other-size)
>(define x 7) ;
> binding of constant value, binding is never used
>(define (bar)   ;
> binding of function, function is never used
>(displayln "bar"))
>#t)
>
> (for ((i 5))
> (foo))
>
> Will any of the above items be compiled away?  How many times will each
> thing be expanded and compiled -- is bar defined and compiled five separate
> times, only once, or not at all?
>
>
> Separate but related question:
>
> Perl has the 'state' declaration, which says "Declare this as a local
> variable, but keep it around with its value preserved after you exit the
> function."  For example:
>
> sub foo { state $x = 0;  say $x++; }
> # $x is not visible in this scope
> foo();
> foo();
> foo();
>
>
> Output:
> 0
> 1
> 2
>
> Is there a simple way to achieve the same thing in Racket?
>
> --
> You received this message because you are subscribed to the Google 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] Understanding compilation costs and creating persistent values

2017-07-20 Thread David Storrs
Given this code:

(define (foo)
   (define num (+ 1 1)); result
of a function that is program-local
   (define size (file-size "/some/path"))   ; result of a
function that touches the disk, but result never used
   (define other-size (file-size "/some/other/path")) ; result of function
that touches disk, result is used
   (displayln other-size)
   (define x 7) ;
binding of constant value, binding is never used
   (define (bar)   ;
binding of function, function is never used
   (displayln "bar"))
   #t)

(for ((i 5))
(foo))

Will any of the above items be compiled away?  How many times will each
thing be expanded and compiled -- is bar defined and compiled five separate
times, only once, or not at all?


Separate but related question:

Perl has the 'state' declaration, which says "Declare this as a local
variable, but keep it around with its value preserved after you exit the
function."  For example:

sub foo { state $x = 0;  say $x++; }
# $x is not visible in this scope
foo();
foo();
foo();


Output:
0
1
2

Is there a simple way to achieve the same thing in Racket?

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