Python from Wise Guy's Viewpoint

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Fergus Henderson

    #106
    Re: Python from Wise Guy's Viewpoint

    Lulu of the Lotus-Eaters <mertz@gnosis.c x> writes:
    [color=blue]
    >Joachim Durchholz <joachim.durchh olz@web.de> writes:[color=green]
    >>My 100% subjective private study reveals not a single complaint about
    >>over-restrictive type systems in comp.lang.funct ional in the last 12
    >>months.[/color]
    >
    >I also read c.l.functional (albeit only lightly). In the last 12
    >months, I have encountered dozens of complaints about over-restrictive
    >type sytems in Haskell, OCaml, SML, etc.
    >
    >The trick is that these complaints are not phrased in precisely that
    >way. Rather, someone is trying to do some specific task, and has
    >difficulty arriving at a usable type needed in the task. Often posters
    >provide good answers--Durchholz included. But the underlying complaint
    >-really was- about the restrictiveness of the type system.[/color]

    Could you provide a link to an example of such a post?

    In my experience, people who have difficulties in getting their programs
    to typecheck usually have an inconsistent design, not a design which is
    consistent but which the type checker is too restrictive to support.

    --
    Fergus Henderson <fjh@cs.mu.oz.a u> | "I have always known that the pursuit
    The University of Melbourne | of excellence is a lethal habit"
    WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.

    Comment

    • Pascal Costanza

      #107
      Re: Python from Wise Guy's Viewpoint

      Marshall Spight wrote:
      [color=blue]
      > "Pascal Costanza" <costanza@web.d e> wrote in message news:bn7a3p$1h6 $1@newsreader2. netcologne.de.. .
      >[color=green]
      >>I wouldn't count the use of java.lang.Objec t as a case of dynamic
      >>typing. You need to explicitly cast objects of this type to some class
      >>in order to make useful method calls. You only do this to satisfy the
      >>static type system. (BTW, this is one of the sources for potential bugs
      >>that you don't have in a decent dynamically typed language.)[/color]
      >
      >
      > Huh? The explicit-downcast construct present in Java is the
      > programmer saying to the compiler: "trust me; you can accept
      > this type of parameter." In a dynamically-typed language, *every*
      > call is like this! So if this is a source of errors (which I believe it
      > is) then dynamically-typed languages have this potential source
      > of errors with every function call, vs. statically-typed languages
      > which have them only in those few cases where the programmer
      > explicitly puts them in.[/color]

      What can happen in Java is the following:

      - You might accidentally use the wrong class in a class cast.
      - For the method you try to call, there happens to be a method with the
      same name and signature in that class.

      In this situation, the static type system would be happy, but the code
      is buggy.

      In a decent dynamically typed language, you have proper name space
      management, so that a method cannot ever be defined for a class only by
      accident.

      (Indeed, Java uses types for many different unrelated things - in this
      case as a very weak name space mechanism.)


      Pascal

      Comment

      • Pascal Costanza

        #108
        Re: Python from Wise Guy's Viewpoint

        Ralph Becket wrote:
        [color=blue]
        > Pascal Costanza <costanza@web.d e> wrote in message news:<bn7a3p$1h 6$1@newsreader2 .netcologne.de> ...
        >[color=green]
        >>+ Design process: There are clear indications that processes like
        >>extreme programming work better than processes that require some kind of
        >>specificati on stage. Dynamic typing works better with XP than static
        >>typing because with dynamic typing you can write unit tests without
        >>having the need to immediately write appropriate target code.[/color]
        >
        >
        > This is utterly bogus. If you write unit tests beforehand, you are
        > already pre-specifying the interface that the code to be tested will
        > present.
        >
        > I fail to see how dynamic typing can confer any kind of advantage here.[/color]

        Read the literature on XP.
        [color=blue][color=green]
        >>+ Documentation: Comments are usually better for handling documentation.
        >>;) If you want your "comments" checked, you can add assertions.[/color]
        >
        >
        > Are you seriously claiming that concise, *automatically checked*
        > documentation (which is one function served by explicit type
        > declarations) is inferior to unchecked, ad hoc commenting?[/color]

        I am sorry, but in my book, assertions are automatically checked.
        [color=blue]
        > For one thing, type declarations *cannot* become out-of-date (as
        > comments can and often do) because a discrepancy between type
        > declaration and definition will be immidiately flagged by the compiler.[/color]

        They same holds for assertions as soon as they are run by the test suite.
        [color=blue][color=green]
        >>+ Error checking: I can only guess what you mean by this. If you mean
        >>something like Java's checked exceptions, there are clear signs that
        >>this is a very bad feature.[/color]
        >
        >
        > I think Fergus was referring to static error checking, but (and forgive
        > me if I'm wrong here) that's a feature you seem to insist has little or
        > no practical value - indeed, you seem to claim it is even an impediment
        > to productive programming. I'll leave this point as one of violent
        > disagreement...[/color]

        It has value for certain cases, but not in general.
        [color=blue][color=green]
        >>+ Efficiency: As Paul Graham puts it, efficiency comes from profiling.
        >>In order to achieve efficiency, you need to identify the bottle-necks of
        >>your program. No amount of static checks can identify bottle-necks, you
        >>have to actually run the program to determine them.[/color]
        >
        >
        > I don't think you understand much about language implementation.[/color]

        ....and I don't think you understand much about dynamic compilation. Have
        you ever checked some not-so-recent-anymore work about, say, the HotSpot
        virtual machine?
        [color=blue]
        > A strong, expressive, static type system provides for optimisations
        > that cannot be done any other way. These optimizations alone can be
        > expected to make a program several times faster. For example:
        > - no run-time type checks need be performed;
        > - data representation is automatically optimised by the compiler
        > (e.g. by pointer tagging);
        > - polymorphic code can be inlined and/or specialised according to each
        > application;
        > - if the language does not support dynamic typing then values need not
        > carry their own type identifiers around with them, thereby saving
        > space;
        > - if the language does support explicit dynamic typing, then only
        > those places using that facility need plumb in the type identifiers
        > (something done automatically by the compiler.)[/color]

        You are only talking about micro-efficiency here. I don't care about
        that, my machine is fast enough for a decent dynamically typed language.
        [color=blue]
        > On top of all that, you can still run your code through the profiler,
        > although the need for hand-tuned optimization (and consequent code
        > obfuscation) may be completely obviated by the speed advantage
        > conferred by the compiler exploiting a statically checked type system.[/color]

        Have you checked this?
        [color=blue][color=green]
        >>I wouldn't count the use of java.lang.Objec t as a case of dynamic
        >>typing. You need to explicitly cast objects of this type to some class
        >>in order to make useful method calls. You only do this to satisfy the
        >>static type system. (BTW, this is one of the sources for potential bugs
        >>that you don't have in a decent dynamically typed language.)[/color]
        >
        >
        > No! A thousand times, no!
        >
        > Let me put it like this. Say I have a statically, expressively, strongly
        > typed language L. And I have another language L' that is identical to
        > L except it lacks the type system. Now, any program in L that has the
        > type declarations removed is also a program in L'. The difference is
        > that a program P rejected by the compiler for L can be converted to a
        > program P' in L' which *may even appear to run fine for most cases*.
        > However, and this is the really important point, P' is *still* a
        > *broken* program. Simply ignoring the type problems does not make
        > them go away: P' still contains all the bugs that program P did.[/color]

        You are making several mistakes here. I don't argue for languages that
        don't have a type system, I argue for languages that are dynamically
        typed. We are not debating strong typing.

        Furthermore, a program P that is rejected by L is not necessarily broken.
        [color=blue][color=green][color=darkred]
        >>>Soft typing systems give you dynamic typing unless you explicitly ask
        >>>for static typing. That is the wrong default, IMHO. It works much
        >>>better to add dynamic typing to a statically typed language than the
        >>>other way around.[/color]
        >>
        >>I don't think so.[/color]
        >
        >
        > Yes, but your arguments are unconvincing. I should point out that
        > most of the people on comp.lang.funct ional (a) probably used weakly/
        > dynamically typed languages for many years, and at an expert level,
        > before discovering statically typed (declarative) programming and[/color]

        Weak and dynamic typing is not the same thing.
        [color=blue]
        > (b) probably still do use such languages on a regular basis.
        > Expressive, static typing is not a message shouted from ivory towers
        > by people lacking real-world experience.[/color]
        [color=blue]
        > Why not make the argument more concrete? Present a problem
        > specification for an every-day programming task that you think
        > seriously benefits from dynamic typing. Then we can discuss the
        > pros and cons of different approaches.[/color]

        No. The original question asked in this thread was along the lines of
        why abandon static type systems and why not use them always. I don't
        need to convince you that a proposed general solution doesn't always
        work, you have to convince me that it always works.

        Otherwise I could come up with some other arbitrary restriction and
        claim that it is a general solution for writing better programs, and ask
        you to give counter-examples as well. This is not a reasonable approach
        IMHO.

        There are excellent programs out there that have been written with
        static type systems, and there are also excellent programs out there
        that have been written without static type systems. This is a clear
        indication that static type systems are not a necessary condition for
        writing excellent programs.

        Furthermore, there are crap programs out there that have been written
        with static type systems, so a static type system is also not a
        sufficient condition for writing good software.

        The burden of proof is on the one who proposes a solution.


        Pascal

        Comment

        • Pascal Costanza

          #109
          Re: Python from Wise Guy's Viewpoint

          Fergus Henderson wrote:
          [color=blue]
          > In my experience, people who have difficulties in getting their programs
          > to typecheck usually have an inconsistent design, not a design which is
          > consistent but which the type checker is too restrictive to support.[/color]

          Have you made sure that this is not a circular argument?

          Does "consistent design" mean "acceptable by a type checker" in your book?


          Pascal

          Comment

          • Dirk Thierbach

            #110
            Static typing (was: Python from Wise Guy's Viewpoint)

            Pascal Costanza <costanza@web.d e> wrote:[color=blue]
            > You need some testing discipline, which is supported well by unit
            > testing frameworks.[/color]

            IMHO it helps to think about static typing as a special kind of unit
            tests. Like unit tests, they verify that for some input values, the
            function in question will produce the correct output values. Unlike
            unit tests, they do this for a class of values, instead of testing
            statistically by example. And unlike unit tests, they are pervasive:
            Every execution path will be automatically tested; you don't have
            to invest brain power to make sure you don't forget one.

            Type inference will automatically write unit tests for you (besides
            other uses like hinting that a routine may be more general than you
            thought). But since the computer is not very smart, they will test
            only more or less trivial things. But that's still good, because then
            you don't have to write the trivial unit tests, and only have to care
            about the non-trivial ones.

            Type annotations are an assertion language that you use to write down
            that kind of unit tests.
            [color=blue]
            > Static type systems are claimed to generally improve your code. I
            > don't see that.[/color]

            They do it for the same reason that unit tests do:

            * They are executable documention.

            * By writing them down first, you focus on what you want to do.

            * They help with refactoring.

            etc.

            Of course you can replace the benefits of static typing by enough unit
            tests. But they are different verification tools: For some kind of
            problems, one is better, for other kinds, the other. There's no reason
            not to use both.

            - Dirk

            Comment

            • Joachim Durchholz

              #111
              Re: Python from Wise Guy's Viewpoint

              Andrew Dalke wrote:[color=blue]
              > If a few rockets blow up for testing then it's still cheaper than
              > quintupling the development costs.[/color]

              Not quite - that was a loss of 500 million dollars. I don't know what
              the software development costs were, so I'm just guessing here, but I
              think it's relatively safe to assume a doubly redundant system would
              already have paid off if it had caught the problem.

              The point is that no amount of software technology would have caught the
              problem if the specifications are wrong. I think it would have been more
              successful if there had been some automated specification checking,
              which is safely in the area of theorem proving - which has interesting
              connections to static type checking but is otherwise unrelated to
              programming.

              Regards,
              Jo

              Comment

              • Joachim Durchholz

                #112
                Re: Python from Wise Guy's Viewpoint

                Pascal Costanza wrote:
                [color=blue]
                > For example, static type systems are incompatible with dynamic
                > metaprogramming . This is objectively a reduction of expressive power,
                > because programs that don't allow for dynamic metaprogramming can't be
                > extended in certain ways at runtime, by definition.[/color]

                What is dynamic metaprogramming ?

                Regards,
                Jo

                Comment

                • Holger Krekel

                  #113
                  Re: Static typing (was: Python from Wise Guy's Viewpoint)

                  Dirk Thierbach wrote:[color=blue]
                  > Pascal Costanza <costanza@web.d e> wrote:[color=green]
                  > > You need some testing discipline, which is supported well by unit
                  > > testing frameworks.[/color]
                  >
                  > IMHO it helps to think about static typing as a special kind of unit
                  > tests. Like unit tests, they verify that for some input values, the
                  > function in question will produce the correct output values. Unlike
                  > unit tests, they do this for a class of values, instead of testing
                  > statistically by example. And unlike unit tests, they are pervasive:
                  > Every execution path will be automatically tested; you don't have
                  > to invest brain power to make sure you don't forget one.[/color]

                  IMHO typical unit-tests in python go a lot further than just testing
                  types. They test *behaviour* rather than just types. Thus I tend to
                  think that for languages like python unittests are a *perfect match*
                  because there is hardly any redundancy and they are very short to write
                  down usually. Writing unittests in a statically typed language is more
                  redundant because - like you say - type declarations already are a kind
                  of (IMO very limited) tests.

                  cheers,

                  holger

                  Comment

                  • Pascal Costanza

                    #114
                    Re: Static typing

                    Dirk Thierbach wrote:[color=blue]
                    > Pascal Costanza <costanza@web.d e> wrote:
                    >[color=green]
                    >>You need some testing discipline, which is supported well by unit
                    >>testing frameworks.[/color]
                    >
                    > IMHO it helps to think about static typing as a special kind of unit
                    > tests. Like unit tests, they verify that for some input values, the
                    > function in question will produce the correct output values. Unlike
                    > unit tests, they do this for a class of values, instead of testing
                    > statistically by example. And unlike unit tests, they are pervasive:
                    > Every execution path will be automatically tested; you don't have
                    > to invest brain power to make sure you don't forget one.[/color]

                    This is clear.
                    [color=blue]
                    > Type inference will automatically write unit tests for you (besides
                    > other uses like hinting that a routine may be more general than you
                    > thought). But since the computer is not very smart, they will test
                    > only more or less trivial things. But that's still good, because then
                    > you don't have to write the trivial unit tests, and only have to care
                    > about the non-trivial ones.[/color]

                    Unless the static type system takes away the expressive power that I need.
                    [color=blue]
                    > Type annotations are an assertion language that you use to write down
                    > that kind of unit tests.[/color]

                    Yep.
                    [color=blue]
                    > Of course you can replace the benefits of static typing by enough unit
                    > tests. But they are different verification tools: For some kind of
                    > problems, one is better, for other kinds, the other. There's no reason
                    > not to use both.[/color]

                    I have given reasons when not to use a static type system in this
                    thread. Please take a look at the Smalltalk MOP or the CLOS MOP and tell
                    me what a static type system should look like for these languages!


                    Pascal

                    --
                    Pascal Costanza University of Bonn
                    mailto:costanza @web.de Institute of Computer Science III
                    http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)

                    Comment

                    • Pascal Costanza

                      #115
                      Re: Python from Wise Guy's Viewpoint

                      Joachim Durchholz wrote:[color=blue]
                      > Pascal Costanza wrote:
                      >[color=green]
                      >> For example, static type systems are incompatible with dynamic
                      >> metaprogramming . This is objectively a reduction of expressive power,
                      >> because programs that don't allow for dynamic metaprogramming can't be
                      >> extended in certain ways at runtime, by definition.[/color]
                      >
                      > What is dynamic metaprogramming ?[/color]

                      Writing programs that inspect and change themselves at runtime.


                      Pascal

                      --
                      Pascal Costanza University of Bonn
                      mailto:costanza @web.de Institute of Computer Science III
                      http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)

                      Comment

                      • Joachim Durchholz

                        #116
                        Re: Python from Wise Guy's Viewpoint

                        Andrew Dalke wrote:[color=blue]
                        > Pascal Costanza:
                        >[color=green]
                        >>The set of programs that are useful but cannot be checked by a static
                        >>type system is by definition bigger than the set of useful programs that
                        >>can be statically checked. So dynamically typed languages allow me to
                        >>express more useful programs than statically typed languages.[/color]
                        >
                        > Ummm, both are infinite and both are countably infinite, so those sets
                        > are the same size. You're falling for Hilbert's Paradox.[/color]

                        The sets in question are not /all/ dynamically/statically typed
                        programs, they are all dynamically/statically typed programs that fit
                        any item in the set of specifications in existence. Which is a very
                        finite set.
                        [color=blue]
                        > Also, while I don't know a proof, I'm pretty sure that type inferencing
                        > can do addition (and theorem proving) so is equal in power to
                        > programming.[/color]

                        Nope. It depends on the type system used: some are decidable, some are
                        undecidable, and for some, decidability is unknown.

                        Actually, for decidable type inference systems, there's also the
                        distinction between exponential, polynomial, O (N log N), and linear
                        behaviour; for some systems, the worst-case behaviour is unknown but
                        benevolent in practice.

                        The vast majority of practical programming languages use a type
                        inference system where the behavior is known to be O (N log N) or better :-)
                        (meaning that the other type systems and associated inference algorithms
                        are research subjects and/or research tools)

                        Regards,
                        Jo

                        Comment

                        • Joachim Durchholz

                          #117
                          Re: Python from Wise Guy's Viewpoint

                          Pascal Costanza wrote:
                          [color=blue]
                          > Fergus Henderson wrote:
                          >[color=green]
                          >> In my experience, people who have difficulties in getting their programs
                          >> to typecheck usually have an inconsistent design, not a design which is
                          >> consistent but which the type checker is too restrictive to support.[/color]
                          >
                          > Have you made sure that this is not a circular argument?
                          >
                          > Does "consistent design" mean "acceptable by a type checker" in your book?[/color]

                          Matthias Blume already posted that the type checker caught several
                          design errors. He's not the only to post such reports, I regularly
                          statements like that on comp.lang.funct ional.

                          Regards,
                          Jo

                          Comment

                          • Joachim Durchholz

                            #118
                            Re: Python from Wise Guy's Viewpoint

                            Pascal Costanza wrote:
                            [color=blue]
                            > Ralph Becket wrote:[color=green]
                            >> I fail to see how dynamic typing can confer any kind of advantage here.[/color]
                            >
                            > Read the literature on XP.[/color]

                            Note that most literature contrasts dynamic typing with the static type
                            systems of C++ and/or Java. Good type systems are /far/ better.
                            [color=blue][color=green]
                            >> Are you seriously claiming that concise, *automatically checked*
                            >> documentation (which is one function served by explicit type
                            >> declarations) is inferior to unchecked, ad hoc commenting?[/color]
                            >
                            > I am sorry, but in my book, assertions are automatically checked.[/color]

                            But only at runtime, where a logic flaw may or may not trigger the
                            assertion.
                            (Assertions are still useful: if they are active, they prove that the
                            errors checked by them didn't occur in a given program run. This can
                            still be useful. But then, production code usually runs with assertion
                            checking off - which is exactly the point where knowing that some bug
                            occurred would be more important...)
                            [color=blue][color=green]
                            >> For one thing, type declarations *cannot* become out-of-date (as
                            >> comments can and often do) because a discrepancy between type
                            >> declaration and definition will be immidiately flagged by the compiler.[/color]
                            >
                            > They same holds for assertions as soon as they are run by the test suite.[/color]

                            A test suite can never catch all permutations of data that may occur (on
                            a modern processor, you can't even check the increment-by-one operation
                            with that, the universe will end before the CPU has counted even half of
                            the full range).
                            [color=blue][color=green][color=darkred]
                            >>> + Efficiency: As Paul Graham puts it, efficiency comes from
                            >>> profiling. In order to achieve efficiency, you need to identify the
                            >>> bottle-necks of your program. No amount of static checks can identify
                            >>> bottle-necks, you have to actually run the program to determine them.[/color]
                            >>
                            >> I don't think you understand much about language implementation.[/color]
                            >
                            >
                            > ....and I don't think you understand much about dynamic compilation.
                            > Have you ever checked some not-so-recent-anymore work about, say, the
                            > HotSpot virtual machine?[/color]

                            Well, I did - and the results were, ahem, unimpressive.
                            Besides, HotSpot is for Java, which is statically typed, so I don't
                            really see your point here... unless we're talking about different VMs.

                            And, yes, VMs got pretty fast these days (and that actually happened
                            several years ago).
                            It's only that compiled languages still have a good speed advantage -
                            making a VM fast requires just that extra amount of effort which, when
                            invested into a compiler, will make the compiled code still run faster
                            than the VM code.
                            Also, I have seen several cases where VM code just plain sucked
                            performance-wise until it was carefully hand-optimized. (A concrete
                            example: the all-new, great graphics subsystem for Squeak that could do
                            wonders like rendering fonts with all sorts of funky effects, do 3D
                            transformations on the fly, and whatnot... I left Squeak before those
                            optimizations became mainstream, but I'm pretty sure that Squeak got
                            even faster. Yet Squeak is still a bit sluggish... only marginally so,
                            and certainly no more sluggish than the bloatware that's around and that
                            commercial programmers are forced to write, but efficiency is simply
                            more of a concern and a manpower hog than with a compiled language.)
                            [color=blue]
                            > There are excellent programs out there that have been written with
                            > static type systems, and there are also excellent programs out there
                            > that have been written without static type systems. This is a clear
                            > indication that static type systems are not a necessary condition for
                            > writing excellent programs.[/color]

                            Hey, there are also excellent programs written in assembly. By your
                            argument, using a higher language is not a necessary condition for
                            writing excellent languages.

                            The question is: what effort goes into an excellent program? Is static
                            typing a help or a hindrance?

                            One thing I do accept: that non-inferring static type systems like those
                            of C++ and Java are a PITA. Changing a type in some interface tends to
                            cost a day or more, chasing all the consequences in callers, subclasses,
                            and whatnot, and I don't need that (though it does tell me all the
                            places where I should take a look to check if the change didn't break
                            anything, so this isn't entirely wasted time).
                            I'm still unconvinced that an inferring type system is worse than
                            run-time type checking. (Except for that "dynamic metaprogramming " thing
                            I'd like to know more about. In my book, things that are overly powerful
                            are also overly uncontrollable, but that may be an exception.)

                            Regards,
                            Jo

                            Comment

                            • Joachim Durchholz

                              #119
                              Re: Python from Wise Guy's Viewpoint

                              Pascal Costanza wrote:[color=blue]
                              > See the example of downcasts in Java.[/color]

                              Please do /not/ draw your examples from Java, C++, or Eiffel. Modern
                              static type systems are far more flexible and powerful, and far less
                              obtrusive than the type systems used in these languages.

                              A modern type system has the following characteristics :

                              1. It's safe: Code that type checks cannot assign type-incorrect values
                              (as opposed to Eiffel).

                              2. It is expressive: There's no need to write type casts (as opposed to
                              C++ and Java). (The only exceptions where type casts are necessary are
                              those where it is logically unavoidable: e.g. when importing binary data
                              from an untyped source.)

                              3. It is unobtrusive: The compiler can infer most if not all types by
                              itself. Modifying some code so that it is slightly more general will
                              thus automatically acquire the appropriate slightly more general type.

                              4. It is powerful: any type may have other types as parameters. Not only
                              for container types such as Array <Integer>, but also for other
                              purposes. Advanced type systems can even express mutually recursive
                              types - an (admittedly silly) example: trees that have alternating node
                              types on paths from root to leaves. (And all that without type casts,
                              Mum! *g*)

                              Regards,
                              Jo

                              Comment

                              • Andreas Rossberg

                                #120
                                Re: Python from Wise Guy's Viewpoint

                                Joachim Durchholz wrote:[color=blue]
                                >
                                > The vast majority of practical programming languages use a type
                                > inference system where the behavior is known to be O (N log N) or better[/color]

                                Not true, unfortunately. Type inference for almost all FP languages is a
                                derivative from the original Hindley/Milner algorithm for ML, which is
                                known to have exponential worst-case behaviour. Interestingly, such
                                cases never show up in practice, most realistic programs can be checked
                                in subquadratic time and space. For that reason even the inventors of
                                the algorithm originally believed it was polynomial, until somebody
                                found a counterexample.

                                The good news is that, for similar reasons, undecidable type checking
                                need not be a hindrance in practice.

                                - Andreas

                                --
                                Andreas Rossberg, rossberg@ps.uni-sb.de

                                "Computer games don't affect kids; I mean if Pac Man affected us
                                as kids, we would all be running around in darkened rooms, munching
                                magic pills, and listening to repetitive electronic music."
                                - Kristian Wilson, Nintendo Inc.

                                Comment

                                Working...