Re: [racket-users] opinion needed on best fix for handin-server problem
> On Apr 27, 2016, at 3:01 PM, Sam Tobin-Hochstadt wrote: > > The exceptions raised by `match` are indeed not transparent. But I > don't understand why they need to be in order for the handin server to > handle them properly. (caveat: this is my reading of the code below) The handin server wants to add information to the exn-message part, in order to indicate what handin test triggered the error. Doing this involves converting the exception to a vector, adding text to the message part, and then reassembling and re-raising the error. The code below therefore bails out when either “skipped?” turns out to be true or when one or when struct->vector produces a vector with opaque fields. This doesn’t appear to be a problem for any of the other exceptions that the handin server encounters (well, this is the first time I’ve seen this problem, anyhow). I can hack the handin server to treat match exceptions specially, but that definitely doesn’t seem like the right solution. John (define ((wrap-evaluator eval) expr) (define unknown "unknown") (define (reraise exn) (raise (let-values ([(struct-type skipped?) (struct-info exn)]) (if (and struct-type (not skipped?)) (let ([vals (cdr (vector->list (struct->vector exn unknown)))]) (if (memq unknown vals) exn (apply (struct-type-make-constructor struct-type) (format "while evaluating ~s:\n ~a" expr (car vals)) (cdr vals exn (with-handlers ([exn? reraise]) (eval expr))) > > Sam > > On Wed, Apr 27, 2016 at 5:58 PM, 'John Clements' via Racket Users > wrote: >> >>> On Apr 22, 2016, at 1:47 PM, 'John Clements' via Racket Users >>> wrote: >>> >>> Currently, the handin-server runs student expressions in an ‘eval’ which >>> intercepts errors and re-raises them with a message that includes the >>> failing expression. All good. >>> >>> However, it doesn’t catch all of them. Specifically, if the exception >>> contains any values that are opaque to struct->vector, it gives up and >>> re-raises the exception as-is. >>> >>> This turns out to cause a problem with “match” failures, which include such >>> values. This causes a problem for my students, because they’re unable to >>> see the text of the test cases that they failed. >>> >>> It’s easy enough to hack around this in my code by re-wording ‘match’ >>> failures in the same way that wrap-evaluator does. In general, though, it >>> seems like there’s no good reason that ‘match’ failures shouldn’t go into >>> the same bin as division by zero, applying a non-function, and all of the >>> other things that can go wrong during evaluation. >>> >>> In order to fix this, then, I’m trying to determine why this check exists: >>> what exceptions do you *not* want to re-word here? >> >> Okay, answering my own question and asking another: >> >> The fundamental reason for the existence of this logic is that the >> handin-engine is trying to be careful, and modify exceptions that can safely >> be reconstructed. If the “skipped” value is #t, or if one or more of the >> values in the structure are opaque, this is impossible. At this point, the >> handin engine just throws up its hands and decides to follow the hippocratic >> oath, “first do no harm,” and let the exception continue as is. >> >> So, this leads to a different question: *why* is the match exception >> different from all the other exceptions? Based on my reading of the >> struct-info documentation, it appears that the ‘match’ form constructs >> exceptions whose inspector is not the current one, or perhaps that it fails >> to declare itself as transparent. >> >> My guess is that this is just an oversight, and that a ‘match’ exception >> should be just as transparent as, say, a division by zero exception. Here’s >> code that illustrates the difference: >> >> #lang racket >> >> (with-handlers ([exn:fail? >> (λ (exn) >> (struct-info exn))]) >> (/ 1 0)) >> >> (with-handlers ([exn:fail? >> (λ (exn) >> (struct-info exn))]) >> (match 13 >>['a 4])) >> >> So, here’s my question: >> >> Is there a good reason for the difference between the `match` exception >> (skipped is #t) and the division-by-zero exception (skipped is #f) ? >> >> 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.
Re: [racket-users] opinion needed on best fix for handin-server problem
The exceptions raised by `match` are indeed not transparent. But I don't understand why they need to be in order for the handin server to handle them properly. Sam On Wed, Apr 27, 2016 at 5:58 PM, 'John Clements' via Racket Users wrote: > >> On Apr 22, 2016, at 1:47 PM, 'John Clements' via Racket Users >> wrote: >> >> Currently, the handin-server runs student expressions in an ‘eval’ which >> intercepts errors and re-raises them with a message that includes the >> failing expression. All good. >> >> However, it doesn’t catch all of them. Specifically, if the exception >> contains any values that are opaque to struct->vector, it gives up and >> re-raises the exception as-is. >> >> This turns out to cause a problem with “match” failures, which include such >> values. This causes a problem for my students, because they’re unable to see >> the text of the test cases that they failed. >> >> It’s easy enough to hack around this in my code by re-wording ‘match’ >> failures in the same way that wrap-evaluator does. In general, though, it >> seems like there’s no good reason that ‘match’ failures shouldn’t go into >> the same bin as division by zero, applying a non-function, and all of the >> other things that can go wrong during evaluation. >> >> In order to fix this, then, I’m trying to determine why this check exists: >> what exceptions do you *not* want to re-word here? > > Okay, answering my own question and asking another: > > The fundamental reason for the existence of this logic is that the > handin-engine is trying to be careful, and modify exceptions that can safely > be reconstructed. If the “skipped” value is #t, or if one or more of the > values in the structure are opaque, this is impossible. At this point, the > handin engine just throws up its hands and decides to follow the hippocratic > oath, “first do no harm,” and let the exception continue as is. > > So, this leads to a different question: *why* is the match exception > different from all the other exceptions? Based on my reading of the > struct-info documentation, it appears that the ‘match’ form constructs > exceptions whose inspector is not the current one, or perhaps that it fails > to declare itself as transparent. > > My guess is that this is just an oversight, and that a ‘match’ exception > should be just as transparent as, say, a division by zero exception. Here’s > code that illustrates the difference: > > #lang racket > > (with-handlers ([exn:fail? > (λ (exn) >(struct-info exn))]) > (/ 1 0)) > > (with-handlers ([exn:fail? > (λ (exn) >(struct-info exn))]) > (match 13 > ['a 4])) > > So, here’s my question: > > Is there a good reason for the difference between the `match` exception > (skipped is #t) and the division-by-zero exception (skipped is #f) ? > > 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.
Re: [racket-users] opinion needed on best fix for handin-server problem
> On Apr 22, 2016, at 1:47 PM, 'John Clements' via Racket Users > wrote: > > Currently, the handin-server runs student expressions in an ‘eval’ which > intercepts errors and re-raises them with a message that includes the failing > expression. All good. > > However, it doesn’t catch all of them. Specifically, if the exception > contains any values that are opaque to struct->vector, it gives up and > re-raises the exception as-is. > > This turns out to cause a problem with “match” failures, which include such > values. This causes a problem for my students, because they’re unable to see > the text of the test cases that they failed. > > It’s easy enough to hack around this in my code by re-wording ‘match’ > failures in the same way that wrap-evaluator does. In general, though, it > seems like there’s no good reason that ‘match’ failures shouldn’t go into the > same bin as division by zero, applying a non-function, and all of the other > things that can go wrong during evaluation. > > In order to fix this, then, I’m trying to determine why this check exists: > what exceptions do you *not* want to re-word here? Okay, answering my own question and asking another: The fundamental reason for the existence of this logic is that the handin-engine is trying to be careful, and modify exceptions that can safely be reconstructed. If the “skipped” value is #t, or if one or more of the values in the structure are opaque, this is impossible. At this point, the handin engine just throws up its hands and decides to follow the hippocratic oath, “first do no harm,” and let the exception continue as is. So, this leads to a different question: *why* is the match exception different from all the other exceptions? Based on my reading of the struct-info documentation, it appears that the ‘match’ form constructs exceptions whose inspector is not the current one, or perhaps that it fails to declare itself as transparent. My guess is that this is just an oversight, and that a ‘match’ exception should be just as transparent as, say, a division by zero exception. Here’s code that illustrates the difference: #lang racket (with-handlers ([exn:fail? (λ (exn) (struct-info exn))]) (/ 1 0)) (with-handlers ([exn:fail? (λ (exn) (struct-info exn))]) (match 13 ['a 4])) So, here’s my question: Is there a good reason for the difference between the `match` exception (skipped is #t) and the division-by-zero exception (skipped is #f) ? 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] Compiler question
On Wed, Apr 27, 2016 at 01:52:24PM -0600, Jerry Jackson wrote: > I'd really be interested in how the two forms look when they've both been > reduced to some canonical internal format. You can use `raco expand` the result after macro expansion, and `raco decompile` to look at the result of decompiling the bytecode. If I understand correctly, the latter may include some optimizations, but most optimizations are done by the JIT compiler. E.g. > raco expand test.rkt | less > raco make test.rkt > raco decompile test.rkt | less -- William J. Bowman -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. signature.asc Description: PGP signature
Re: [racket-users] Compiler question
I appreciate the responses; at this point, however, I'm trying to figure out what to do with my intuition. If those two pieces of code don't compile to the same thing, I'm not sure how I should approach code style. I tend to favor ((if x y z) foo) over (if x (y foo) (z foo)) because it avoids redundancy and localizes the choice. Apparently, that's a pessimising choice and I now don't feel like I have much intuition at all about how things will perform. Obviously, I can use profiling to track such things down but... I'd really be interested in how the two forms look when they've both been reduced to some canonical internal format. Thanks, --Jerry On Wed, Apr 27, 2016 at 8:49 AM, Vincent St-Amour < stamo...@eecs.northwestern.edu> wrote: > When you have a program that's surprisingly fast (or slow), you can use > the optimization coach in DrRacket (in the "view" menu) to see what > optimizations Racket applies to your code. > > For your program, the coach confirms Matthew's diagnosis that inlining > is what makes `fib2` faster. > > Vincent > > > On Wed, 27 Apr 2016 08:42:03 -0500, > Jerry Jackson wrote: > > > > Hello all, > > > > I was experimenting a bit yesterday and discovered something that > surprised me. Here are two fibonacci functions: > > > > (define fib1 > > (letrec ([aux (lambda (i n) > > (if (< n 2) > > 1 > > (+ (fib1 i (- n 2)) (fib1 i (- n 1)]) > > (let ([funs (vector aux aux)]) > > (lambda (index num) > > ((if (= index 0) aux (vector-ref funs index)) index num) > > > > (define fib2 > > (letrec ([aux (lambda (i n) > > (if (< n 2) > > 1 > > (+ (fib2 i (- n 2)) (fib2 i (- n 1)]) > > (let ([funs (vector aux aux)]) > > (lambda (index num) > > (if (= index 0) > > (aux index num) > > ((vector-ref funs index) index num)) > > > > I expected them to behave basically identically (in fact, I thought they > would probably generate the same code). However, that was not the case: > > > > > (time (fib1 0 40)) > > cpu time: 4490 real time: 4489 gc time: 0 > > 165580141 > > > (time (fib1 1 40)) > > cpu time: 5031 real time: 5027 gc time: 0 > > 165580141 > > > (time (fib2 0 40)) > > cpu time: 3042 real time: 3040 gc time: 0 > > 165580141 > > > (time (fib2 1 40)) > > cpu time: 5031 real time: 5027 gc time: 0 > > 165580141 > > > (time (fib1 0 40)) > > cpu time: 4535 real time: 4532 gc time: 0 > > 165580141 > > > (time (fib2 0 40)) > > cpu time: 3027 real time: 3025 gc time: 0 > > 165580141 > > > > > > > It looks like one of the functions is 1.5 times faster than the other > (in the i == 0 case). Any ideas as to why? > > > > Thanks, > > --Jerry Jackson > > > > -- > > 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] the right way to use `syntax-local-introduce`?
> On Apr 27, 2016, at 2:38 PM, Matthew Butterick wrote: > > For the first time, I used `syntax-local-introduce` to solve a problem. But I > don't understand whether I'm using it correctly or just relying on a spooky > side effect. (I did the read the docs, but I'm looking for a higher-level > "why this exists and what its idiomatic use is") > > The problem I had was how to make two macros cooperate: one macro defines a > variable, and another macro uses it. One can re-introduce the variable > unhygienically each time. Or, apparently, you can use > `syntax-local-introduce` once at the moment of binding. (Sample code below > shows these two options.) > > I understand that the two options are not the same in terms of the use site. > Introducing a binding unhygienically makes it available to other code at the > use site as if it had been defined there; `syntax-local-introduce` does not. > > I suppose I'm wondering if a) this "cooperation" among macros I'm enjoying is > simply a lucky side effect of both being in the same module Well, it's not even that. This doesn't work: (let () (define-sli-foo) (let () (invoke-sli-foo))) I had expected that changing invoke-sli-foo to this would help: (define-simple-macro (invoke-sli-foo) #:with sli-foo (syntax-local-introduce #'foo) (slo-foo)) But it didn't. Hm. Although this definition of invoke-sli-foo works with define-sli-foo: (which uses syntax-local-introduce) (define-simple-macro (invoke-sli-foo) #:with sli-foo (datum->syntax this-syntax 'foo) (sli-foo)) And it works with with and without that let. I'm not sure why (datum->syntax this-syntax 'foo) would work and (syntax-local-introduce #'foo) wouldn't. Alex Knauth > and thus sharing a 'local' environment into which the identifier is being > 'introduced', and if so b) there's a better way to go about this than > `syntax-local-introduce`. > > > > > > ; > #lang racket > (provide (all-defined-out)) > > (define-syntax (define-sli-foo stx) > (syntax-case stx () > [(_) > (with-syntax ([sli-foo (syntax-local-introduce #'foo)]) >#`(begin >(define (sli-foo) 'sli-worked)))])) > > (define-syntax-rule (invoke-sli-foo) > (foo)) > > (define-syntax (define-ds-foo stx) > (syntax-case stx () > [(_) > (with-syntax ([ds-foo (datum->syntax stx 'foo)]) >#`(begin >(define (ds-foo) 'ds-worked)))])) > > (define-syntax (invoke-ds-foo stx) > (syntax-case stx () > [(_) > (with-syntax ([ds-foo (datum->syntax stx 'foo)]) >#'(ds-foo))])) > > > (module+ test > (require rackunit) > (check-equal? >(let () > (define-sli-foo) > (invoke-sli-foo)) 'sli-worked) > (check-equal? >(let () > (define-ds-foo) > (invoke-ds-foo)) 'ds-worked)) -- 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] the right way to use `syntax-local-introduce`?
For the first time, I used `syntax-local-introduce` to solve a problem. But I don't understand whether I'm using it correctly or just relying on a spooky side effect. (I did the read the docs, but I'm looking for a higher-level "why this exists and what its idiomatic use is") The problem I had was how to make two macros cooperate: one macro defines a variable, and another macro uses it. One can re-introduce the variable unhygienically each time. Or, apparently, you can use `syntax-local-introduce` once at the moment of binding. (Sample code below shows these two options.) I understand that the two options are not the same in terms of the use site. Introducing a binding unhygienically makes it available to other code at the use site as if it had been defined there; `syntax-local-introduce` does not. I suppose I'm wondering if a) this "cooperation" among macros I'm enjoying is simply a lucky side effect of both being in the same module and thus sharing a 'local' environment into which the identifier is being 'introduced', and if so b) there's a better way to go about this than `syntax-local-introduce`. ; #lang racket (provide (all-defined-out)) (define-syntax (define-sli-foo stx) (syntax-case stx () [(_) (with-syntax ([sli-foo (syntax-local-introduce #'foo)]) #`(begin (define (sli-foo) 'sli-worked)))])) (define-syntax-rule (invoke-sli-foo) (foo)) (define-syntax (define-ds-foo stx) (syntax-case stx () [(_) (with-syntax ([ds-foo (datum->syntax stx 'foo)]) #`(begin (define (ds-foo) 'ds-worked)))])) (define-syntax (invoke-ds-foo stx) (syntax-case stx () [(_) (with-syntax ([ds-foo (datum->syntax stx 'foo)]) #'(ds-foo))])) (module+ test (require rackunit) (check-equal? (let () (define-sli-foo) (invoke-sli-foo)) 'sli-worked) (check-equal? (let () (define-ds-foo) (invoke-ds-foo)) 'ds-worked)) -- 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] why this error?
In addition to my previous mail: Did you notice that allDiff? is, or at least must be, symmetrical in its two arguments? That is (allDiff? list1 list2) always must return the same answer as (allDiff? list2 list1) Jos -Original Message- From: Jos Koot [mailto:jos.k...@gmail.com] Sent: miércoles, 27 de abril de 2016 17:39 To: 'Andreas Petrou'; 'Racket Users' Cc: 'Jos Koot' Subject: RE: [racket-users] why this error? I dont get the error when running your example. snip -- 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] why this error?
I dont get the error when running your example. Notice that your function (allDiff? '() '(1 2 3)) returns '() I suppose you want #t in this case. Why the line( if (null? (cdr list1)) ? Simpler is: (define (allDiff? list1 list2) (if (null? list1) #t (if (memq (car list1) list2) #f (allDiff? (cdr list1) list2 How about using cond in stead of if? (define (allDiff0? list1 list2) (cond ((null? list1)) ((memq (car list1) list2) #f) (else (allDiff0? (cdr list1) list2 Other simple versions: (define (allDiff1? list1 list2) (or (null? list1) (and (not (memq (car list1) list2)) (allDiff1? (cdr list1) list2 (define (allDiff2? list1 list2) (not (ormap (curryr memq list2) list1))) (define (allDiff3? list1 list2) (not (for/or ((a (in-list list1))) (memq a list2 (define (allDiff3a? list1 list2) (not (for/or ((a (in-list list1)) (b (in-list list2))) (or (memq a list2) (memq b list1) Or you can recur on both lists: (define (allDiff4? list1 list2) (or (null? list1) (null? list2) (and (not (memq (car list1) list2)) (not (memq (car list2) list1)) (allDiff4? (cdr list1) (cdr list2) And two very odd versions ;) (define (allDiff5? list1 list2) (define a (remove-duplicates list1 eq?)) (define b (remove-duplicates list2 eq?)) (= (length (remove-duplicates (append list1 list2) eq?)) (+ (length a) (length b (define (allDiff6? list1 list2) ; This version assumes the lists not to contain #f (define a (remove-duplicates list1 eq?)) (define b (remove-duplicates list2 eq?)) (not (check-duplicates (append a b) eq?))) Jos -Original Message- From: racket-users@googlegroups.com [mailto:racket-users@googlegroups.com] On Behalf Of Andreas Petrou Sent: miércoles, 27 de abril de 2016 2:39 To: Racket Users Subject: [racket-users] why this error? My code is here:) ;3.) A function called allDiff? that takes as parameters two lists. The function returns #t if none of the elements in the first list can be found in the second ( define (allDiff? list1 list2) ( if (null? list1) '() ( if (null? (cdr list1)) (if (memq (car list1) list2) #f #t) (if (memq (car list1) list2) #f (allDiff? (cdr list1) list2)) ) ) ) See this error. Please Help list1: undefined; cannot reference an identifier before its definition -- 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] As clean as possible in a dirty macro
On Wednesday, April 27, 2016 at 8:55:29 AM UTC-4, Alex Knauth wrote: > I'm not sure if this is what you wanted, but here's a version of your monad > file with much less weird macro stuff. It used syntax-local-introduce in two > places right next to each other, and it doesn't use datum->syntax, > syntax->datum, or format-id anywhere. It also uses functions instead of > chained splicing-let-syntax forms to make monad implementations based on > other monad implementations. Our original implementation is almost identical to this. It assumes a fixed set of effects for all monads, each of which needs to be explicitly defined and lifted in the macro definition. It's also a bit limiting in the type of effects transformers can define (defining a lazy stream transformer with just functions is a pain). The expansion-time definitions also open the door for algebraic simplifications or partial evaluation down the line. I don't think I can use `syntax/loc' for dynamic identifiers (and still need `format-id', `syntax->datum', and `datum->syntax'). The only other weird macro stuff (that I see) is my `define-as-syntax' and use of `syntax-local-value' to preserve the definition site's scope--if there's a more canonical way to do this I'm all ears. -- 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] Compiler question
When you have a program that's surprisingly fast (or slow), you can use the optimization coach in DrRacket (in the "view" menu) to see what optimizations Racket applies to your code. For your program, the coach confirms Matthew's diagnosis that inlining is what makes `fib2` faster. Vincent On Wed, 27 Apr 2016 08:42:03 -0500, Jerry Jackson wrote: > > Hello all, > > I was experimenting a bit yesterday and discovered something that surprised > me. Here are two fibonacci functions: > > (define fib1 > (letrec ([aux (lambda (i n) > (if (< n 2) > 1 > (+ (fib1 i (- n 2)) (fib1 i (- n 1)]) > (let ([funs (vector aux aux)]) > (lambda (index num) > ((if (= index 0) aux (vector-ref funs index)) index num) > > (define fib2 > (letrec ([aux (lambda (i n) > (if (< n 2) > 1 > (+ (fib2 i (- n 2)) (fib2 i (- n 1)]) > (let ([funs (vector aux aux)]) > (lambda (index num) > (if (= index 0) > (aux index num) > ((vector-ref funs index) index num)) > > I expected them to behave basically identically (in fact, I thought they > would probably generate the same code). However, that was not the case: > > > (time (fib1 0 40)) > cpu time: 4490 real time: 4489 gc time: 0 > 165580141 > > (time (fib1 1 40)) > cpu time: 5031 real time: 5027 gc time: 0 > 165580141 > > (time (fib2 0 40)) > cpu time: 3042 real time: 3040 gc time: 0 > 165580141 > > (time (fib2 1 40)) > cpu time: 5031 real time: 5027 gc time: 0 > 165580141 > > (time (fib1 0 40)) > cpu time: 4535 real time: 4532 gc time: 0 > 165580141 > > (time (fib2 0 40)) > cpu time: 3027 real time: 3025 gc time: 0 > 165580141 > > > > It looks like one of the functions is 1.5 times faster than the other (in the > i == 0 case). Any ideas as to why? > > Thanks, > --Jerry Jackson > > -- > 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] Compiler question
The compiler inlines the call to `aux` in `fib2` because that call is readily apparent. It's not so apparent in the other cases that the function `aux` is always called. At Wed, 27 Apr 2016 06:42:03 -0700 (PDT), Jerry Jackson wrote: > Hello all, > > I was experimenting a bit yesterday and discovered something that surprised > me. Here are two fibonacci functions: > > (define fib1 > (letrec ([aux (lambda (i n) > (if (< n 2) > 1 > (+ (fib1 i (- n 2)) (fib1 i (- n 1)]) > (let ([funs (vector aux aux)]) > (lambda (index num) > ((if (= index 0) aux (vector-ref funs index)) index num) > > (define fib2 > (letrec ([aux (lambda (i n) > (if (< n 2) > 1 > (+ (fib2 i (- n 2)) (fib2 i (- n 1)]) > (let ([funs (vector aux aux)]) > (lambda (index num) > (if (= index 0) > (aux index num) > ((vector-ref funs index) index num)) > > I expected them to behave basically identically (in fact, I thought they > would > probably generate the same code). However, that was not the case: > > > (time (fib1 0 40)) > cpu time: 4490 real time: 4489 gc time: 0 > 165580141 > > (time (fib1 1 40)) > cpu time: 5031 real time: 5027 gc time: 0 > 165580141 > > (time (fib2 0 40)) > cpu time: 3042 real time: 3040 gc time: 0 > 165580141 > > (time (fib2 1 40)) > cpu time: 5031 real time: 5027 gc time: 0 > 165580141 > > (time (fib1 0 40)) > cpu time: 4535 real time: 4532 gc time: 0 > 165580141 > > (time (fib2 0 40)) > cpu time: 3027 real time: 3025 gc time: 0 > 165580141 > > > > It looks like one of the functions is 1.5 times faster than the other (in the > i == 0 case). Any ideas as to why? > > Thanks, > --Jerry Jackson > > -- > 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] Compiler question
Hello all, I was experimenting a bit yesterday and discovered something that surprised me. Here are two fibonacci functions: (define fib1 (letrec ([aux (lambda (i n) (if (< n 2) 1 (+ (fib1 i (- n 2)) (fib1 i (- n 1)]) (let ([funs (vector aux aux)]) (lambda (index num) ((if (= index 0) aux (vector-ref funs index)) index num) (define fib2 (letrec ([aux (lambda (i n) (if (< n 2) 1 (+ (fib2 i (- n 2)) (fib2 i (- n 1)]) (let ([funs (vector aux aux)]) (lambda (index num) (if (= index 0) (aux index num) ((vector-ref funs index) index num)) I expected them to behave basically identically (in fact, I thought they would probably generate the same code). However, that was not the case: > (time (fib1 0 40)) cpu time: 4490 real time: 4489 gc time: 0 165580141 > (time (fib1 1 40)) cpu time: 5031 real time: 5027 gc time: 0 165580141 > (time (fib2 0 40)) cpu time: 3042 real time: 3040 gc time: 0 165580141 > (time (fib2 1 40)) cpu time: 5031 real time: 5027 gc time: 0 165580141 > (time (fib1 0 40)) cpu time: 4535 real time: 4532 gc time: 0 165580141 > (time (fib2 0 40)) cpu time: 3027 real time: 3025 gc time: 0 165580141 > It looks like one of the functions is 1.5 times faster than the other (in the i == 0 case). Any ideas as to why? Thanks, --Jerry Jackson -- 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] As clean as possible in a dirty macro
> On Apr 27, 2016, at 2:55 AM, Nicholas Labich wrote: > > Thanks for the feedback. Attached is the solution applied to my original > implementation (only 65loc, documented). A couple of interesting points: > > - My simplified example didn't show this, but I have to > `syntax-local-introduce' the identifiers recursively, else > references to symbol=? `let-syntax'-bound identifiers are > ambiguous. Each `returnₘ' reference can have at most one other > `returnₘ' identifier in scope. > - For the `syntax-local-introduce'd identifiers to be visible in the > body of the `splicing-let-syntax' [line 66], recursive calls to > `use-monad' have to be `local-expand'ed by hand. I suppose I could > recur over the stack from the top down, but I would need to > special-case the first iteration after MId deference, which seems > sloppier. > > If there are any fixes for this second point, I'd be interested to hear. For > now, this should be a good starting point. > > Nick I'm not sure if this is what you wanted, but here's a version of your monad file with much less weird macro stuff. It used syntax-local-introduce in two places right next to each other, and it doesn't use datum->syntax, syntax->datum, or format-id anywhere. It also uses functions instead of chained splicing-let-syntax forms to make monad implementations based on other monad implementations. -- 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. monad.rkt Description: Binary data Or do you really want it to do some specific thing with the syntax that this doesn't do? Alex Knauth -- 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.