Re: [racket-users] Re: with-continuation-marks in errortrace

2020-07-26 Thread Shu-Hung You
By changing (fact 5) to (* 2 (fact 5)), the stack information becomes

/: division by zero
  errortrace...:
   /Volumes/ramdisk/fact.rkt:6:17: (/ 1 0)
   /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n)
   /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n)
   /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n)
   /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n)
   /Volumes/ramdisk/fact.rkt:7:12: (* (loop (sub1 n)) n)
   /Volumes/ramdisk/fact.rkt:9:0: (* 2 (fact 5))

Here, the difference is that (fact 5) is no longer at tail position. I
believe errortrace is aiming at preserving proper tail implementation
behavior.

On Mon, Jul 27, 2020 at 11:39 AM Sorawee Porncharoenwase
 wrote:
>
> (By "integrating" with the new strategy, I meant having two keys: one for the 
> new strategy and one for the old strategy. I can see that the first entry of 
> the old strategy is useful, and it's missing in the new strategy).
>
> On Sun, Jul 26, 2020 at 8:21 PM Sorawee Porncharoenwase 
>  wrote:
>>
>> Hi everyone,
>>
>> I have a question about the implementation of errortrace.
>>
>> Consider the classic factorial program, except that the base case is buggy:
>>
>> (define (fact m)
>>   (let loop ([n m])
>> (cond
>>   [(zero? n) (/ 1 0)]
>>   [else (* (loop (sub1 n)) n)])))
>>
>> (fact 5)
>>
>> Running this program with racket -l errortrace -t fact.rkt gives the 
>> following output:
>>
>> /: division by zero
>>   errortrace...:
>>/Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)
>>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>>
>> I find this result subpar: it doesn’t indicate which call at the top-level 
>> leads to the error. You can imagine another implementation of fact that 
>> errors iff m = 5. Being able to see that (fact 5) at the top-level causes 
>> the error, as opposed to (fact 3), would be very helpful.
>>
>> Not only that, (* (loop (sub1 n)) n) also looks weird. There’s nothing wrong 
>> with multiplication, so I don’t find this information useful.
>>
>> The tail-recursive factorial is similarly not helpful:
>>
>> (define (fact m)
>>   (let loop ([n m] [acc 1])
>> (cond
>>   [(zero? n) (/ 1 0)]
>>   [else (loop (sub1 n) (* n acc))])))
>>
>> (fact 5)
>>
>> produces:
>>
>> /: division by zero
>>   errortrace...:
>>/Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)
>>
>> 
>>
>> I have been toying with another way to instrument the code. It roughly 
>> expands to:
>>
>> (define-syntax-rule (wrap f)
>>   (call-with-immediate-continuation-mark
>>'errortrace-k
>>(λ (k)
>>  (let ([ff (thunk f)])
>>(if k
>>(ff)
>>(with-continuation-mark 'errortrace-k 'f
>>  (ff)))
>>
>> (define (handler ex)
>>   (continuation-mark-set->list (exn-continuation-marks ex) 'errortrace-k))
>>
>> (define (fact m)
>>   (wrap (let loop ([n m])
>>   (wrap (cond
>>   [(wrap (zero? n)) (wrap (/ 1 0))]
>>   [else (wrap (* (wrap n) (wrap (loop (wrap (sub1 
>> n))])
>>
>> (with-handlers ([exn:fail? handler])
>>   (wrap (fact 5)))
>>
>> which produces:
>>
>> '((loop (wrap (sub1 n)))
>>   (loop (wrap (sub1 n)))
>>   (loop (wrap (sub1 n)))
>>   (loop (wrap (sub1 n)))
>>   (loop (wrap (sub1 n)))
>>   (fact 5))
>>
>> This result is more aligned with the traditional stacktrace, and gives 
>> useful information that I can use to trace to the error location.
>>
>> It is also safe-for-space:
>>
>> (define (fact m)
>>   (wrap (let loop ([n m] [acc 1])
>>   (wrap (cond
>>   [(wrap (zero? n)) (wrap (/ 1 0))]
>>   [else (wrap (loop (wrap (sub1 n)) (wrap (* n acc])
>>
>> (with-handlers ([exn:fail? handler])
>>   (wrap (fact 5)))
>>
>> produces:
>>
>> '((fact 5))
>>
>> Now, the question: why is the current errortrace implemented in that way? Am 
>> I missing any downside of this new strategy? Would switching and/or 
>> integrating with the new strategy be better?
>>
>> Thanks,
>> Sorawee (Oak)
>
> --
> You received this message because you are subscribed to the Google 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/CADcuegto9%2BDtFTwAVmiReOcCwpARzBSbFhF0knyexb7UhoHQiA%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 

[racket-users] Re: with-continuation-marks in errortrace

2020-07-26 Thread Sorawee Porncharoenwase
(By "integrating" with the new strategy, I meant having two keys: one for
the new strategy and one for the old strategy. I can see that the first
entry of the old strategy is useful, and it's missing in the new strategy).

On Sun, Jul 26, 2020 at 8:21 PM Sorawee Porncharoenwase <
sorawee.pw...@gmail.com> wrote:

> Hi everyone,
>
> I have a question about the implementation of errortrace.
>
> Consider the classic factorial program, except that the base case is buggy:
>
> (define (fact m)
>   (let loop ([n m])
> (cond
>   [(zero? n) (/ 1 0)]
>   [else (* (loop (sub1 n)) n)])))
>
> (fact 5)
>
> Running this program with racket -l errortrace -t fact.rkt gives the
> following output:
>
> /: division by zero
>   errortrace...:
>/Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)
>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>/Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
>
> I find this result subpar: it doesn’t indicate which call at the top-level
> leads to the error. You can imagine another implementation of fact that
> errors iff m = 5. Being able to see that (fact 5) at the top-level causes
> the error, as opposed to (fact 3), would be very helpful.
>
> Not only that, (* (loop (sub1 n)) n) also looks weird. There’s nothing
> wrong with multiplication, so I don’t find this information useful.
>
> The tail-recursive factorial is similarly not helpful:
>
> (define (fact m)
>   (let loop ([n m] [acc 1])
> (cond
>   [(zero? n) (/ 1 0)]
>   [else (loop (sub1 n) (* n acc))])))
>
> (fact 5)
>
> produces:
>
> /: division by zero
>   errortrace...:
>/Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)
>
> --
>
> I have been toying with another way to instrument the code. It roughly
> expands to:
>
> (define-syntax-rule (wrap f)
>   (call-with-immediate-continuation-mark
>'errortrace-k
>(λ (k)
>  (let ([ff (thunk f)])
>(if k
>(ff)
>(with-continuation-mark 'errortrace-k 'f
>  (ff)))
>
> (define (handler ex)
>   (continuation-mark-set->list (exn-continuation-marks ex) 'errortrace-k))
>
> (define (fact m)
>   (wrap (let loop ([n m])
>   (wrap (cond
>   [(wrap (zero? n)) (wrap (/ 1 0))]
>   [else (wrap (* (wrap n) (wrap (loop (wrap (sub1 
> n))])
>
> (with-handlers ([exn:fail? handler])
>   (wrap (fact 5)))
>
> which produces:
>
> '((loop (wrap (sub1 n)))
>   (loop (wrap (sub1 n)))
>   (loop (wrap (sub1 n)))
>   (loop (wrap (sub1 n)))
>   (loop (wrap (sub1 n)))
>   (fact 5))
>
> This result is more aligned with the traditional stacktrace, and gives
> useful information that I can use to trace to the error location.
>
> It is also safe-for-space:
>
> (define (fact m)
>   (wrap (let loop ([n m] [acc 1])
>   (wrap (cond
>   [(wrap (zero? n)) (wrap (/ 1 0))]
>   [else (wrap (loop (wrap (sub1 n)) (wrap (* n acc])
>
> (with-handlers ([exn:fail? handler])
>   (wrap (fact 5)))
>
> produces:
>
> '((fact 5))
>
> Now, the question: why is the current errortrace implemented in that way?
> Am I missing any downside of this new strategy? Would switching and/or
> integrating with the new strategy be better?
>
> Thanks,
> Sorawee (Oak)
>

-- 
You received this message because you are subscribed to the Google 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/CADcuegto9%2BDtFTwAVmiReOcCwpARzBSbFhF0knyexb7UhoHQiA%40mail.gmail.com.


[racket-users] with-continuation-marks in errortrace

2020-07-26 Thread Sorawee Porncharoenwase
Hi everyone,

I have a question about the implementation of errortrace.

Consider the classic factorial program, except that the base case is buggy:

(define (fact m)
  (let loop ([n m])
(cond
  [(zero? n) (/ 1 0)]
  [else (* (loop (sub1 n)) n)])))

(fact 5)

Running this program with racket -l errortrace -t fact.rkt gives the
following output:

/: division by zero
  errortrace...:
   /Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)
   /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
   /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
   /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
   /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)
   /Users/sorawee/playground/fact.rkt:10:12: (* (loop (sub1 n)) n)

I find this result subpar: it doesn’t indicate which call at the top-level
leads to the error. You can imagine another implementation of fact that
errors iff m = 5. Being able to see that (fact 5) at the top-level causes
the error, as opposed to (fact 3), would be very helpful.

Not only that, (* (loop (sub1 n)) n) also looks weird. There’s nothing
wrong with multiplication, so I don’t find this information useful.

The tail-recursive factorial is similarly not helpful:

(define (fact m)
  (let loop ([n m] [acc 1])
(cond
  [(zero? n) (/ 1 0)]
  [else (loop (sub1 n) (* n acc))])))

(fact 5)

produces:

/: division by zero
  errortrace...:
   /Users/sorawee/playground/fact.rkt:9:17: (/ 1 0)

--

I have been toying with another way to instrument the code. It roughly
expands to:

(define-syntax-rule (wrap f)
  (call-with-immediate-continuation-mark
   'errortrace-k
   (λ (k)
 (let ([ff (thunk f)])
   (if k
   (ff)
   (with-continuation-mark 'errortrace-k 'f
 (ff)))

(define (handler ex)
  (continuation-mark-set->list (exn-continuation-marks ex) 'errortrace-k))

(define (fact m)
  (wrap (let loop ([n m])
  (wrap (cond
  [(wrap (zero? n)) (wrap (/ 1 0))]
  [else (wrap (* (wrap n) (wrap (loop (wrap (sub1 n))])

(with-handlers ([exn:fail? handler])
  (wrap (fact 5)))

which produces:

'((loop (wrap (sub1 n)))
  (loop (wrap (sub1 n)))
  (loop (wrap (sub1 n)))
  (loop (wrap (sub1 n)))
  (loop (wrap (sub1 n)))
  (fact 5))

This result is more aligned with the traditional stacktrace, and gives
useful information that I can use to trace to the error location.

It is also safe-for-space:

(define (fact m)
  (wrap (let loop ([n m] [acc 1])
  (wrap (cond
  [(wrap (zero? n)) (wrap (/ 1 0))]
  [else (wrap (loop (wrap (sub1 n)) (wrap (* n acc])

(with-handlers ([exn:fail? handler])
  (wrap (fact 5)))

produces:

'((fact 5))

Now, the question: why is the current errortrace implemented in that way?
Am I missing any downside of this new strategy? Would switching and/or
integrating with the new strategy be better?

Thanks,
Sorawee (Oak)

-- 
You received this message because you are subscribed to the Google 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/CADcueguwj1rK0oBAj3m2eiv_h94GGSOQP67g5Rxst%2BC4qWjwHg%40mail.gmail.com.


Re: [racket-users] Does Racket interpreter exist?

2020-07-26 Thread Sam Tobin-Hochstadt
Hi,

Racket BC (the non-Chez version) does use an interpreter. The pipeline
in Racket BC is

   source code => expanded code => compiled bytecode => interpreter

or

   source code => expanded code => compiled bytecode => JIT compiler
=> machine code

You can turn off the JIT compiler with the `-j` flag, meaning that it
always uses the interpreter. There is also an interpreter for Racket
CS, but that is a little harder to control manually and less
efficient, so I'll ignore it for these purposes.

The compilation time for Racket is quite small, actually, and
typically pays for itself. The "start slow" effect that you see is
mostly 3 things, in varying proportions in different settings:

1. Time to run macro expansion.
2. Time to do IO to load the standard library (such as `racket/base`)
3. Time to execute the modules in the standard library

For example, if we look at the time to run the command `racket -l
racket/base`, which just loads `racket/base` and exits, provided that
you've fully compiled all of `racket/base`, that takes no time under
bullet 1. But it's still somewhat slow, about 70 ms on my machine.
Python, executing a single print command, is an order of magnitude
faster. That's because Python (a) loads many fewer python source files
on startup (`racket -l racket/base` looks at 234 files that are
actually there with `.rkt` in the name, Python looks at 96) and (b) I
believe the Python module loading semantics allows less work at load
time. Additionally, when Racket starts up, it executes the source of
the expander, which is stored as bytecode in the binary.

All these things add up to slower start time. For user programs, if
you time just expansion of the program (with `raco expand`) and also
compiling the program (with `raco make`) you'll see that most of the
time is expansion time. For the JIT compiler, turning it off
_increases_ startup time because JIT compilation is enough of a win
on, for example, the code in the macro expander.

To have a "start-fast" version of Racket, we would need to pursue some
of the following directions:
 1. ways of loading code using `mmap()` instead of doing IO and
parsing bytecode or compiled machine code
 2. ways to indicate that certain modules didn't need to do any real
execution, perhaps because they contain purely definitions
 3. ways to flatten all of a racket program into something that can be
compiled and loaded as a single file, avoiding IO (this accomplishes 2
as well)
 4. ways to make the macro expander substantially faster

Sam


On Sun, Jul 26, 2020 at 1:36 PM zeRusski  wrote:
>
> Hi all. I wonder if such a thing exist or even possible? Question triggered 
> by the trade off between "compile slowly now to run fast later" vs "start 
> fast". Racket like other modern(ish) Scheme derivatives appear to have 
> settled on being in the former camp. Is there anything in the language that 
> would make interpretation infeasible (semantics?) or unreasonably slow 
> (expansion?)? Chez sports an interpreter with some limitations. I think 
> Gambit ships one although I'm not sure how performant that one is. IIRC Guile 
> recently got something. What about Racket?
>
> Thanks
>
> --
> You received this message because you are subscribed to the Google 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/dd9dd201-5826-4453-8fbe-babc0c477dcdo%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/CAK%3DHD%2BYyjhB47L0YTxOCTDue%3DNscAef4MWGfHqSH7ZweRFukPg%40mail.gmail.com.


[racket-users] Does Racket interpreter exist?

2020-07-26 Thread zeRusski
Hi all. I wonder if such a thing exist or even possible? Question triggered 
by the trade off between "compile slowly now to run fast later" vs "start 
fast". Racket like other modern(ish) Scheme derivatives appear to have 
settled on being in the former camp. Is there anything in the language that 
would make interpretation infeasible (semantics?) or unreasonably slow 
(expansion?)? Chez sports an interpreter with some limitations. I think 
Gambit ships one although I'm not sure how performant that one is. IIRC 
Guile recently got something. What about Racket?

Thanks

-- 
You received this message because you are subscribed to the Google 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/dd9dd201-5826-4453-8fbe-babc0c477dcdo%40googlegroups.com.