<div dir="ltr"><div><span style="font-family:arial,sans-serif;font-size:13px">“don't forget:</span><br></div><span style="font-family:arial,sans-serif;font-size:13px">call-by-value! call-by-value!” somewhere early on.</span><div>
<span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">Don't feel bad, fellow i-wish-racket-was-as-awesome-as-haskell-ian, I submitted an incorrect bug report claiming something like</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px">(function-call (const (random))) wasn't passing different random values, where it was kindly pointed out that call-by-value insures it wouldn't.  There *is* lazy racket.  The issues you have with for/and, etc. is a fundamental issue with strict evaluation vs. either lazy evaluation or no evaluation (macros).  One cannot correctly short circuit out of a loop that's already preprocessed every possible result!</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">I had tried to implement Haskell's monoid type class (and type classes in general), but mappend doesn't work in a strict language. There's no way to pass the arguments to the Or monoid without evaluating them, and any macro/thunk-based solution has this restraint propagate outwards.  Anything calling mappend has to not evaluate its arguments either, or they will be pre-evaluated before being Or-mappended, e.g. mconcat.  Then I tried it in lazy racket and couldn't get the macros for the type classes to even compile.  Something about begin != lazybegin != begin-for-syntax != begin-for-lazy-syntax-but-itself-is-strict or who knows...</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">On the other hand, a few weeks ago I did ICFP 2007 contest for fun in Haskell.  It took me several hours to fix a "bug" (turned out to be a space leak) caused by laziness.  It turned out that my flood fill loop was thunk-ifying a tail recursive function that I had defined with an internal let.  Using a couple bang patterns changed a minute long wait for "out of memory" into an efficient loop.  In a real live contest or with real customers waiting, I imagine using a who-knows-what's-actually-happening-language carries considerable risk to the developer...</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">So there are tradeoffs.  To me, Haskell with its type system (and the desired overloading) and more uniform evaluation (always lazy instead of function vs. macro for things like and/or) is the "better" language, but to be honest I'm not sure I would want my life to depend on making software in it.  So I find myself using Racket a lot as a usually trustworthy alternative.  There have been a couple of literally unbelievable bugs, like in one case where opening a tab in DrRacket changes the results running a test module in another tab.</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><font face="arial, sans-serif">At present, my roommate and I are building side-by-side solutions in Visual Basic and Racket (RESPECTIVELY, thank you).  It's a front-end for a matlab simulation -- a simple GUI with few complications.  Since that's actually what basic is good at, the number of lines of code are actually almost the same, but each new feature I've added in about 1/3 the time, spending the other 2/3 debugging his:</font></div>
<div><span style="font-family:arial,sans-serif"><br></span></div><div><span style="font-family:arial,sans-serif">public sub function (byref dim integer sub1 as ref, byval integer(,) ref as mouseeventargs of systemeventhandler) as function as refdimval</span></div>
<div><span style="font-family:arial,sans-serif">   omgtherearesomanykeywordsandstuffthatare40characterslong = "string1"</span></div><div><span style="font-family:arial,sans-serif">   thisismakingmyeyesbleed = "string2"</span></div>
<div><span style="font-family:arial,sans-serif">   ...</span></div><div><span style="font-family:arial,sans-serif">   exit function return for</span></div><div><span style="font-family:arial,sans-serif">end sub function ref dim functionsub</span></div>
<div><span style="font-family:arial,sans-serif"><br></span></div><div>It takes an average of 15 keywords * 5 characters average = 75 characters to setup the definition of a function (I made that statistic up, but it's probably close).  Racket uses (define ()) = 11, Haskell uses "=" = 1.  So the winner is Haskell, at 1/75 the verbosity of basic!  What's worse, is because you *really* don't want to have to define a new function in basic, you avoid programming functionally!  So he has all kinds of global variables to save typing byref dim integer refval functionsub seriouslywtf end exit just to add 1 to something.  But he gets to drag controls around on the form, where there's almost no way to explicitly position things in Racket, and it has to be done with code.</div>
<div><br></div><div>So all 3 of these languages have strikes against them.  I would still vote in favor of Racket in very many situations.</div><div><br></div><div>Lastly, without meaning to be rude, as it's coming from the point of view of someone who's had similar issues, there's a degree of RTFM present.  I'll share one other story...in developing a game library for Racket, I ran into a mystery bug that I eventually realized seemed to be the fault of Racket and not me.  Despite repeatedly simplifying C code into basically just pure debug output, it still wasn't doing what it was supposed to...apparently the linked library wasn't even being loaded at all.  ...And it wasn't.  But upon scrolling through the FFI documentation, there was some little line like "btw DrRacket doesn't reload libraries when run is clicked, you have to restart DrRacket".  So technically it was my fault, but the documentation could benefit from some kind of "WARNING!" section on each or at least especially dangerous pages for such pitfalls.  Imagine if your car explodes if you have the break depressed while turning the AC dial.  Probably don't want that info on page 87 subsection a.1.c.  But since there's no way to anticipate all potential user bugs, it's not really the fault of the documentation writers either.  So who/what is at fault?  Why did it happen?  I would say the inefficiencies present in attempting to plow through new material at breakneck speed.  I was able to compute matrix multiplication in C wrapped with Racket in almost no development time at all, except the bug -- ***and I had to learn how to do it as I went along***.  With the internet and high powered computational devices, humans can learn or at least think they've learned and do more than they ever could in history.  I don't think we're smart enough to handle our own output sometimes.  My point is that, to some degree, I think some of the perceived issues you or I have with Racket is simply due to it being different (and very (as in "too" (but not with a negative connotation)) complex).  It's just *very* powerful stuff, and human's fuzzy way of thinking doesn't always mesh 1:1 with the 90 billion lines of precise under-the-hood code present.  It's not Haskell, and so the reaction is it's stupid because it's not Haskell, but it's intentionally *not* Haskell or it would be a useless clone.  So it's up to the user to learn it as Racket and not why-isn't-it-Haskell-Racket.  And thank god, because it would take 15 minutes to insert an impure debug statement.</div>
<div><br></div><div>By the way, speed is improved when using the "racket" command-line command as opposed to running in DrRacket for whatever reason, especially when using big numbers, by an astounding amount sometimes.  I myself recently learned that...</div>
</div>