Re: [racket-dev] Simple loop checking in beginner?
On Nov 10, 2010, at 10:40 AM, namekuseijin wrote: On Wed, Nov 10, 2010 at 12:13 AM, John Clements cleme...@brinckerhoff.org wrote: ;; NOW I'M A STUDENT: ;; only-long-strings : (listof string) - (listof string) ;; return a list containing the strings longer than 2 chars (define/noloop (only-long-strings l) (cond [(empty? l) empty] [else (cond [( 2 (string-length (first l))) (cons (first l) (only-long-strings (rest l)))] [else (only-long-strings l)])])) gosh, students do suck. I guess you teach them to use cond because it's a generalized if. But then they proceed to use it just like if: always two conditions per (verbose) cond! :p then again, may be someone who had previous exposure to lesser languages... Perhaps you should ask before you critique. We insist on this style: -- the outer cond corresponds to the structure of the data definition of the input -- the inner one signals decision relevant for the output (I would use an 'if' for the inner one, but over N years of programming as if a student might see my code one day, I have come to really, truly like the unconditional use of cond for the layout purpose) _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] Simple loop checking in beginner?
On Wed, Nov 10, 2010 at 10:40 AM, namekuseijin namekusei...@gmail.com wrote: On Wed, Nov 10, 2010 at 12:13 AM, John Clements cleme...@brinckerhoff.org wrote: ;; NOW I'M A STUDENT: ;; only-long-strings : (listof string) - (listof string) ;; return a list containing the strings longer than 2 chars (define/noloop (only-long-strings l) (cond [(empty? l) empty] [else (cond [( 2 (string-length (first l))) (cons (first l) (only-long-strings (rest l)))] [else (only-long-strings l)])])) gosh, students do suck. I guess you teach them to use cond because it's a generalized if. But then they proceed to use it just like if: always two conditions per (verbose) cond! :p I disagree - the outer `cond' has 2 clauses because it it processing a data definition - (listof string) - which has 2 clauses. The second `cond' clause, which processes conses, has a conditional as well, but there's certainly nothing wrong with having the structure of your program match the structure of your data, especially not for HtDP programs. -- sam th sa...@ccs.neu.edu _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] Simple loop checking in beginner?
I see the reasoning now, I apologize. It's a good choice for students, not so sure about ye old daily buggy sofware maintenance. OTOH, perhaps if this practice was widespread it would lead to less bugs or at least more maintenable software. At least for those aware of this idiom. On Wed, Nov 10, 2010 at 1:44 PM, Matthias Felleisen matth...@ccs.neu.edu wrote: On Nov 10, 2010, at 10:40 AM, namekuseijin wrote: On Wed, Nov 10, 2010 at 12:13 AM, John Clements cleme...@brinckerhoff.org wrote: ;; NOW I'M A STUDENT: ;; only-long-strings : (listof string) - (listof string) ;; return a list containing the strings longer than 2 chars (define/noloop (only-long-strings l) (cond [(empty? l) empty] [else (cond [( 2 (string-length (first l))) (cons (first l) (only-long-strings (rest l)))] [else (only-long-strings l)])])) gosh, students do suck. I guess you teach them to use cond because it's a generalized if. But then they proceed to use it just like if: always two conditions per (verbose) cond! :p then again, may be someone who had previous exposure to lesser languages... Perhaps you should ask before you critique. We insist on this style: -- the outer cond corresponds to the structure of the data definition of the input -- the inner one signals decision relevant for the output (I would use an 'if' for the inner one, but over N years of programming as if a student might see my code one day, I have come to really, truly like the unconditional use of cond for the layout purpose) _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] Simple loop checking in beginner?
The value in the large comes when the data structures are more complex (in the function below you'd use a loop or filter, of course). When they are larger, you can pinpoint where to change your function based on a change to your data definition. For example, consider writing an interpreter. Now imagine the language changes in some way -- you can read off where exactly to change the interpreter. Robby On Wed, Nov 10, 2010 at 10:02 AM, namekuseijin namekusei...@gmail.com wrote: I see the reasoning now, I apologize. It's a good choice for students, not so sure about ye old daily buggy sofware maintenance. OTOH, perhaps if this practice was widespread it would lead to less bugs or at least more maintenable software. At least for those aware of this idiom. On Wed, Nov 10, 2010 at 1:44 PM, Matthias Felleisen matth...@ccs.neu.edu wrote: On Nov 10, 2010, at 10:40 AM, namekuseijin wrote: On Wed, Nov 10, 2010 at 12:13 AM, John Clements cleme...@brinckerhoff.org wrote: ;; NOW I'M A STUDENT: ;; only-long-strings : (listof string) - (listof string) ;; return a list containing the strings longer than 2 chars (define/noloop (only-long-strings l) (cond [(empty? l) empty] [else (cond [( 2 (string-length (first l))) (cons (first l) (only-long-strings (rest l)))] [else (only-long-strings l)])])) gosh, students do suck. I guess you teach them to use cond because it's a generalized if. But then they proceed to use it just like if: always two conditions per (verbose) cond! :p then again, may be someone who had previous exposure to lesser languages... Perhaps you should ask before you critique. We insist on this style: -- the outer cond corresponds to the structure of the data definition of the input -- the inner one signals decision relevant for the output (I would use an 'if' for the inner one, but over N years of programming as if a student might see my code one day, I have come to really, truly like the unconditional use of cond for the layout purpose) _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] Simple loop checking in beginner?
A factor of 2.+. (We could provide a type system, take away recursion, and replace it with a structural induction form. It would be impossible to write infinite loops.) On Nov 10, 2010, at 12:41 PM, John Clements wrote: On Nov 10, 2010, at 6:50 AM, Matthias Felleisen wrote: Your reasoning is correct. What's the performance hit? In order to try it, I used the legendary 12.4.2, and... uh, it seg faulted. Okay, I submitted a bug report on that. Moving right along: Testing in the simplest way, here's what I got for permute of size 9: Debugging enabled, no loop protection: cpu time: 2520 real time: 2539 gc time: 1554 cpu time: 1504 real time: 1523 gc time: 542 cpu time: 1515 real time: 1534 gc time: 552 Debugging enabled, with loop protection: cpu time: 4496 real time: 4532 gc time: 1940 cpu time: 3653 real time: 3694 gc time: 1079 cpu time: 3692 real time: 3730 gc time: 1112 Debugging disabled, no loop protection: cpu time: 2181 real time: 2200 gc time: 1651 cpu time: 1132 real time: 1152 gc time: 597 cpu time: 1143 real time: 1163 gc time: 603 Debugging disabled, with loop protection: cpu time: 3458 real time: 3494 gc time: 2007 cpu time: 2434 real time: 2471 gc time: 972 cpu time: 2424 real time: 2461 gc time: 1001 ... so it's quite a bit slower. Note that a whole bunch of this slowdown in the debugging enabled category is presumably due to the errortrace annotation of the macro expansion. I'm guessing that folding this into the errortrace expansion would reduce its overhead quite a bit. John _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] Simple loop checking in beginner?
HtDP in Coq? Hadn't thought of of that before... On Wed, Nov 10, 2010 at 1:26 PM, Matthias Felleisen matth...@ccs.neu.edu wrote: A factor of 2.+. (We could provide a type system, take away recursion, and replace it with a structural induction form. It would be impossible to write infinite loops.) On Nov 10, 2010, at 12:41 PM, John Clements wrote: On Nov 10, 2010, at 6:50 AM, Matthias Felleisen wrote: Your reasoning is correct. What's the performance hit? In order to try it, I used the legendary 12.4.2, and... uh, it seg faulted. Okay, I submitted a bug report on that. Moving right along: Testing in the simplest way, here's what I got for permute of size 9: Debugging enabled, no loop protection: cpu time: 2520 real time: 2539 gc time: 1554 cpu time: 1504 real time: 1523 gc time: 542 cpu time: 1515 real time: 1534 gc time: 552 Debugging enabled, with loop protection: cpu time: 4496 real time: 4532 gc time: 1940 cpu time: 3653 real time: 3694 gc time: 1079 cpu time: 3692 real time: 3730 gc time: 1112 Debugging disabled, no loop protection: cpu time: 2181 real time: 2200 gc time: 1651 cpu time: 1132 real time: 1152 gc time: 597 cpu time: 1143 real time: 1163 gc time: 603 Debugging disabled, with loop protection: cpu time: 3458 real time: 3494 gc time: 2007 cpu time: 2434 real time: 2471 gc time: 972 cpu time: 2424 real time: 2461 gc time: 1001 ... so it's quite a bit slower. Note that a whole bunch of this slowdown in the debugging enabled category is presumably due to the errortrace annotation of the macro expansion. I'm guessing that folding this into the errortrace expansion would reduce its overhead quite a bit. John _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
[racket-dev] Simple loop checking in beginner?
Here's a simple macro that prevents same-argument recursive calls (including non-tail ones). It's illustrated by a student function that made a teeny mistake which would result in looping forever, but (using this macro) instead signals an error. To the best of my limited knowledge, beginner is purely functional aside from the use of the test functions, right? So any recursive call with eq? args is guaranteed to loop forever, right? Hmm... well, I suppose there's (random)... It seems to me that a macro like this one (or even complete memoization) could potentially reduce student frustration, and would not prevent students from writing the programs that they wanted to. No? John Clements #lang racket (require rackunit) (define-syntax (define/noloop stx) (syntax-case stx () [(_ (funname arg ...) body ...) #`(define funname (let () (define fresh-key (gensym 'funname)) (define (funname arg ...) (let* ([most-recent-args (continuation-mark-set-first #f fresh-key)] [these-args (list arg ...)]) (when (and most-recent-args (= (length these-args) (length most-recent-args)) (andmap eq? these-args most-recent-args)) (error 'funname recursive call with identical arguments ~s is guaranteed to run forever. these-args)) (with-continuation-mark fresh-key these-args body ...))) funname))])) ;; NOW I'M A STUDENT: ;; only-long-strings : (listof string) - (listof string) ;; return a list containing the strings longer than 2 chars (define/noloop (only-long-strings l) (cond [(empty? l) empty] [else (cond [( 2 (string-length (first l))) (cons (first l) (only-long-strings (rest l)))] [else (only-long-strings l)])])) (check-equal? (only-long-strings (cons abc (cons de (cons fgh empty (cons abc (cons fgh empty))) smime.p7s Description: S/MIME cryptographic signature _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev