Re: [racket-users] Working out which directory the current code was loaded from?

2020-07-27 Thread Peter W A Wood
Many thanks Philip

The resulting code is much neater and, to me, more readable:

(define-runtime-path foo.txt "foo.txt")
(define-runtime-path bar.txt "bar.txt")
(define-runtime-path outfile.txt "outfile.txt")
(define-runtime-path Data/portfolio.csv "../../Data/portfolio.csv")
(define-runtime-path Data/portfolio.csv.gz "../../Data/portfolio.csv.gz”)

Peter

> On 28 Jul 2020, at 09:40, Philip McGrath  wrote:
> 
> For this particular purpose, you want `define-runtime-path`: 
> https://docs.racket-lang.org/reference/Filesystem.html#%28part._runtime-path%29
>  
> 
> 
> -Philip
> 
> 
> On Mon, Jul 27, 2020 at 9:38 PM Peter W A Wood  > wrote:
> I have a short racket program/script that reads a file from the directory in 
> which it is stored. The directory structure is something like this:
> 
> a/
> b/
> c/
> my-racket.rkt 
> my-data-file.txt
> 
> I want to be able to run the program from the command line no matter what is 
> the current working directory. E.G.:
> 
> a> racket b/c/my-racket.rkt
> a/b> racket c/my-racket.rkt
> a/b/c> racket my-racket.rkt
> 
> In order to do so, I need to provide the correct path to my-data-file.txt 
> depending on from where the script was launched. I haven’t learnt about 
> Racket modules yet so I resorted to searching Stack Overflow. I found a code 
> snippet that I used which worked:
> 
> (define script-dir (path-only (resolved-module-path-name
>   (variable-reference->resolved-module-path
>(#%variable-reference)
> 
> Is this the best way to ascertain the directory of the “current module”?
> 
> Thanks in advance
> 
> Peter 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com 
> .
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/92DACE01-60C8-445A-A07E-A4E6A6F5F684%40gmail.com
>  
> .

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/524F478B-0915-4C2F-874B-84CDB966B7D5%40gmail.com.


Re: [racket-users] Working out which directory the current code was loaded from?

2020-07-27 Thread Philip McGrath
For this particular purpose, you want `define-runtime-path`:
https://docs.racket-lang.org/reference/Filesystem.html#%28part._runtime-path%29

-Philip


On Mon, Jul 27, 2020 at 9:38 PM Peter W A Wood 
wrote:

> I have a short racket program/script that reads a file from the directory
> in which it is stored. The directory structure is something like this:
>
> a/
> b/
> c/
> my-racket.rkt
> my-data-file.txt
>
> I want to be able to run the program from the command line no matter what
> is the current working directory. E.G.:
>
> a> racket b/c/my-racket.rkt
> a/b> racket c/my-racket.rkt
> a/b/c> racket my-racket.rkt
>
> In order to do so, I need to provide the correct path to my-data-file.txt
> depending on from where the script was launched. I haven’t learnt about
> Racket modules yet so I resorted to searching Stack Overflow. I found a
> code snippet that I used which worked:
>
> (define script-dir (path-only (resolved-module-path-name
>   (variable-reference->resolved-module-path
>(#%variable-reference)
>
> Is this the best way to ascertain the directory of the “current module”?
>
> Thanks in advance
>
> Peter
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/92DACE01-60C8-445A-A07E-A4E6A6F5F684%40gmail.com
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAH3z3ga%2B4Lhvg8%3DitgW_aLZ%2B-RbdN%2BAZuPPPeYukD3qRYuPiBw%40mail.gmail.com.


[racket-users] Working out which directory the current code was loaded from?

2020-07-27 Thread Peter W A Wood
I have a short racket program/script that reads a file from the directory in 
which it is stored. The directory structure is something like this:

a/
b/
c/
my-racket.rkt 
my-data-file.txt

I want to be able to run the program from the command line no matter what is 
the current working directory. E.G.:

a> racket b/c/my-racket.rkt
a/b> racket c/my-racket.rkt
a/b/c> racket my-racket.rkt

In order to do so, I need to provide the correct path to my-data-file.txt 
depending on from where the script was launched. I haven’t learnt about Racket 
modules yet so I resorted to searching Stack Overflow. I found a code snippet 
that I used which worked:

(define script-dir (path-only (resolved-module-path-name
  (variable-reference->resolved-module-path
   (#%variable-reference)

Is this the best way to ascertain the directory of the “current module”?

Thanks in advance

Peter 


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/92DACE01-60C8-445A-A07E-A4E6A6F5F684%40gmail.com.


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

2020-07-27 Thread zeRusski

>
> The best way to distinguish compilers from interpreters is that a 
> compiler takes a program and produces another program, whereas an 
> interpreter takes a program (along with some input) and produces an 
> answer. 
>

Doesn't this trivialize the difference a bit too much? Does it really come 
down to the time you choose to compute? I persist intermediate state - I am 
a compiler. I do the exact same thing (run off the same "compiler" 
codebase) but ask for inputs and compute - I am an interpreter.

I scratched my head a bit and came up with the following: if there is one 
to one correspondence between target and host language "blocks" (there may 
be multiple such pairs till you get to machine code) then this is an 
interpreter. If you do nasty shenanigans in the generated code in the host 
(semantics altering optimisation passes and what not) then this is a 
compiler. Latter ought to effect debugging even error reporting quite 
drastically. This is almost certainly naive and amateur of me. I'm 
desperately trying to understand why I have the impression that there ought 
to be a non-trivial difference between the two. That's been my impression 
from the literature.

I think I had this paper in mind: https://www.jilp.org/vol5/v5paper12.pdf 
oh wait p4: "we do not have a precise definition for efficient interpreter" 
... oh good. Although they do mention some justification for "compiling" to 
a VM in the following paragraphs that boils down to "avoid the overhead of 
re-parsing and re-interpreting intermediate representation". I vaguely 
recall that Lisp in Small Pieces switched to a VM when the "fast 
interpretation" was introduced.

I may have confused myself. Badly :(

I guess I would call Tcl and Picolisp interpreters and Racket and most 
Scheme implementations of note not at all.

-- 
You received this message because you are subscribed to the Google 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/98a4e936-1703-4182-bb85-ce78a8694feao%40googlegroups.com.


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

2020-07-27 Thread Sam Tobin-Hochstadt
A few thoughts on interpreters vs compilers:

- somewhere, there has to be an interpreter -- the x86 chip in my
laptop is interpreting the x86 code that Racket generates.
- there could certainly be a more direct AST-based interpreter for
(fully-expanded) Racket. My work on Pycket involved writing such an
interpreter, for example.

The best way to distinguish compilers from interpreters is that a
compiler takes a program and produces another program, whereas an
interpreter takes a program (along with some input) and produces an
answer.

Sam

On Mon, Jul 27, 2020 at 12:35 PM zeRusski  wrote:
>
> Thank you for this fantastic reply Sam! I now think I had a very naive model 
> of "interpreter" when I asked the question. My CS degree from the nowhere 
> university has it that language interpreters walk the tree and you know 
> "execute" be it in the host language or generating native code. I feel a bit 
> stupid now. Technically you're absolutely right - there is an interpreter for 
> the bytecode (or whatever), so duh. But there are also a bunch of compilation 
> steps in between. I am now completely lost as to what constitutes a compiler 
> and what makes an interpreter. I always thought of interpreters as something 
> I encountered in PLAI. I remember reading some old paper abound "fast 
> interpreters" and all of them implemented a virtual machine they "compiled" 
> to and I was lost then - how's that not a compiler - as I am lost now.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/b183ae65-524d-4e70-9bee-ce0531bf21feo%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%2BZ0G-iYDYAreU2qg1vC%3DDhT777%3DsE2kqT6QC0iQyD3JwQ%40mail.gmail.com.


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

2020-07-27 Thread zeRusski
Thank you for this fantastic reply Sam! I now think I had a very naive 
model of "interpreter" when I asked the question. My CS degree from the 
nowhere university has it that language interpreters walk the tree and you 
know "execute" be it in the host language or generating native code. I feel 
a bit stupid now. Technically you're absolutely right - there is an 
interpreter for the bytecode (or whatever), so duh. But there are also a 
bunch of compilation steps in between. I am now completely lost as to what 
constitutes a compiler and what makes an interpreter. I always thought of 
interpreters as something I encountered in PLAI. I remember reading some 
old paper abound "fast interpreters" and all of them implemented a virtual 
machine they "compiled" to and I was lost then - how's that not a compiler 
- as I am lost now.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/b183ae65-524d-4e70-9bee-ce0531bf21feo%40googlegroups.com.


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

2020-07-27 Thread 'John Clements' via Racket Users
Let me jump in here and say a few things that maybe everyone already knows :).

The stepper’s annotation places a *ton* of annotation on a computation, and 
allows the reconstruction of the full computation. Errortrace does less, and 
provides less.

The both share a goal of allowing the programmer to see “where you are in the 
computation”, by capturing “what remains to be done in the computation”, and 
neither one tries to capture “how we got here”.

Specifically, in the (* (loop (sub1 n) n) expression, a mark on the application 
of loop is currently overwritten immediately by the mark on the body of the 
called function. In this case, the still-present mark on the multiplication is 
telling you “this multiplication still remains to be done”, but in fact you’ve 
lost important information on *which* of the subterms of the multiplication is 
currently being evaluated. In the stepper, this is essentially converted to 
a-normal form so that the mark isn’t just “the multiplication isn’t done yet” 
but rather “the second argument hasn’t yet been evaluated.”

My understanding of your proposal is that it suggests preserving the first mark 
that is associated with a continuation, rather than (or perhaps in addition to) 
the last.

I do think that this could be helpful in some situations.

I also think that the fundamental problem that you point to in the beginning 
isn’t one of what information to store, though, but rather how it’s presented. 
Specifically, the presence of the mark around the multiplication captures the 
following information: “we’re currently in a call to loop, and we’re evaluating 
either the first or second argument of this multiplication”. I’m not sure what 
a good way to present this information would be:

> in call to ‘loop’, at either (* [] n) or (* (loop (sub1 n) []).

yeah, that was terrible. Ugh. Surely someone can do better than that.

Anyhow, my point is that for the example that I believe you’re examining, the 
information you want can be extracted from the information that’s present.

I would like to acknowledge though, that that’s definitely *not* always the 
case; if you have a bunch of calls that only make tail calls, then you can 
easily lose information about how you got here. I understand that from a 
programmer’s standpoint, the question “how did we get here” may be more 
relevant than “where are we now,” and I do think that it might make sense to 
take the same approach that (IIRC) Andrew Tolmach & others took in the ML 
debugger of saving a rolling sequence of up to five marks (or six or ten or 
whatever you choose).

Put differently, I think that there is potentially a “lost information” 
situation here, but I think that if you want to preserve that information, you 
should do so by using a rolling buffer, rather than by supplementing “last 
expression” with “first expression”.

More broadly, I also think that errortrace’s display of information is probably 
not the best; I think it’s been a long time since anyone was thinking hard 
about how best to convey the errortrace information to the programmer. 
Apologies if I’m wrong about that.

AND, as always, apologies if I’m misunderstanding something important about 
your proposal!

Best,

John


> On Jul 27, 2020, at 09:26, Matthew Flatt  wrote:
> 
> At Sun, 26 Jul 2020 20:21:56 -0700, Sorawee Porncharoenwase wrote:
>> 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)))
> 
> This variant probably generates faster code:
> 
> (define-syntax-rule (wrap f)
>   (call-with-immediate-continuation-mark
>'errortrace-k
>(λ (k)
>  (with-continuation-mark 'errortrace-k (or k 'f)
>f
> 
> 
>> 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?
> 
> I don't recall there was any careful study of the alternatives. Always
> setting the mark is easiest, and so that's probably why the current
> implementation always sets the mark. Maybe keeping the first expression
> for a frame instead of the last is consistently more useful.
> 
> At Sun, 26 Jul 2020 20:39:35 -0700, 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).
> 
> Instead of a separate mark, `or` above could be replaced by some
> combinator that keeps more information in the mark value, such as a
> first and last call using a pair:
> 
> (define-syntax-rule (wrap f)
>   (call-with-immediate-continuation-mark
>'errortrace-k
>

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

2020-07-27 Thread Matthew Flatt
At Sun, 26 Jul 2020 20:21:56 -0700, Sorawee Porncharoenwase wrote:
> 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)))

This variant probably generates faster code:

 (define-syntax-rule (wrap f)
   (call-with-immediate-continuation-mark
'errortrace-k
(λ (k)
  (with-continuation-mark 'errortrace-k (or k 'f)
f


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

I don't recall there was any careful study of the alternatives. Always
setting the mark is easiest, and so that's probably why the current
implementation always sets the mark. Maybe keeping the first expression
for a frame instead of the last is consistently more useful.

At Sun, 26 Jul 2020 20:39:35 -0700, 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).

Instead of a separate mark, `or` above could be replaced by some
combinator that keeps more information in the mark value, such as a
first and last call using a pair:

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

Something other than a pair could keeps the first plus up to 5 most
recent calls. But then you'd probably want the errortrace annotator to
be a little smarter and not useless report syntactically enclosing
expressions, like a sequence of `begin`s in something like

 (begin
   
   (begin
 
 (begin
   
   )))

Overall, your simple change seems clearly worth trying out in
errortrace, and maybe other variants would be interesting to explore.


Matthew

-- 
You received this message because you are subscribed to the Google 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/20200727072658.3df%40sirmail.smtp.cs.utah.edu.


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

2020-07-27 Thread Shu-Hung You
Thinking about your example again, is the idea here to preserve the
first (so perhaps outermost) continuation mark information, instead of
the innermost continuation mark? I don't yet fully understand how this
approach interacts with the evaluation of tail position expressions,
but keeping both seems pretty useful.

Regarding the (* (loop (sub1 n)) n) information, as I understand
errortrace does wrap subexpressions. Here is the instrumentation
result of (* (loop (sub1 n)) n):

  (with-continuation-mark ek:errortrace-key '((* (loop (sub1 n)) n) SRCLOC)
(#%app
*
(with-continuation-mark ek:errortrace-key '((loop (sub1 n)) SRCLOC)
  (#%app
loop
(with-continuation-mark ek:errortrace-key '((sub1 n) SRCLOC)
  (#%app sub1 n
n))

A guess is that the continuation mark value '((loop (sub1 n)) SRCLOC)
is being overwritten by its subsequent evaluation to (* (loop (sub1
n)) n). This provides error-centric backtrace information.

What I can think about the effect of keeping only the outermost
continuation mark is that the control-flow information w.r.t. tail
expressions will be lost. In the following (unreal) example, there
will be no chance to identify which (/ y 0) caused the error.

On Mon, Jul 27, 2020 at 1:13 PM Shu-Hung You  wrote:
>
> 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