Re: [racket-users] for/stream and values
I just created a package that helps creating a stream of multiple values a couple of weeks ago. You might find it useful: https://docs.racket-lang.org/stream-values/ On Sat, May 2, 2020 at 3:38 PM Yury Bulka wrote: > (sorry for the typos - obviously, it should be racket/stream) > > -- > Yury Bulka > https://mamot.fr/@setthemfree > #NotOnFacebook > > > > Yury Bulka writes: > > > Hello everyone, > > > > I have a question about creating a steam that yields multiple values on > > each iteration. Given something like: > > > > (require racket/strema) > > > > (define my-stream (for/stream ([i (in-range 1 10)]) > > (values "hi" i))) > > > > When I'm trying to: > > > > (let-values ([(a b) (stream-ref my-stream 0)]) > > (printf "~v: ~v" a b)) > > > > I'm getting: > > > > ; result arity mismatch; > > ; expected number of values not received > > ; expected: 1 > > ; received: 2 > > ; values...: > > ;"hi" > > ;2 > > ; Context: > > ; > /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 > > > > Similarly: > > > > (for ([(a b) my-stream]) > > (printf "~v: ~v" a b)) > > > > leads to: > > > > ; result arity mismatch; > > ; expected number of values not received > > ; expected: 1 > > ; received: 2 > > ; values...: > > ;"hi" > > ;1 > > ; Context: > > ; tcp-accepted:1:1 for-loop > > ; top-level:1:1 [running body] > > ; > /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 > > > > Documentation on stream-ref specifically mentions that it can have > > multiple values: > > > https://docs.racket-lang.org/reference/streams.html?q=stream-ref#%28def._%28%28lib._racket%2Fstream..rkt%29._stream-ref%29%29 > > > > What am I doing wrong here? > > > > P.S. The context is that I'm trying to create a function that would > > return results from an API as a stream that can be iterated with the for > > family of forms, and would yield multiple values per iteration. > > > > -- > > Yury Bulka > > https://mamot.fr/@setthemfree > > #NotOnFacebook > > -- > 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/87ees2nerz.fsf%40privacyrequired.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/CADcuegvfgFo1SPQq6Dh7ncrgCpHDWFBArCSf99WHkOcY5Jjv1A%40mail.gmail.com.
Re: [racket-users] for/stream and values
(sorry for the typos - obviously, it should be racket/stream) -- Yury Bulka https://mamot.fr/@setthemfree #NotOnFacebook Yury Bulka writes: > Hello everyone, > > I have a question about creating a steam that yields multiple values on > each iteration. Given something like: > > (require racket/strema) > > (define my-stream (for/stream ([i (in-range 1 10)]) > (values "hi" i))) > > When I'm trying to: > > (let-values ([(a b) (stream-ref my-stream 0)]) > (printf "~v: ~v" a b)) > > I'm getting: > > ; result arity mismatch; > ; expected number of values not received > ; expected: 1 > ; received: 2 > ; values...: > ;"hi" > ;2 > ; Context: > ; > /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 > > Similarly: > > (for ([(a b) my-stream]) > (printf "~v: ~v" a b)) > > leads to: > > ; result arity mismatch; > ; expected number of values not received > ; expected: 1 > ; received: 2 > ; values...: > ;"hi" > ;1 > ; Context: > ; tcp-accepted:1:1 for-loop > ; top-level:1:1 [running body] > ; > /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 > > Documentation on stream-ref specifically mentions that it can have > multiple values: > https://docs.racket-lang.org/reference/streams.html?q=stream-ref#%28def._%28%28lib._racket%2Fstream..rkt%29._stream-ref%29%29 > > What am I doing wrong here? > > P.S. The context is that I'm trying to create a function that would > return results from an API as a stream that can be iterated with the for > family of forms, and would yield multiple values per iteration. > > -- > Yury Bulka > https://mamot.fr/@setthemfree > #NotOnFacebook -- 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/87ees2nerz.fsf%40privacyrequired.com.
[racket-users] for/stream and values
Hello everyone, I have a question about creating a steam that yields multiple values on each iteration. Given something like: (require racket/strema) (define my-stream (for/stream ([i (in-range 1 10)]) (values "hi" i))) When I'm trying to: (let-values ([(a b) (stream-ref my-stream 0)]) (printf "~v: ~v" a b)) I'm getting: ; result arity mismatch; ; expected number of values not received ; expected: 1 ; received: 2 ; values...: ;"hi" ;2 ; Context: ; /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 Similarly: (for ([(a b) my-stream]) (printf "~v: ~v" a b)) leads to: ; result arity mismatch; ; expected number of values not received ; expected: 1 ; received: 2 ; values...: ;"hi" ;1 ; Context: ; tcp-accepted:1:1 for-loop ; top-level:1:1 [running body] ; /nix/store/z4mpvw1p6whq454lmjshbdr6472sdbr3-racket-7.6/share/racket/collects/racket/repl.rkt:11:26 Documentation on stream-ref specifically mentions that it can have multiple values: https://docs.racket-lang.org/reference/streams.html?q=stream-ref#%28def._%28%28lib._racket%2Fstream..rkt%29._stream-ref%29%29 What am I doing wrong here? P.S. The context is that I'm trying to create a function that would return results from an API as a stream that can be iterated with the for family of forms, and would yield multiple values per iteration. -- Yury Bulka https://mamot.fr/@setthemfree #NotOnFacebook -- 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/87ftcineuk.fsf%40privacyrequired.com.
[racket-users] Racket v7.7
Racket version 7.7 is now available from https://racket-lang.org/ * Racket CS remains ready for production use---thanks to those who have been putting it into practice to help iron out the remaining kinks---and it now supports a C API for embedding into other applications. See the "Inside: Racket" documentation for details. * Racket CS uses a new HAMT implementation, dramatically reducing the memory required for immutable hash tables. * Optimizations to the Racket CS compiler result in a code size savings of approximately 20%. * GC callbacks are reliably called on major collections in Racket CS. Also, garbage collection is 10-20% faster. * DrRacket can recover much more quickly from errors involving large stack traces. * DrRacket now supports the use of the keyboard in the macOS Catalina "Open File" dialog. * The net/http-client collection supports the 'deflate' content encoding. * The `call-in-continuation` function (like Marc Feeley's `continuation-graft`) simplifies certain `call/cc` patterns by calling a thunk in a restored continuation. * The `call-with-current-language` form allows more reliable tests for language level code. * Use of the Cairo library can be multi-threaded. * Improved documentation! * Many bug fixes! The following people contributed to this release: Alexander Shopov, Ben Greenman, Benjamin Yeung, Brian Adkins, Brian Wignall, Chongkai Zhu, Craig Ferry, David Florness, Fred Fu, Greg Hendershott, Gustavo Massaccesi, Ilnar Salimzianov, Jack Firth, James Bornholt, Jay McCarthy, Jens Axel Søgaard, Jesse Alama, John Clements, Jon Zeppieri, Kartik Singhal, Laurent Orseau, Leo Shen, Luka Hadži-Đokić, Matthew Butterick, Matthew Flatt, Matthias Felleisen, Mike Sperber, Noah W M, Paulo Matos, Philip McGrath, Philippe Meunier, Ricardo Herdt, Robby Findler, Ryan Culpepper, Sam Tobin-Hochstadt, Sorawee Porncharoenwase, Spencer Florence, Stephen Chang, Syntacticlosure, Thaddäus Töppen, Tom Gillespie, Xu Chunyang, ZHUO Qingliang, kryptine, mehlon, muzimuzhi, redwyn, and Štěpán Němec Feedback Welcome -- 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/10eebecc-dd92-4f39-97ce-168bfa9e7ea1%40mtasv.net.
Re: [racket-users] Reducing parentheses without language damage.
Quick question: Would it better if this discussion happened over at https://github.com/racket/rhombus-brainstorming/blob/master/resources/goals.md or on the Racket Slack #rhombus channel? I’m aware that email and slack is a bit ephemeral - it is probably a good idea to turn any proposals into RFC’s or issues at https://github.com/racket/rhombus-brainstorming - so they are not lost. Kind regards Stephen -- 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/277b6aa7-f44c-45a1-917a-e9c5340473fc%40googlegroups.com.
Re: [racket-users] Re: Should I stop sending packages to the catalog?
Sage Gerard writes: > As long as I don't have to keep reorganizing my code to accommodate > the tooling, then it's a night and day improvement. Would you mind > terribly if I worked with you? I was mulling over this myself in the > dev list, but I am happy to aid any existing effort. I'd appreciate it! Let's sync up on Slack. -- 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/m2ees2mkvs.fsf%40192.168.0.142.
[racket-users] Script of the day! (2-May-2020)
> Script of the day: Have a Menu that displays all open tabs in DrRacket. > (Currently, DrRacket displays only the first 10). > > How to install: Click on Scripts | Manage scripts | New script... > Enter "All tabs" (a new script opens filled with a template. > > Replace the template with the code below. Save the file. > > Click on Scripts | All tabs. A new menu "All tabs" appears in DrRacket! (Via slack courtesy of Laurent) https://gist.github.com/Metaxal/cfe71127092d2ec95013cc81a5b88cd6 -- 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/49f6b54b-e518-4a54-b998-6a0c0ad91175%40googlegroups.com.
Re: [racket-users] Futures + threads SIGSEGV
Hi Sam, On 02. 05. 20 14:26, Sam Tobin-Hochstadt wrote: > I successfully reproduced this on the first try, which is good. Here's > my debugging advice (I'm also looking at it): > > 1. To use a binary with debugging symbols, use > `racket/src/build/racket/racket3m` from the checkout of the Racket > repository that you built. > 2. When running racket in GDB, there are lots of segfaults because of > the GC; you'll want to use `handle SIGSEGV nostop noprint` > 3. It may not work for this situation because of parallelism, but if > you can reproduce the bug using `rr` [1] it will be almost infinitely > easier to find and fix. thanks for the hints and also thanks for opening the Github issue for that. I'll try to post my results (if any) there. > > I'm also curious about your experience with Racket CS and futures. > It's unlikely to have the _same_ bugs, but it would be good to find > the ones there are. :) This is going to be a really hard one. With all the tricks I learned during past weeks, I get almost 400 frames per second with my experiment using 3m and unsafe operations. Without unsafe operations it goes down to 300 and without unsafe operations and with the de-optimized flip function as shown in the example + set-argb-pixels, I am at about 50 fps (that is presumably a completely "safe" version without relying on my bounds and type checking). With CS, I am unable to get quickly working anything else than the de-optimized version with set-argb-pixels and I am at about 5 fps. Also, the thread scheduling is "interesting" at best. I am postponing the work on that - I sort of assume, that it can take another few weeks to understand how to properly use all the fixnum/flonum related stuff with CS. Thanks again! Dominik > > [1] https://rr-project.org > > On Sat, May 2, 2020 at 7:56 AM Dominik Pantůček > wrote: >> >> Hello fellow Racketeers, >> >> during my research into how Racket can be used as generic software >> rendering platform, I've hit some limits of Racket's (native) thread >> handling. Once I started getting SIGSEGVs, I strongly suspected I am >> doing too much unsafe operations - and to be honest, that was true. >> There was one off-by-one memory access :). >> >> But that was easy to resolve - I just switched to safe/contracted >> versions of everything and found and fixed the bug. But I still got >> occasional SIGSEGV. So I dug even deeper (during last two months I've >> read most of the JIT inlining code) than before and noticed that the >> crashes disappear when I refrain from calling bytes-set! in parallel >> using futures. >> >> So I started creating a minimal-crashing-example. At first, I failed >> miserably. Just filling a byte array over and over again, I was unable >> to reproduce the crash. But then I realized, that in my application, >> threads come to play and that might be the case. And suddenly, creating >> MCE was really easy: >> >> Create new eventspace using parameterize/make-eventspace, put the actual >> code in application thread (thread ...) and make the main thread wait >> for this application thread using thread-wait. Before starting the >> application thread, I create a simple window, bitmap and a canvas, that >> I keep redrawing using refresh-now after each iteration. Funny thing is, >> now it keeps crashing even without actually modifying the bitmap in >> question. All I need to do is to mess with some byte array in 8 threads. >> Sometimes it takes a minute on my computer before it crashes, sometimes >> it needs more, but it eventually crashes pretty consistently. >> >> And it is just 60 lines of code: >> >> #lang racket/gui >> >> (require racket/future racket/fixnum racket/cmdline) >> >> (define width 800) >> (define height 600) >> >> (define framebuffer (make-fxvector (* width height))) >> (define pixels (make-bytes (* width height 4))) >> >> (define max-depth 0) >> >> (command-line >> #:once-each >> (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth >> (string->number d >> >> (file-stream-buffer-mode (current-output-port) 'none) >> >> (parameterize ((current-eventspace (make-eventspace))) >> (define win (new frame% >>(label "test") >>(width width) >>(height height))) >> (define bmp (make-bitmap width height)) >> (define canvas (new canvas% >> (parent win) >> (paint-callback >>(λ (c dc) >> (send dc draw-bitmap bmp 0 0))) >> )) >> >> (define (single-run) >> (define (do-bflip start end (depth 0)) >> (cond ((fx< depth max-depth) >> (define cnt (fx- end start)) >> (define cnt2 (fxrshift cnt 1)) >> (define mid (fx+ start cnt2)) >> (let ((f (future >>(λ () >> (do-bflip start mid (fx+ depth 1)) >>(do-bflip mid end (fx+ depth 1)) >>
Re: [racket-users] Futures + threads SIGSEGV
I opened https://github.com/racket/racket/issues/3145 to avoid too much mailing list traffic, and posted a stack trace there. Sam On Sat, May 2, 2020 at 8:31 AM Matthew Flatt wrote: > > I wasn't able to produce a crash on my first try, but the Nth try > worked, so this is very helpful! > > I'm investigating, too... > > At Sat, 2 May 2020 08:26:10 -0400, Sam Tobin-Hochstadt wrote: > > I successfully reproduced this on the first try, which is good. Here's > > my debugging advice (I'm also looking at it): > > > > 1. To use a binary with debugging symbols, use > > `racket/src/build/racket/racket3m` from the checkout of the Racket > > repository that you built. > > 2. When running racket in GDB, there are lots of segfaults because of > > the GC; you'll want to use `handle SIGSEGV nostop noprint` > > 3. It may not work for this situation because of parallelism, but if > > you can reproduce the bug using `rr` [1] it will be almost infinitely > > easier to find and fix. > > > > I'm also curious about your experience with Racket CS and futures. > > It's unlikely to have the _same_ bugs, but it would be good to find > > the ones there are. :) > > > > [1] https://rr-project.org > > > > On Sat, May 2, 2020 at 7:56 AM Dominik Pantůček > > wrote: > > > > > > Hello fellow Racketeers, > > > > > > during my research into how Racket can be used as generic software > > > rendering platform, I've hit some limits of Racket's (native) thread > > > handling. Once I started getting SIGSEGVs, I strongly suspected I am > > > doing too much unsafe operations - and to be honest, that was true. > > > There was one off-by-one memory access :). > > > > > > But that was easy to resolve - I just switched to safe/contracted > > > versions of everything and found and fixed the bug. But I still got > > > occasional SIGSEGV. So I dug even deeper (during last two months I've > > > read most of the JIT inlining code) than before and noticed that the > > > crashes disappear when I refrain from calling bytes-set! in parallel > > > using futures. > > > > > > So I started creating a minimal-crashing-example. At first, I failed > > > miserably. Just filling a byte array over and over again, I was unable > > > to reproduce the crash. But then I realized, that in my application, > > > threads come to play and that might be the case. And suddenly, creating > > > MCE was really easy: > > > > > > Create new eventspace using parameterize/make-eventspace, put the actual > > > code in application thread (thread ...) and make the main thread wait > > > for this application thread using thread-wait. Before starting the > > > application thread, I create a simple window, bitmap and a canvas, that > > > I keep redrawing using refresh-now after each iteration. Funny thing is, > > > now it keeps crashing even without actually modifying the bitmap in > > > question. All I need to do is to mess with some byte array in 8 threads. > > > Sometimes it takes a minute on my computer before it crashes, sometimes > > > it needs more, but it eventually crashes pretty consistently. > > > > > > And it is just 60 lines of code: > > > > > > #lang racket/gui > > > > > > (require racket/future racket/fixnum racket/cmdline) > > > > > > (define width 800) > > > (define height 600) > > > > > > (define framebuffer (make-fxvector (* width height))) > > > (define pixels (make-bytes (* width height 4))) > > > > > > (define max-depth 0) > > > > > > (command-line > > > #:once-each > > > (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth > > > (string->number d > > > > > > (file-stream-buffer-mode (current-output-port) 'none) > > > > > > (parameterize ((current-eventspace (make-eventspace))) > > > (define win (new frame% > > >(label "test") > > >(width width) > > >(height height))) > > > (define bmp (make-bitmap width height)) > > > (define canvas (new canvas% > > > (parent win) > > > (paint-callback > > >(λ (c dc) > > > (send dc draw-bitmap bmp 0 0))) > > > )) > > > > > > (define (single-run) > > > (define (do-bflip start end (depth 0)) > > > (cond ((fx< depth max-depth) > > > (define cnt (fx- end start)) > > > (define cnt2 (fxrshift cnt 1)) > > > (define mid (fx+ start cnt2)) > > > (let ((f (future > > >(λ () > > > (do-bflip start mid (fx+ depth 1)) > > >(do-bflip mid end (fx+ depth 1)) > > >(touch f))) > > > (else > > > (for ((i (in-range start end))) > > >(define c (fxvector-ref framebuffer i)) > > >(bytes-set! pixels (+ (* i 4) 0) #xff) > > >(bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) > > > #xff)) > > >(bytes-set! pixels (+ (* i
Re: [racket-users] Futures + threads SIGSEGV
Hi Dominik, Ah that explains why I was getting an incorrect number of threads! I didn’t think about using future-visualizer, but I’ll give it a try. Thanks! Dex > On May 2, 2020, at 2:27 PM, Dominik Pantůček > wrote: > > Hi Dex, > >> On 02. 05. 20 14:10, Dexter Lagan wrote: >> Hello, >> >> I’ve been getting inconsistent results as well. A while ago I made a >> benchmark based on a parallel spectral norm computation. The benchmark >> works fine on Windows on most systems and uses all cores, but crashes >> randomly on other systems. I haven’t been able to figure out why. On >> Linux it doesn’t seem to use more than one core. I’d be interested to >> know if this is related. Here’s the benchmark code : >> >> https://github.com/DexterLagan/benchmark > > Beware that (processor-count) returns the number of HT-cores, so your > v1.3 is actually requesting twice the number of threads as there are > HTs. At least on Linux this is the case (checked right now). > > Interesting idea... 16 threads: > > $ time racket crash.rkt -d 4 > SIGSEGV MAPERR si_code 1 fault on addr (nil) > Aborted (core dumped) > > real6m37,579s > user32m55,192s > sys0m35,124s > > So that is consistent to what I see. > > Have you tried using future-visualizer[1] for checking why it uses only > single CPU thread? Last summer I spent quite some time with it to help > me find the right futures usage patterns that actually enable the > speculative computation in parallel. Usually if your code is too deep > and keeps allocating "something" each frame, it goes back to the runtime > thread for each allocation. > > > Cheers, > Dominik > > [1] https://docs.racket-lang.org/future-visualizer/index.html > >> >> Dex >> >>> On May 2, 2020, at 1:56 PM, Dominik Pantůček >>> wrote: >>> >>> Hello fellow Racketeers, >>> >>> during my research into how Racket can be used as generic software >>> rendering platform, I've hit some limits of Racket's (native) thread >>> handling. Once I started getting SIGSEGVs, I strongly suspected I am >>> doing too much unsafe operations - and to be honest, that was true. >>> There was one off-by-one memory access :). >>> >>> But that was easy to resolve - I just switched to safe/contracted >>> versions of everything and found and fixed the bug. But I still got >>> occasional SIGSEGV. So I dug even deeper (during last two months I've >>> read most of the JIT inlining code) than before and noticed that the >>> crashes disappear when I refrain from calling bytes-set! in parallel >>> using futures. >>> >>> So I started creating a minimal-crashing-example. At first, I failed >>> miserably. Just filling a byte array over and over again, I was unable >>> to reproduce the crash. But then I realized, that in my application, >>> threads come to play and that might be the case. And suddenly, creating >>> MCE was really easy: >>> >>> Create new eventspace using parameterize/make-eventspace, put the actual >>> code in application thread (thread ...) and make the main thread wait >>> for this application thread using thread-wait. Before starting the >>> application thread, I create a simple window, bitmap and a canvas, that >>> I keep redrawing using refresh-now after each iteration. Funny thing is, >>> now it keeps crashing even without actually modifying the bitmap in >>> question. All I need to do is to mess with some byte array in 8 threads. >>> Sometimes it takes a minute on my computer before it crashes, sometimes >>> it needs more, but it eventually crashes pretty consistently. >>> >>> And it is just 60 lines of code: >>> >>> #lang racket/gui >>> >>> (require racket/future racket/fixnum racket/cmdline) >>> >>> (define width 800) >>> (define height 600) >>> >>> (define framebuffer (make-fxvector (* width height))) >>> (define pixels (make-bytes (* width height 4))) >>> >>> (define max-depth 0) >>> >>> (command-line >>> #:once-each >>> (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth >>> (string->number d >>> >>> (file-stream-buffer-mode (current-output-port) 'none) >>> >>> (parameterize ((current-eventspace (make-eventspace))) >>> (define win (new frame% >>> (label "test") >>> (width width) >>> (height height))) >>> (define bmp (make-bitmap width height)) >>> (define canvas (new canvas% >>> (parent win) >>> (paint-callback >>> (λ (c dc) >>> (send dc draw-bitmap bmp 0 0))) >>> )) >>> >>> (define (single-run) >>>(define (do-bflip start end (depth 0)) >>> (cond ((fx< depth max-depth) >>> (define cnt (fx- end start)) >>> (define cnt2 (fxrshift cnt 1)) >>> (define mid (fx+ start cnt2)) >>> (let ((f (future >>> (λ () >>> (do-bflip start mid (fx+ depth 1)) >>> (do-bflip mid end (fx+
Re: [racket-users] Futures + threads SIGSEGV
I wasn't able to produce a crash on my first try, but the Nth try worked, so this is very helpful! I'm investigating, too... At Sat, 2 May 2020 08:26:10 -0400, Sam Tobin-Hochstadt wrote: > I successfully reproduced this on the first try, which is good. Here's > my debugging advice (I'm also looking at it): > > 1. To use a binary with debugging symbols, use > `racket/src/build/racket/racket3m` from the checkout of the Racket > repository that you built. > 2. When running racket in GDB, there are lots of segfaults because of > the GC; you'll want to use `handle SIGSEGV nostop noprint` > 3. It may not work for this situation because of parallelism, but if > you can reproduce the bug using `rr` [1] it will be almost infinitely > easier to find and fix. > > I'm also curious about your experience with Racket CS and futures. > It's unlikely to have the _same_ bugs, but it would be good to find > the ones there are. :) > > [1] https://rr-project.org > > On Sat, May 2, 2020 at 7:56 AM Dominik Pantůček > wrote: > > > > Hello fellow Racketeers, > > > > during my research into how Racket can be used as generic software > > rendering platform, I've hit some limits of Racket's (native) thread > > handling. Once I started getting SIGSEGVs, I strongly suspected I am > > doing too much unsafe operations - and to be honest, that was true. > > There was one off-by-one memory access :). > > > > But that was easy to resolve - I just switched to safe/contracted > > versions of everything and found and fixed the bug. But I still got > > occasional SIGSEGV. So I dug even deeper (during last two months I've > > read most of the JIT inlining code) than before and noticed that the > > crashes disappear when I refrain from calling bytes-set! in parallel > > using futures. > > > > So I started creating a minimal-crashing-example. At first, I failed > > miserably. Just filling a byte array over and over again, I was unable > > to reproduce the crash. But then I realized, that in my application, > > threads come to play and that might be the case. And suddenly, creating > > MCE was really easy: > > > > Create new eventspace using parameterize/make-eventspace, put the actual > > code in application thread (thread ...) and make the main thread wait > > for this application thread using thread-wait. Before starting the > > application thread, I create a simple window, bitmap and a canvas, that > > I keep redrawing using refresh-now after each iteration. Funny thing is, > > now it keeps crashing even without actually modifying the bitmap in > > question. All I need to do is to mess with some byte array in 8 threads. > > Sometimes it takes a minute on my computer before it crashes, sometimes > > it needs more, but it eventually crashes pretty consistently. > > > > And it is just 60 lines of code: > > > > #lang racket/gui > > > > (require racket/future racket/fixnum racket/cmdline) > > > > (define width 800) > > (define height 600) > > > > (define framebuffer (make-fxvector (* width height))) > > (define pixels (make-bytes (* width height 4))) > > > > (define max-depth 0) > > > > (command-line > > #:once-each > > (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth > > (string->number d > > > > (file-stream-buffer-mode (current-output-port) 'none) > > > > (parameterize ((current-eventspace (make-eventspace))) > > (define win (new frame% > >(label "test") > >(width width) > >(height height))) > > (define bmp (make-bitmap width height)) > > (define canvas (new canvas% > > (parent win) > > (paint-callback > >(λ (c dc) > > (send dc draw-bitmap bmp 0 0))) > > )) > > > > (define (single-run) > > (define (do-bflip start end (depth 0)) > > (cond ((fx< depth max-depth) > > (define cnt (fx- end start)) > > (define cnt2 (fxrshift cnt 1)) > > (define mid (fx+ start cnt2)) > > (let ((f (future > >(λ () > > (do-bflip start mid (fx+ depth 1)) > >(do-bflip mid end (fx+ depth 1)) > >(touch f))) > > (else > > (for ((i (in-range start end))) > >(define c (fxvector-ref framebuffer i)) > >(bytes-set! pixels (+ (* i 4) 0) #xff) > >(bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) > > #xff)) > >(bytes-set! pixels (+ (* i 4) 2) (fxand (fxrshift c 8) #xff)) > >(bytes-set! pixels (+ (* i 4) 3) (fxand c #xff)) > > (do-bflip 0 (* width height)) > > (send canvas refresh-now)) > > (send win show #t) > > > > (define appthread > > (thread > > (λ () > >(let loop () > > (single-run) > > (loop) > > (thread-wait appthread)) > > > > Note: the code is
Re: [racket-users] Futures + threads SIGSEGV
Hi Dex, On 02. 05. 20 14:10, Dexter Lagan wrote: > Hello, > > I’ve been getting inconsistent results as well. A while ago I made a > benchmark based on a parallel spectral norm computation. The benchmark > works fine on Windows on most systems and uses all cores, but crashes > randomly on other systems. I haven’t been able to figure out why. On > Linux it doesn’t seem to use more than one core. I’d be interested to > know if this is related. Here’s the benchmark code : > > https://github.com/DexterLagan/benchmark Beware that (processor-count) returns the number of HT-cores, so your v1.3 is actually requesting twice the number of threads as there are HTs. At least on Linux this is the case (checked right now). Interesting idea... 16 threads: $ time racket crash.rkt -d 4 SIGSEGV MAPERR si_code 1 fault on addr (nil) Aborted (core dumped) real6m37,579s user32m55,192s sys 0m35,124s So that is consistent to what I see. Have you tried using future-visualizer[1] for checking why it uses only single CPU thread? Last summer I spent quite some time with it to help me find the right futures usage patterns that actually enable the speculative computation in parallel. Usually if your code is too deep and keeps allocating "something" each frame, it goes back to the runtime thread for each allocation. Cheers, Dominik [1] https://docs.racket-lang.org/future-visualizer/index.html > > Dex > >> On May 2, 2020, at 1:56 PM, Dominik Pantůček >> wrote: >> >> Hello fellow Racketeers, >> >> during my research into how Racket can be used as generic software >> rendering platform, I've hit some limits of Racket's (native) thread >> handling. Once I started getting SIGSEGVs, I strongly suspected I am >> doing too much unsafe operations - and to be honest, that was true. >> There was one off-by-one memory access :). >> >> But that was easy to resolve - I just switched to safe/contracted >> versions of everything and found and fixed the bug. But I still got >> occasional SIGSEGV. So I dug even deeper (during last two months I've >> read most of the JIT inlining code) than before and noticed that the >> crashes disappear when I refrain from calling bytes-set! in parallel >> using futures. >> >> So I started creating a minimal-crashing-example. At first, I failed >> miserably. Just filling a byte array over and over again, I was unable >> to reproduce the crash. But then I realized, that in my application, >> threads come to play and that might be the case. And suddenly, creating >> MCE was really easy: >> >> Create new eventspace using parameterize/make-eventspace, put the actual >> code in application thread (thread ...) and make the main thread wait >> for this application thread using thread-wait. Before starting the >> application thread, I create a simple window, bitmap and a canvas, that >> I keep redrawing using refresh-now after each iteration. Funny thing is, >> now it keeps crashing even without actually modifying the bitmap in >> question. All I need to do is to mess with some byte array in 8 threads. >> Sometimes it takes a minute on my computer before it crashes, sometimes >> it needs more, but it eventually crashes pretty consistently. >> >> And it is just 60 lines of code: >> >> #lang racket/gui >> >> (require racket/future racket/fixnum racket/cmdline) >> >> (define width 800) >> (define height 600) >> >> (define framebuffer (make-fxvector (* width height))) >> (define pixels (make-bytes (* width height 4))) >> >> (define max-depth 0) >> >> (command-line >> #:once-each >> (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth >> (string->number d >> >> (file-stream-buffer-mode (current-output-port) 'none) >> >> (parameterize ((current-eventspace (make-eventspace))) >> (define win (new frame% >> (label "test") >> (width width) >> (height height))) >> (define bmp (make-bitmap width height)) >> (define canvas (new canvas% >> (parent win) >> (paint-callback >> (λ (c dc) >> (send dc draw-bitmap bmp 0 0))) >> )) >> >> (define (single-run) >> (define (do-bflip start end (depth 0)) >> (cond ((fx< depth max-depth) >> (define cnt (fx- end start)) >> (define cnt2 (fxrshift cnt 1)) >> (define mid (fx+ start cnt2)) >> (let ((f (future >> (λ () >> (do-bflip start mid (fx+ depth 1)) >> (do-bflip mid end (fx+ depth 1)) >> (touch f))) >> (else >> (for ((i (in-range start end))) >> (define c (fxvector-ref framebuffer i)) >> (bytes-set! pixels (+ (* i 4) 0) #xff) >> (bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) >> #xff)) >> (bytes-set! pixels (+ (* i 4) 2) (fxand (fxrshift c 8) >> #xff)) >>
Re: [racket-users] Futures + threads SIGSEGV
I successfully reproduced this on the first try, which is good. Here's my debugging advice (I'm also looking at it): 1. To use a binary with debugging symbols, use `racket/src/build/racket/racket3m` from the checkout of the Racket repository that you built. 2. When running racket in GDB, there are lots of segfaults because of the GC; you'll want to use `handle SIGSEGV nostop noprint` 3. It may not work for this situation because of parallelism, but if you can reproduce the bug using `rr` [1] it will be almost infinitely easier to find and fix. I'm also curious about your experience with Racket CS and futures. It's unlikely to have the _same_ bugs, but it would be good to find the ones there are. :) [1] https://rr-project.org On Sat, May 2, 2020 at 7:56 AM Dominik Pantůček wrote: > > Hello fellow Racketeers, > > during my research into how Racket can be used as generic software > rendering platform, I've hit some limits of Racket's (native) thread > handling. Once I started getting SIGSEGVs, I strongly suspected I am > doing too much unsafe operations - and to be honest, that was true. > There was one off-by-one memory access :). > > But that was easy to resolve - I just switched to safe/contracted > versions of everything and found and fixed the bug. But I still got > occasional SIGSEGV. So I dug even deeper (during last two months I've > read most of the JIT inlining code) than before and noticed that the > crashes disappear when I refrain from calling bytes-set! in parallel > using futures. > > So I started creating a minimal-crashing-example. At first, I failed > miserably. Just filling a byte array over and over again, I was unable > to reproduce the crash. But then I realized, that in my application, > threads come to play and that might be the case. And suddenly, creating > MCE was really easy: > > Create new eventspace using parameterize/make-eventspace, put the actual > code in application thread (thread ...) and make the main thread wait > for this application thread using thread-wait. Before starting the > application thread, I create a simple window, bitmap and a canvas, that > I keep redrawing using refresh-now after each iteration. Funny thing is, > now it keeps crashing even without actually modifying the bitmap in > question. All I need to do is to mess with some byte array in 8 threads. > Sometimes it takes a minute on my computer before it crashes, sometimes > it needs more, but it eventually crashes pretty consistently. > > And it is just 60 lines of code: > > #lang racket/gui > > (require racket/future racket/fixnum racket/cmdline) > > (define width 800) > (define height 600) > > (define framebuffer (make-fxvector (* width height))) > (define pixels (make-bytes (* width height 4))) > > (define max-depth 0) > > (command-line > #:once-each > (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth > (string->number d > > (file-stream-buffer-mode (current-output-port) 'none) > > (parameterize ((current-eventspace (make-eventspace))) > (define win (new frame% >(label "test") >(width width) >(height height))) > (define bmp (make-bitmap width height)) > (define canvas (new canvas% > (parent win) > (paint-callback >(λ (c dc) > (send dc draw-bitmap bmp 0 0))) > )) > > (define (single-run) > (define (do-bflip start end (depth 0)) > (cond ((fx< depth max-depth) > (define cnt (fx- end start)) > (define cnt2 (fxrshift cnt 1)) > (define mid (fx+ start cnt2)) > (let ((f (future >(λ () > (do-bflip start mid (fx+ depth 1)) >(do-bflip mid end (fx+ depth 1)) >(touch f))) > (else > (for ((i (in-range start end))) >(define c (fxvector-ref framebuffer i)) >(bytes-set! pixels (+ (* i 4) 0) #xff) >(bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) > #xff)) >(bytes-set! pixels (+ (* i 4) 2) (fxand (fxrshift c 8) #xff)) >(bytes-set! pixels (+ (* i 4) 3) (fxand c #xff)) > (do-bflip 0 (* width height)) > (send canvas refresh-now)) > (send win show #t) > > (define appthread > (thread > (λ () >(let loop () > (single-run) > (loop) > (thread-wait appthread)) > > Note: the code is deliberately de-optimized to highlight the problem. > Not even mentioning CPU cache coherence here > > Running this from command-line, I can adjust the number of threads. > Running with 8 threads: > > $ time racket crash.rkt -d 3 > SIGSEGV MAPERR si_code 1 fault on addr (nil) > Aborted (core dumped) > > real1m18,162s > user7m11,936s > sys 0m3,832s > $ time racket crash.rkt -d 3 > SIGSEGV MAPERR si_code 1 fault on
Re: [racket-users] Futures + threads SIGSEGV
Hello, I’ve been getting inconsistent results as well. A while ago I made a benchmark based on a parallel spectral norm computation. The benchmark works fine on Windows on most systems and uses all cores, but crashes randomly on other systems. I haven’t been able to figure out why. On Linux it doesn’t seem to use more than one core. I’d be interested to know if this is related. Here’s the benchmark code : https://github.com/DexterLagan/benchmark Dex > On May 2, 2020, at 1:56 PM, Dominik Pantůček > wrote: > > Hello fellow Racketeers, > > during my research into how Racket can be used as generic software > rendering platform, I've hit some limits of Racket's (native) thread > handling. Once I started getting SIGSEGVs, I strongly suspected I am > doing too much unsafe operations - and to be honest, that was true. > There was one off-by-one memory access :). > > But that was easy to resolve - I just switched to safe/contracted > versions of everything and found and fixed the bug. But I still got > occasional SIGSEGV. So I dug even deeper (during last two months I've > read most of the JIT inlining code) than before and noticed that the > crashes disappear when I refrain from calling bytes-set! in parallel > using futures. > > So I started creating a minimal-crashing-example. At first, I failed > miserably. Just filling a byte array over and over again, I was unable > to reproduce the crash. But then I realized, that in my application, > threads come to play and that might be the case. And suddenly, creating > MCE was really easy: > > Create new eventspace using parameterize/make-eventspace, put the actual > code in application thread (thread ...) and make the main thread wait > for this application thread using thread-wait. Before starting the > application thread, I create a simple window, bitmap and a canvas, that > I keep redrawing using refresh-now after each iteration. Funny thing is, > now it keeps crashing even without actually modifying the bitmap in > question. All I need to do is to mess with some byte array in 8 threads. > Sometimes it takes a minute on my computer before it crashes, sometimes > it needs more, but it eventually crashes pretty consistently. > > And it is just 60 lines of code: > > #lang racket/gui > > (require racket/future racket/fixnum racket/cmdline) > > (define width 800) > (define height 600) > > (define framebuffer (make-fxvector (* width height))) > (define pixels (make-bytes (* width height 4))) > > (define max-depth 0) > > (command-line > #:once-each > (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth > (string->number d > > (file-stream-buffer-mode (current-output-port) 'none) > > (parameterize ((current-eventspace (make-eventspace))) > (define win (new frame% > (label "test") > (width width) > (height height))) > (define bmp (make-bitmap width height)) > (define canvas (new canvas% > (parent win) > (paint-callback > (λ (c dc) > (send dc draw-bitmap bmp 0 0))) > )) > > (define (single-run) >(define (do-bflip start end (depth 0)) > (cond ((fx< depth max-depth) > (define cnt (fx- end start)) > (define cnt2 (fxrshift cnt 1)) > (define mid (fx+ start cnt2)) > (let ((f (future > (λ () > (do-bflip start mid (fx+ depth 1)) > (do-bflip mid end (fx+ depth 1)) > (touch f))) >(else > (for ((i (in-range start end))) > (define c (fxvector-ref framebuffer i)) > (bytes-set! pixels (+ (* i 4) 0) #xff) > (bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) > #xff)) > (bytes-set! pixels (+ (* i 4) 2) (fxand (fxrshift c 8) #xff)) > (bytes-set! pixels (+ (* i 4) 3) (fxand c #xff)) >(do-bflip 0 (* width height)) >(send canvas refresh-now)) > (send win show #t) > > (define appthread >(thread > (λ () > (let loop () > (single-run) > (loop) > (thread-wait appthread)) > > Note: the code is deliberately de-optimized to highlight the problem. > Not even mentioning CPU cache coherence here > > Running this from command-line, I can adjust the number of threads. > Running with 8 threads: > > $ time racket crash.rkt -d 3 > SIGSEGV MAPERR si_code 1 fault on addr (nil) > Aborted (core dumped) > > real1m18,162s > user7m11,936s > sys0m3,832s > $ time racket crash.rkt -d 3 > SIGSEGV MAPERR si_code 1 fault on addr (nil) > Aborted (core dumped) > > real3m44,005s > user20m10,920s > sys0m11,702s > $ time racket crash.rkt -d 3 > SIGSEGV MAPERR si_code 1 fault on addr (nil) > Aborted (core dumped) > > real2m1,650s > user10m58,392s > sys0m6,445s > $ time racket crash.rkt -d 3 >
[racket-users] Futures + threads SIGSEGV
Hello fellow Racketeers, during my research into how Racket can be used as generic software rendering platform, I've hit some limits of Racket's (native) thread handling. Once I started getting SIGSEGVs, I strongly suspected I am doing too much unsafe operations - and to be honest, that was true. There was one off-by-one memory access :). But that was easy to resolve - I just switched to safe/contracted versions of everything and found and fixed the bug. But I still got occasional SIGSEGV. So I dug even deeper (during last two months I've read most of the JIT inlining code) than before and noticed that the crashes disappear when I refrain from calling bytes-set! in parallel using futures. So I started creating a minimal-crashing-example. At first, I failed miserably. Just filling a byte array over and over again, I was unable to reproduce the crash. But then I realized, that in my application, threads come to play and that might be the case. And suddenly, creating MCE was really easy: Create new eventspace using parameterize/make-eventspace, put the actual code in application thread (thread ...) and make the main thread wait for this application thread using thread-wait. Before starting the application thread, I create a simple window, bitmap and a canvas, that I keep redrawing using refresh-now after each iteration. Funny thing is, now it keeps crashing even without actually modifying the bitmap in question. All I need to do is to mess with some byte array in 8 threads. Sometimes it takes a minute on my computer before it crashes, sometimes it needs more, but it eventually crashes pretty consistently. And it is just 60 lines of code: #lang racket/gui (require racket/future racket/fixnum racket/cmdline) (define width 800) (define height 600) (define framebuffer (make-fxvector (* width height))) (define pixels (make-bytes (* width height 4))) (define max-depth 0) (command-line #:once-each (("-d" "--depth") d "Futures binary partitioning depth" (set! max-depth (string->number d (file-stream-buffer-mode (current-output-port) 'none) (parameterize ((current-eventspace (make-eventspace))) (define win (new frame% (label "test") (width width) (height height))) (define bmp (make-bitmap width height)) (define canvas (new canvas% (parent win) (paint-callback (λ (c dc) (send dc draw-bitmap bmp 0 0))) )) (define (single-run) (define (do-bflip start end (depth 0)) (cond ((fx< depth max-depth) (define cnt (fx- end start)) (define cnt2 (fxrshift cnt 1)) (define mid (fx+ start cnt2)) (let ((f (future (λ () (do-bflip start mid (fx+ depth 1)) (do-bflip mid end (fx+ depth 1)) (touch f))) (else (for ((i (in-range start end))) (define c (fxvector-ref framebuffer i)) (bytes-set! pixels (+ (* i 4) 0) #xff) (bytes-set! pixels (+ (* i 4) 1) (fxand (fxrshift c 16) #xff)) (bytes-set! pixels (+ (* i 4) 2) (fxand (fxrshift c 8) #xff)) (bytes-set! pixels (+ (* i 4) 3) (fxand c #xff)) (do-bflip 0 (* width height)) (send canvas refresh-now)) (send win show #t) (define appthread (thread (λ () (let loop () (single-run) (loop) (thread-wait appthread)) Note: the code is deliberately de-optimized to highlight the problem. Not even mentioning CPU cache coherence here Running this from command-line, I can adjust the number of threads. Running with 8 threads: $ time racket crash.rkt -d 3 SIGSEGV MAPERR si_code 1 fault on addr (nil) Aborted (core dumped) real1m18,162s user7m11,936s sys 0m3,832s $ time racket crash.rkt -d 3 SIGSEGV MAPERR si_code 1 fault on addr (nil) Aborted (core dumped) real3m44,005s user20m10,920s sys 0m11,702s $ time racket crash.rkt -d 3 SIGSEGV MAPERR si_code 1 fault on addr (nil) Aborted (core dumped) real2m1,650s user10m58,392s sys 0m6,445s $ time racket crash.rkt -d 3 SIGSEGV MAPERR si_code 1 fault on addr (nil) Aborted (core dumped) real8m8,666s user45m52,359s sys 0m25,184s $ With 4 threads it didn't crash even after quite some time: $ time racket crash.rkt -d 2 ^Cuser break context...: "crash.rkt": [running body] temp35_0 for-loop run-module-instance! perform-require! real20m18,706s user61m38,546s sys 0m22,719s $ I'll re-run the 4-thread test overnight. What would be the best approach to debugging this issue? I assume I'll load the racket binary in gdb and see the stack traces at the moment of the crash, but that won't reveal the source of the problem (judging based on my previous experience of debugging heavily multi-threaded
Re: [racket-users] Reducing parentheses without language damage.
For the sake of discussion, here’s a long rant: I might have a very uninformed opinion here, but wouldn’t having significant white space and no scope-defining character amount to multiple spaces and line feeds being part of the syntax? The next best thing being, allowing semicolons in place of line feeds. I’m no language designer, so let me try to give you my perspective as an average programmer: I find editing Python and Haskell a pain, because of white spaces. I can’t count the times I got that dreaded ‘invalid indentation’ error, because I’m editing code with a different editor on a different system. I also had to reformat entire programs after somebody saved using the incorrect tab setting, and I avoid Python because of this. Yet I haven’t heard this complaint from Python programmers, so I always believed I was just too dumb. I haven’t seen a better solution than s-expr to make expressions and scope ultra-visible and easy to manipulate. Yet s-expressions still bring their own requirements for comfortable editing: most people still require a specialized editor or a plugin for lisps. I fact, is there any language that doesn’t require some sort of plugin or specialized editor to be attractive to new programmers? Thinking of it, isn’t the IDE almost as important as the syntax or the language these days? Some JavaScript programmers can’t work without VSCode, scope-sensitive autocomplete, a linter and god knows how many other plugins. PHP programmers also feel naked without a fancy IDE and a host of plugins. I keep hearing people complain about x or y language because it doesn’t have a good editor, IDE or plugin for VSCode. Globally, people use more and more tools to program in the same languages. That’s what turned me into a sort of ‘digital minimalist’. I take comfort in not being dependant on anything other than a compiler/interpreter and a simple editor I can whip out of any system in seconds. I think there’s value in reducing our dependencies, including on tools, editors, IDEs and plugins. That being said, I love DrRacket and its facilities, also because it’s self-contained and bundled with Racket. One less thing to install. These are the considerations I’d take in account when thinking of a new syntax. Still, like I said before, I’m excited by the fact that the Racket team is looking for a solution to this problem, and I’ll be the first to applaud a way to keep the next Racket expressive and powerful, while making it more attractive to people used to more familiar syntax. Parentheses are, and always will be a barrier to entry for potential Racket adopters, and this is no small matter. I think Julia is a good example of the right balance between simple, attractive syntax and power. Are there downsides to their approach? Cheers, Dex > On May 2, 2020, at 2:12 AM, George Neuner wrote: > > > On 5/1/2020 4:35 PM, Dexter Lagan wrote: >> Is there value in Rob Pike’s comment on avoiding significant white space >> in the Go language? >> >> “We have had extensive experience tracking down build and test failures >> caused by cross-language builds where a Python snippet embedded in another >> language, for instance through a SWIG invocation, is subtly and invisibly >> broken by a change in the indentation of the surrounding code.” — Rob Pike, >> 2012 > > I'm not really sure what Pike is getting at there: I haven't used SWIG > myself, but if I understand it correctly, Python code would have to be in a > module to be called from "other" language code. If so, I don't see how the > indentation of the "other" code could affect the Python. > > That aside: > > Even working only in Python, programmers routinely get tripped up by > copy/paste errors - so it is evident that indentation sensitivity is not any > real solution to scope related logic problems. It might [for some > definition] help newbies identify stupid errors, but I believe that even > moderately experienced programmers are more hindered than helped by it. > > >> I personally dislike white space and prefer either mustaches or >> parenthesis, just so I know my code will still work if line feeds are >> stripped somehow, or that some piece of code is embedded or quoted in >> another language, which is what I gather Rob was talking about. However, >> Haskell and Python people don’t seem to mind, and if it saves us more >> keystrokes while keeping expressiveness, why not? > > Well, few people use Haskell, so I would discount it as a data point. Even > so, one of the tutorials includes this interesting tidbit: > > With good text editor, programming is fun. Of course, you can get along with > simplistic > editor capable of just cut-n-paste, but good editor is capable of doing most > of the chores > for you, letting you concentrate on what you are writing. With respect to > programming > in Haskell, good text editor should have as much as possible of the following >