
Why Go? Use Racket - brudgers
http://cxwangyi.wordpress.com/2012/07/22/why-go-use-racket/
======
mediocregopher
> But it is inefficient to pass an array or struct; instead, we should pass
> pointers to these types.

I feel like the author hasn't used go much. You almost never work with arrays
directly, you use slices, which CAN be efficiently passed around.

EDIT: Upon re-reading I think the author was making a point about the
consistency of go, and how different types have different behavior with
regards to pass-by-reference/copy. There's actually a pretty simple rule for
it:

If the variable is a primitive, or defined by the user, it is passed by copy
(ints, strings, structs, etc...). Everything else (compositional types like
slices and maps, and others like channels) are passed by reference.

The outlier are raw arrays, but again you don't ever actually use those, so
you can just ignore them.

~~~
NateDad
So... you have the right idea, but your statement about passing is technically
wrong.

Everything in Go is passed by copying its value.

However, slices, maps, channels, and interfaces all have small values, which
are just a pointer and some other small data (length, type, etc), so passing
them directly (rather than by pointer) is not a big deal.

------
neya
> the type system of Go is so complex;

For someone coming from a Scala background, I feel this statement is _absurd_.

One thing we are all forgetting here is that anyone can prove language X is
better than Y. But it's always wise to choose the best tool for the job (X is
better than Z in doing what exactly?).

Languages and frameworks are a personal preference. You choose them based on
their philosophises and if their philosophies resonate with yours.

After a certain point, language choices will no longer matter. Your end goal,
should be to get to this point, instead of fighting over them. Just my 2
cents.

~~~
mwcampbell
As long as we treat languages as personal preferences, the programming
community will remain deplorably divided. In order to join forces to work on
demanding projects, I think we need to agree on a relatively small number of
good-enough languages. To do this, we need objective criteria for choosing one
language that is good for a particular class of software.

~~~
dragonwriter
> As long as we treat languages as personal preferences, the programming
> community will remain deplorably divided.

Languages _are_ personal preferences; they certainly have objective
differences which have some effect on utility, but a substantial part of what
makes a language the best for a particular programmer for a particular purpose
is how well the the language matches the programmer's experience and patterns
of thought for addressing the problem domain. These are inherently subjective
factors.

> In order to join forces to work on demanding projects, I think we need to
> agree on a relatively small number of good-enough languages.

We may need to agree, for large projects that need to be integrated in such a
way that you can't use a mix of languages for different components, on as few
as _one_ language for a particular project, but that doesn't constrain the
number of languages we can have in the whole programming ecosystem (and,
indeed, restricting the domain of available languages would restrict the
development of new techniques and languages and the development of better
languages for new use case.)

> To do this, we need objective criteria for choosing one language that is
> good for a particular class of software.

This requires, obviously, the ability to objectively categorize software into
"classes" to apply the criteria. Since I think you are going to fall down hard
on that, I'm not really holding my breath to seeing your vision realized, even
if I thought it was a good thing.

------
yfefyf
Racket is not only a great language. It's also a great developing environment,
a great community.

And unlike most other languages, it's out of box support for Windows is
perfect.

~~~
6cxs2hd6
To be fair, maybe this blog post is getting more attention than the author
expected. Regardless, I don't think it makes a great case for "Why __? Use
Racket!".

The case I'd make: The shiny new feature X in today's fashionable new lang Y?
Racket probably does this, does it elegantly, and has done it for awhile.

CSP is just one example. It's great that Go is helping popularize it.

Also I'd headline it as, "Intrigued by __? Also try Racket!".

Racket draws on a lot of PL research (which is why it probably already has
feature X) but is also very practical. It's easy to install and use on all
platforms. There's also a wonderful community.

About the only thing it lacks is a BFD/cult leader phenom such as some
companies and langs have. ;)

~~~
yfefyf
Yeah. And Racket suits programmers of different levels well.

For beginners, it's an easy to learn language with an easy to setup
programming environment.

For advanced programmers, there're a lot of advanced features available as
6cxs2hd6 mentioned.

------
leokun
> the type system of Go is so complex;

Go's type system is not complex at all. What is complex about it? There is a
limited set of types, and they can have methods. You can define your own
types. What's so complex about that?

> programmers need to know all the details about the implementation of
> standard types, before they can use them correctly.

You should not have problem with knowing the details of the language or the
third party libraries you are using if you want to be a proficient engineer
builds stable, secure and easily-maintainable systems.

~~~
coldtea
> _You should not have problem with knowing the details of the language or the
> third party libraries you are using if you want to be a proficient engineer
> builds stable, secure and easily-maintainable systems._

What if you instead want/have to be a pragmatic programmer, you doesn't
"engineer stable, secure and easily-maintainable systems" with all the time of
the world available to him, but has to build something working adequate
enough, as quick as possible, warts and all?

You know, like 90% of early startup code out there, including companies that
sold for hundrends of millions.

~~~
asdasf
You are welcome to write shit code in go too, nothing is stopping you.

~~~
coldtea
Thanks, this thread needed a strawman.

~~~
asdasf
You don't need to thank me, I didn't help you write your post. Did you mean to
thank your caretaker?

------
jameskilton
Why do we keep playing this like a competition? I'm sure someone could put
together an equally valid post about why Go is "better" than Racket. It's
frustrating how so many people forget that we're all in this together, how
every language has it's pros and cons, and how our job is to pick the best
tool for the job.

~~~
weavie
I think it sums it up at the very last sentence, almost as if it isn't really
relevant :

"Racket programs build and run much slower than Go programs."

Edit: By this I meant to be agreeing with the above statement that someone
will come along and write a post about why Go is better - it's already been
done in this one post. Sorry for the misunderstanding..

Obviously, sometimes execution speed is important, and sometimes it isn't - it
depends on what you are trying to do.

~~~
brudgers
The author's postscript links to this follow-up blog post:

[http://cxwangyi.wordpress.com/2012/07/29/chinese-whispers-
in...](http://cxwangyi.wordpress.com/2012/07/29/chinese-whispers-in-racket-
and-go/)

To me, the speed at which the code executes is a second derivative problem -
this is to say that if a language gets version 0.1 deployed two months faster,
then it is faster in a more important sense. A hammer and screws is more
useful than a screwdriver and nails - intact it is more useful than a Phillips
screwdriver and slotted screws.

------
Touche
My problem with Racket is that it's startup time is slow. Because of that it
competes with Clojure, and Clojure is frankly just better. I would probably
use Racket if it started up instantly; could be great for cli programs. But
Chicken has a decent ecosystem and is blazing fast, so I use that.

------
irahul
The author has a follow-up post
[http://cxwangyi.wordpress.com/2012/07/29/chinese-whispers-
in...](http://cxwangyi.wordpress.com/2012/07/29/chinese-whispers-in-racket-
and-go/)

 _Each thread reads from the channel to its left and writes the processed
input into the channel to its right._

Except that the programs he posted are flowing the other way(start with
rightmost, read final value from leftmost). The implementation of the author's
wording needs a slight change.

Go implementation:

    
    
        package main
    
        import "fmt"
    
        func setup_channels(left chan int, num int) chan int {
            for i := 0; i < num; i++ {
                right := make(chan int)
                go func(left, right chan int) { right <- 1 + <-left }(left, right)
                left = right
            }
            return left
        }
    
        func main() {
            leftmost := make(chan int)
            rightmost := setup_channels(leftmost, 100000)
            leftmost <- 1
            fmt.Println(<-rightmost)
        }
    
    
    
    

Racket implementation:

    
    
        #lang racket
    
        (define (setup-channels left idx num)
        (if (>= idx num)
            left
            (let [(right (make-channel))]
            (thread (λ ()
                        (channel-put right (+ 1 (channel-get left)))))
            (setup-channels right (add1 idx) num))))
    
        (let* [(leftmost (make-channel))
            (rightmost (setup-channels leftmost 0 100000))]
        (channel-put leftmost 1)
        (channel-get rightmost))
    

I also don't understand why is he writing to the leftmost channel in a
separate thread. I don't think that's needed.

------
niuzeta
I'm very ignorant on the difference between the functional languages, but
could someone _please_ explain, apart from the implementation which affect the
performances, the actual difference between the languages? To me they all look
like LISP.

I feel like a non-linux user categorizing Debian, Ubuntu, Mint, Red Hat, and
so on altogether as 'Linux'; While he's not incorrect, there are subtle
difference that he's not seeing. It feels rather frustrating. I'm using
Racket(when I want to experiment in functional language) because that's what
I'm used to, but it would be great to hear _X and Y are different in ..._ than
_X is better than Y because..._

~~~
Mikeb85
Dunno, ML-based languages have a pretty different feel to Lisp. They're
compiled languages, have type inference, heavily rely on pattern matching,
type declarations. An example from OCaml's front page:

type tree = Leaf of int | Node of tree * tree

let rec exists_leaf test tree = match tree with | Leaf v -> test v | Node
(left, right) -> exists_leaf test left || exists_leaf test right

let has_even_leaf tree = exists_leaf (fun n -> n mod 2 = 0) tree

~~~
zhemao
Most LISP implementations also provide compilers. The difference is that ML
variants are statically typed, while LISPs are generally dynamically typed.

~~~
pmelendez
> "generally dynamically typed"

I appreciate the "generally" word here. Racket and Chicken Scheme for
instance, both provide statically type extensions.

~~~
asdasf
But they are essentially garbage are they not? Adding java-style static typing
is not helpful at all. The benefits of static typing are very much tied to the
power of the type system in question.

~~~
takikawa
Typed Racket definitely doesn't add a "Java-style static typing" system at
all. Its type system is quite specifically designed to accommodate the kinds
of programming idioms you find in Racket programs (via occurrence typing,
function intersection types, and so on), and comes with local type inference.

~~~
asdasf
I don't use racket obviously, but looking through the docs on typed racket it
certainly looks like it adds java-style static typing. Having crappy partial
type inference doesn't make the type system powerful or expressive, C# has
that too and it certainly falls into the java-style type system camp.

~~~
takikawa
> but looking through the docs on typed racket it certainly looks like it adds
> java-style static typing

It's unclear what you mean by "Java-style static typing" then, because the
Java type system and Typed Racket's type system are completely different.

One actually has local type inference (which is not "crappy" type inference
necessarily; HM-style type inference is notoriously brittle), the other
doesn't. One has nominal class types, the other has no class types (yet). One
has intersection types, occurrence typing, "true" union types, and so on,
while the other has none of those. One has bounded polymorphism, the other has
System F-like polymorphism. One of them has variable-arity polymorphism, while
the other doesn't. The list goes on.

In fact, aside from being explicitly typed, there are few _similarities_.

~~~
asdasf
>One actually has local type inference

Which is totally orthogonal to the power and expressiveness of the type
system. I specifically gave an example that C# also has crappy limited type
inference too, and is still java-style static typing.

>HM-style type inference is notoriously brittle

Yeah, obviously no languages could possibly exist that use it with no
problems.

>One has nominal class types, the other has no class types (yet)

What does being OO have to do with anything? I am talking about the
expressiveness of the type system. The amount of things you can express in the
type system.

>One has intersection types, occurrence typing, "true" union types

So racket has a partial implementation of ADTs? And that's it? Ok, you win,
racket has java + 0.1 level of static typing, hooray! The point is, using
static typing in racket gets you virtually nothing, because it is such a
primitive type system. Go use ML or haskell and then compare it to typed
racket.

------
JulianMorrison
If you do not comprehend the type system in your language, your program will
be inefficient garbage if it runs at all. This is true in Racket as much as in
Go.

And Racket's type system (being an expandable, routinely expanded language) is
much, much larger.

------
thraxil
How lightweight are Racket's threads? I'm curious if they're really
lightweight in the same way that goroutines are. Go's documentation states:
"It is practical to create hundreds of thousands of goroutines in the same
address space."

Is the same true for Racket threads? Or are they closer to "lightweight" green
threads in other languages. I'm genuinely curious. If they are really as
lightweight as goroutines, that should be publicized more heavily. If they're
not, then it's disingenuous to claim that Racket's CSP story is equivalent to
Go's.

------
pmelendez
I would imagine that Go has the advantage of being significantly faster than
Racket. Although if people still loves to do things in Ruby maybe performance
is less than a concern in web development.

~~~
bhauer
> _Although if people still loves to do things in Ruby maybe performance is
> less than a concern in web development._

As a user of web sites (and a web developer), I find it disappointing and
frustrating to use web sites designed by people who clearly have not made
performance a priority. So just as a tangential point: if you are one of those
web developers who loves doing things on slower platforms, believing that it's
just fine to disregard performance, please think of your users! We are the
ones who suffer! 250ms here, 500ms there, sometimes over 1,000ms before the
server responds with the first byte! It adds up to an annoying user
experience.

Among popular sites, those that are slow tend to really irk me, and I seek out
alternatives. For example, there is this very popular source code social
network site...

~~~
drdaeman
I believe, in most cases of those milliseconds amount to network and
database/storage latency, not site code's performance.

So it's just insignificant (performance-wise) whenever you write site in
carefully optimized C or just write some Ruby magic that performs, say, 100x
slower. 1ns vs 100ns is insignificant when it's your database that responds in
300ms.

~~~
TylerE
You couldn't be more wrong. PHP and Ruby page generation times can easily
exceed 1000ms if the programmer isn't careful. Nanoseconds is just rubbish.
Even the fastest template engines typically take on the order of a few ms.

~~~
bhauer
TylerE is correct.

Each application is its own unique snowflake, admittedly, but I encourage web
developers to profile their applications to understand where server time is
actually consumed. Furthermore, I implore you to realize that time spent in
the ORM is _not_ the same as time waiting for the database. If your profiler
conflates ORM machinations as database time, you are not seeing the correct
data.

Modern databases are extremely efficient at fetching data from well-indexed
tables. They are in many cases _not_ the bottleneck although conventional
wisdom would have you believe otherwise.

In our experience, slower platforms consume an impressively large amount of
time doing things unrelated to the actual database queries. Under load, the
database server can be nearly idle while the application server is falling
over itself in its slow ORM, its template engine, or helper functions.
Meanwhile, faster platforms mean faster frameworks, faster ORMs, and faster
templates. These platforms can easily saturate the Gigabit Ethernet connection
to their database server without the database server hiccuping.

------
pbnjay
> But we are not allowed to convert the interface into that type. Instead, we
> can convert it into a pointer to that type.

I don't quite follow this "problem" \- it sounds like a complaint about the
lack of generics. I haven't been programming in Go for long, but I found the
reflection system pretty easy to use and it basically allows you to do this.

Sure, it's not EXACTLY the same, but in what case do I actually need a float
or integer instead of an interface method that acts on them in the way I
expect?

------
programminggeek
I like racket and I've always wanted an excuse to use it, but the development
experience with go is very, very nice. Nice enough that I'm starting to reach
for go where I would reach for ruby most days. The racket experience seemed
pretty great, but go has me hooked. Fast compile, fast tests, fast startup,
binary deploys. The whole go experience seems fast, clean, and sane.

Is there a great reason to use racket instead of go?

------
dragonwriter
Racket threads (which are green threads hosted on the same native thread in
1:n model) are not really equivalent to Goroutines (which are green threads
hosted across a pool of native threads in an m:n model).

Racket has a richer set of concurrency/parallelism structures (threads,
futures, places, engines) than Go provides (goroutines). This is both a source
of power, and a source of cognitive overhead.

------
pjmlp
What?! If anything the type system is quite simple.

Probably only Oberon-7 strives to be simpler, from the current set of modern
languages.

~~~
xradionut
Correction: Oberon-07, which has so few users, I doubt it qualifies as valid
option.

~~~
pjmlp
> Correction: Oberon-07...

Right, I always forget the right naming. From the Oberon family, I prefer
Active Oberon anyway.

> .., which has so few users, I doubt it qualifies as valid option.

True, it is unfortunate that the whole Oberon ecosystem never left the
academia, except for a single digit set of companies that managed to make some
money out of it.

Still, it does count when discussing about language type systems.

~~~
xradionut
Since it was one of the very few semi-modern systems programming languages
other than C used to build an OS, I would love to see some form of Oberon gain
more nerd traction.

~~~
pjmlp
I was really into it, back when System Oberon was being actively developed.

My experience with it, made me a supporter of GC enabled systems programming
languages and OS made with them.

The other one I also played with was Modula-3.

Nowadays it seems even at ETHZ, Oberon does not get used that much, if at all
and they switched their focus to research based on .NET.

> I would love to see some form of Oberon gain more nerd traction.

I doubt it will ever get one, due to its Pascal syntax heritage, which many
don't like, specially the all caps for keywords.

Oh well, at least Go got some influence from it.

