
SICP in Python - crammyRL
https://wizardforcel.gitbooks.io/sicp-in-python/content/
======
jedberg
It made me so sad when I found out CS61A was being taught in Python. I love
Python, but I also know that I would have missed out on so much wonderful
information if I hadn't learned Scheme.

It was truly mind blowing when they had us implement a Scheme interpreter in
Scheme, and then add infix operators.

I think the original SICP was perfect for an intro course.

It was also the great leveler, because even if you entered college with
programming experience, almost no one knew Scheme. So you were all on equal
footing when it came to the language.

~~~
montebicyclelo
Thank you for explaining why you think Scheme is a better langauge for SICP
than Python.

As a fan of Python, my reaction to seeing this course was: "oh cool, a course
on interesting things in a language I'm comfortable with".

I was then somewhat discombobulated to see the Python bashing in the comments.

~~~
woofie11
SICP is about deeply understanding computation.

Scheme is a good language for SICP because it's simple. You can build a Scheme
interpreter as a class project. You can analyze it formally. Etc.

Python is a good language because it's readable and writeable. But it doesn't
work for SICP since it's too complex for that. Python also intentionally omits
things critical to SICP (like tail recursion).

Calling this book "SICP in Python" would be like taking your favorite poem,
releasing it into a different language, and finding that the translators wrote
a completely different book, with a different theme, to make it rhyme and the
rhythm hold. Just something different with the same name.

~~~
StreamBright
Except that 90% of Python programmers fail to answer simple questions like:

Given:

    
    
        def extendList(val, list=[]):
            list.append(val)
            return list
    
    

What do the following print:

print(extendList(1))

print(extendList(1))

print(extendList(2))

print(extendList(3,[]))

I do not blame them. This sort of behavior is error-prone. You can make sure
that you do not use such a code in production with code reviews but it would
be also great to not having such things in the language.

~~~
czzr
For what it’s worth, I’m not a Python programmer and I got that correct.

The answer is:

[1]

[1, 1]

[1, 1, 2]

[3]

It relies on knowing something about how python applies default arguments.

I’ve only written about a hundred lines of python in my life, so possibly I
just got lucky - still, I would have thought an actual Python programmer
should get this?

~~~
goatlover
It is different from how Ruby and Javascript handle default arguments. I'm
surprised Python does that, since I would expect function arguments to be
reset to their defaults each call. That's a major side effect.

~~~
kadoban
It's pretty odd behavior, yeah. It's easy to work around (set the default to
None and then set the actual default in the function body), but I don't know
if I've _ever_ seen anyone want it to behave as it does now.

~~~
nitroll
It does make sense to evaluate the default value for the parameter at the
point of definition for serveral reasons. First of all, the default value does
not have to be a literal value, and if you wanted it to be evaluated at call
time the function would need to capture all of the default values in a
closure.

    
    
      default = 10
      def foo(x=default):
          return x
      default = 20
      assert foo() == 10
    

I think tat makes a lot of sense.

It could also be that the default value is a more ocmplex expression, we could
use a function to generate a default argument.

    
    
      def foo(x=create_default(y, z))
    

By evaluating it at definition time we only have to evaluate the expression
once and not have this weird lazy expression.

And yes it is used, for example the fastapi Dependency Injection system has
been build quite cleverly using the ability to construct default values

[https://fastapi.tiangolo.com/tutorial/query-params-str-
valid...](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/)

Yes it is one of those things you just have to learn, but there are tons of
stuff like that in most programming languages.

~~~
kazinator
Under the sane semantics implemented in every major language other than
Python, if you want to capture a snapshot of something at definition time, you
can put it into a variable:

    
    
      wildly_changing_variable = random_initializer();
    
      stable_snapshot = wildly_changing_variable
    
      def foo(arg = stable_snapshot):
        ...
    

Don't touch stable_snapshot and everything is cool. This is the rare case. Of
course

    
    
      def foo(arg = wildly_changing_variable)
    

means we want the current value.

I don't understand your "closure" comments; either way, things are being
lexically closed. It's a question of when evaluation takes place, not in what
scope or under what scoping discipline.

In fact, Python's treatment requires the implementation to have a hidden
storage that is closed over; the equivalent of my _stable_snapshot_ variable
has to be maintained by the implementation. The definition-time evaluation has
to stash the value somewhere, so to that it can use that one and not the
current.

------
hf
If you wanted to delve into the original 1984 LISP/Scheme version by Abelson
and Sussman, I recommend you take a look at

[https://opendocs.github.io/sicp/sicp.pdf](https://opendocs.github.io/sicp/sicp.pdf)

which is based on the MITPress HTML version, released under a permissive CC-
by-SA license.

[https://mitpress.mit.edu/sites/default/files/sicp/index.html](https://mitpress.mit.edu/sites/default/files/sicp/index.html)

(nb. The pdf starts out with a curious little 'texinfo foreword'. Being able
to type `info sicp` in one's shell? I wonder ...)

~~~
neilv
> _The pdf starts out with a curious little 'texinfo foreword'. Being able to
> type `info sicp` in one's shell?_

Yes, mostly in Emacs, but you could also do it in your shell. :)
[https://www.neilvandyke.org/sicp-texi/](https://www.neilvandyke.org/sicp-
texi/)

The Texinfo format happened a couple years ago, in the early days of the Web,
and let people on modest computers who couldn't run a Web browser work through
SICP on their screens (no need for expense of printing to paper) while they
also ran a Scheme interpreter on the same modest computer. The work was done
by Lytha Ayth from the original freely-available HTML version of the book.

Later on, and now that everyone has more powerful computers, I've heard
someone took the Texinfo source code, and replaced the ASCII-art illustrations
with real ones, and ran it through TeX, such as for printing or PDF of "camera
ready" format that looked similar to the original print book from MIT Press.

I wasn't involved in that much more recent TeX work, and though it was kind of
them to preserve the version number with my name in it, I'll ask them to
please remove it. (The name was part of some kind of distributed version-
tracking scheme that Lytha Ayth proposed, when this seemed to be in the spirit
of the original HTML release of the book. I tried to follow versioning
instructions when I made changes to the Texinfo source, not knowing my name
would show up 20 years later in a very different thing. :)

~~~
hf
[Late reply -- forgot to hit the button. ;]

Thank you for the pointer and, more so, your contributions.

That screenshot of SICP in Emacs -- running side-by-side with the built-in
Guile interpreter -- induces peculiar sensations. An echo of how things
could've been and possibly still are in some obscure(d) corners of the Net. An
interactive learning environment that at least points in the right direction.
It certainly looks elegant and somewhat inspirational to me (though my inner
Alan Kay is voicing some profound objections ;).

In any case: you carried that torch for a while, don't be hesitant accepting
apparently undue credit -- there's too little, in any case, to warrant worry.
;)

~~~
neilv
Thank you for your nice note.

Regarding the Emacs screenshot, here's another, from an early attempt to make
Emacs more off-she-shelf usable for Scheme programming:
[https://www.neilvandyke.org/quack/](https://www.neilvandyke.org/quack/)

An actually better experience in Emacs (and part of what got me psyched to
learn Lisps) is for Emacs Lisp programming: with a properly
configured/installed Emacs, you can be browsing the documentation with rapid
navigation, bringing up hypertext docstrings from your code , with links to
the source code (perhaps the source code of Emacs itself), evaluating code
that affects your running environment from both REPL and editor, etc. It's
different than the Smalltalk-80 environment (which I also used, and wrote a
little Smalltalk browser for), but there is some overlap. Modern IDEs let you
do some of that, and some other things, but sometimes not as well, and Emacs
people had this for a few decades.

------
neilv
Neat. The more, the merrier.

If anyone wants to work through SICP in the original way, you can get MIT
Scheme, and run it on some computers.

sudo apt install mit-scheme

Some of us added support to DrRacket, for working through SICP that way
(though if you already know how to use an editor, etc., you might prefer to
just run MIT Scheme): [https://docs.racket-lang.org/sicp-
manual/](https://docs.racket-lang.org/sicp-manual/)

~~~
Err_Eek
I have been using #lang sicp in Racket to go through (most of) SICP -- and
it's been mostly a smooth ride. DrRacket can get very slow on Linux, so
eventually I switched back to vim+terminal once exercises started to require
larger amounts of code.

------
qpax
"Processing Recursive Lists" is a good example of how Python is abused for all
sorts of things.

If this is actually taught, I'm no longer surprised by the code that I
encounter in the wild.

~~~
BiteCode_dev
I concur, this book is a terrible way to introduce anybody to Python.

I imagine they want to teach general programming skills, and hence want to
give you a "way to think" that is low level enough to let you work with any
language, using Python as a pseudo-code to demonstrate it.

This approach is doomed to fail.

It's much better to teach the language properly, then introduce other
languages as a comparison point, if this is what you want.

I don't get the stellar reputation of this text, maybe it was great when it
was written for Scheme, but as-is, I can't see most of my students even
finding the motivation to reading it.

~~~
ylyn
SICP shouldn't really be taught in any language other than Scheme, or a
language designed specifically for teaching SICP.

It doesn't make sense otherwise.

~~~
noah_buddy
To disagree with you, I took the Python version of UCB's CS61A and I learned
quite a lot (especially coming from a non-programming background). Perhaps
other forms of SICP are better, but CS61A was a really enjoyable course
overall and was part of the reason I decided to switch majors to Computer
Science.

------
nikofeyn
i think this is rather dishonest to call this "SICP in Python" and the same
goes for the title of this post. this is _not_ SICP and is not simply a port
of the code found in SICP to python with the text unchanged. it's simply a
book that seems inspired by SICP but the introduction doesn't go into any
detail other than saying it's "derived from" SICP. this is misleading to
people who aren't familiar with SICP and think this book is it but just for
python.

~~~
jholman
Agreed. Just a casual browse of the TOC will point out that even at the
coarsest-grained level, only 40-60% of the book follows the SICP lesson plan.

------
yarinr
The current version is here
[https://composingprograms.com/](https://composingprograms.com/) Under the
name Composing Programs. It is the textbook for CS61A.

------
basucoder
I read interview of Hal Abelson, in that interview he explains the reason
behind moving away from scheme to python to teach concepts of SICP.

1\. The purpose of course it self has changed, the current course 6.01 in MIT
attempts to introduce grads to breadth of the software engineering rather than
depths of software engineering. 6.001 course was for the later purpose.

2\. He says entire debate is superficial as both the course have different
purpose.

It's a lengthy interview.

[http://www.gigamonkeys.com/code-quarterly/2011/hal-
abelson/](http://www.gigamonkeys.com/code-quarterly/2011/hal-abelson/)

~~~
basucoder
[https://www.wisdomandwonder.com/link/2110/why-mit-
switched-f...](https://www.wisdomandwonder.com/link/2110/why-mit-switched-
from-scheme-to-python)

------
asicsp
I'm so used to syntax highlighting that it feels odd to try to read code
without highlighthing

A bit off-topic, now that legacy.gitbook.com will be read-only from next
month, anyone else just giving up on the platform? I used it mainly to allow
readers to easily get pdf/epub versions and as far as I know, that won't be
possible with new gitbook site.

~~~
gumby
By the way that is one of reasons for using scheme -- there's hardly any
syntax, and definitely none of the confusing distinction between statements
and expressions. There's not much value to syntax highlighting in such an
environment.

Remember: when the course was introduced (ca 1981) few of the freshman had
ever used a computer before they arrived at MIT. The first lecture included an
second on "how to program in scheme" and after that it was assumed you could
do all the assignments. This book has to include a much more complex (and I
would imagine to the new programmer, daunting) introduction to dealing with
Python.

I feel like the scheme version was a more nuts and bolts class full of
practical information while this Python version feels less practical. But that
could be a bias on my part.

There are good reasons to switch the instruction to Python (the libraries,
mainly) but in exchange something is lost. Engineering is all about dealing
with such tradeoffs :-).

------
jxy
I prefer the scheme version, though the addition of 'distributed and parallel
computing' chapter is really important and I welcome such new additions.

Unfortunately 'distributed and parallel computing' is no where to be seen in
R*RS. I hope we can change that soon.

------
Y_Y
Manual of Ice-Fishing rewritten for desert nomads.

~~~
nikofeyn
in the software world, one can avoid the monster that is c++ rather
successfully, but it's gotten to the point that no matter what, python is
thrust upon you to deal with. "hey here's this thing that is barely working"
(in large part because it's written in python) "and we'd like you to maintain
it but not switch from python" (because anything besides python makes us
uncomfortable). meanwhile, python makes me uncomfortable and is such an
unprincipled language, it feels like it fights you every step of the way to
write error-free code.

~~~
Y_Y
I have my misgivings about Python and C++ too, but when writing them for my
job I think how much worse things could be. I could have a job that didn't
involve coding, or no job, or even something involving Java.

~~~
nikofeyn
i personally can't get past it. i've hated every second of developing in
python in my jobs, and i just sit there wondering how nice it would be if i
could move off of it, especially when debugging and finding yet another inane
design decision in python or something that doesn't work. there's never been a
reason to use it other than that's what someone unfamiliar with better choices
chose for the project, and there's typically a very objective multiplier in
risk and time in the development by sticking with python. moving to clojure,
racket, f#, elixir, etc. would almost always be a better choice aside from
certain uses of python-specific libraries (like for machine learning).

~~~
randomsearch
The vast ecosystem of python libraries is an incredibly powerful argument for
using it. One major library could dramatically cut the development time of
your project.

You’ve not spelt out actual reasons why Python is so bad, could you give your
top three?

~~~
billfruit
One thing I have felt is that python doesn't embrace the functional way of
thinking, even to the extent that JavaScript does. I personally find that once
I have been exposed to a modern functional approach like in Clojure, etc, I
find python lacking. Not just syntactically, but conceptually. For example,
IIRC, many list methods in python modify the list they are working on, instead
of returning a new list.

~~~
jakear
In line with this, list comprehensions are one area of python I find
particularly clunky. They work fairly well for a single map or filter
operation, alright for both mapping and filtering, and are absolutely
unreadable for anything more complicated. A big part of this in my opinion is
how they scramble the flow. Instead of taking a piece of data and performing
successive operations on it, both in logic and in syntax, you have their
'literate' mess that requires you to start reading in the middle of the line
and alternate moving your cursor back and forth.

Consider:

getNumbers() .map(x => x×2) .filter(x => x % 6 == 0) .map(x => x^2)

get numbers. double them. filter for divisibility by 6. square them.

versus

[x^2 for x in x×2 for x in getNumbers() if x % 6 == 0]

get the square of the doubles version of getNumbers values, but only if those
doubles are dividable by 6. But wait are the doubles dividable by 6 or the
squares?

Maybe some people are fine with looking at what operations are being performed
on the data before even knowing what the data itself is, but that for me seems
incredibly backwards. Plus it also gives rise to order of operations
ambiguities. Nobody could mistake the ordering in JS, but I honestly have no
clue how that python would evaluate.

(using carats because hn cant format code)

Edit- This came to mind because of a flattening list comprehension I
encountered earlier today:

#flatten the lists

flattened_list = [y for x in list_of_lists for y in x]

I've spent quite some time staring at this and I still have no clue what it's
actually doing. I've never had that with JS operator chains.

~~~
jletts
map(lambda x:x^2, filter(lambda x:x%6==0, map(lambda x: x*2, getNumbers())))

Would probably be a more pythonic way to do that, avoiding list
comprehensions. Easier to read with added lines and indentation.

But tbf I do appreciate the ability to chain operations in JS without
subclassing objects like list.

~~~
dagw
Funny how 'pythonic' can mean different things to different people. I've been
developing in python on and off for the best part of a decade, and in my world
comprehensions are considered far more 'pythonic' than map/filter/lambda.

------
rahimnathwani
Previous discussion of the book:
[https://news.ycombinator.com/item?id=3718364](https://news.ycombinator.com/item?id=3718364)

And the course:
[https://news.ycombinator.com/item?id=3491142](https://news.ycombinator.com/item?id=3491142)

------
dang
Related from 2012:
[https://news.ycombinator.com/item?id=3141996](https://news.ycombinator.com/item?id=3141996)

2011:
[https://news.ycombinator.com/item?id=3141996](https://news.ycombinator.com/item?id=3141996)

Plus ça change.

------
anon767
Thats great! However does someone know if there is still someone working on
[http://www.sicpdistilled.com/](http://www.sicpdistilled.com/) ?

~~~
sesm
[https://github.com/SICPDistilled/website](https://github.com/SICPDistilled/website)
\- last commit 2 years ago. But I'm sure contributions are still welcome.

------
reminddit
Other languages are not as flexible as lisp according to pg. When you get to
macros, you might run into limitations with python.

------
fireattack
Links in each chapter's TOC don't work.

------
pdamoc
"Do not seek to follow in the footsteps of the wise; seek what they sought."
\- Basho

One of the reasons that the wizards stopped teaching SICP was the fact that
the world changed. Back in the 80s, most programming was done from first
principles, since the middle of the 90s it switched to programming against an
API.

While learning to program from first principles is still amazingly useful, it
is not what beginners need because most of them will never end up programming
like that.

~~~
randomsearch
I’m not so sure. SICP gives a deep understanding of programming principles
like abstraction.

I agree that gluing APIs is essentially what modern programming has become,
but it is helpful to have that extra understanding, especially in the long
term. We don’t know how programming will look in 2050, but abstraction will
remain abstraction, and I wouldn’t bet against Lisp being more popular then
than it is now.

~~~
jarcane
Indeed. APIs do not just appear from the void, someone has to write them for
anyone to have an API to glue together.

Somewhere at the bottom, fundamental code is always present.

------
crysis2917
Up next: Sicp JAVASCRIPT

~~~
wolfgke
This already exists:

[https://sicp.comp.nus.edu.sg/](https://sicp.comp.nus.edu.sg/)

Announcement on Reddit:
[https://www.reddit.com/r/scheme/comments/ea1f8w/sicp_js_goin...](https://www.reddit.com/r/scheme/comments/ea1f8w/sicp_js_going_public/)

~~~
ngcc_hk
Guess JS a better language for this purpose.

------
cutler
Next it will be SICP for Java. Is nothing sacred?

~~~
wolfgke
Concerning "sacred":
[https://kingjamesprogramming.tumblr.com/](https://kingjamesprogramming.tumblr.com/)

~~~
Sorrop
This almost made me fell off my chair.

    
    
      5:5 And, behold, I will deliver you up to the programmer
      tendency to build overelaborate castles of abstractions

~~~
JoeAltmaier
One person's overelaborate is another's perfection.

Behold! The abstraction in ethereal splendor makes mundane human existence
bearable!

------
nromiun
People say SICP is bigger then Scheme and then get outraged when someone
implements it in another language.

~~~
rfrey
Beethoven is bigger than "piano". Also, there is very little outrage in this
thread - some sadness, some resignation, some head shaking sure, but not
outrage.

------
analog31
I don't want to sound snarky, but... is this really it? I haven't looked
through SICP itself, and have no formal CS background, but it always seemed
like SICP was treated like a forbidding rite of passage. The Python version,
if it's faithful to the original, seems pretty lightweight.

~~~
ska
One of the non-obvious things about SICP is that there is a lot of really good
stuff in the footnotes and the exercises. You aren't doing yourself any favors
if you skim over either of them.

~~~
analog31
Indeed, a download and quick look shows that the book has a lot more content
than just a sequence of lessons. I've immersed in the foreword, and enjoying
it greatly. The best textbooks are not just informative, but written to be
enjoyed as literature.

~~~
ska
It's a classic for that reason. Enjoy!

------
gl3nnleblanc
As someone who has taken this iteration of the course and read most of the
original SICP, I actually think this new CS61A does a really good job of
covering the same material as the original SICP while introducing beginners to
a useful rather than esoteric language. The capstone project is still writing
a scheme interpreter, just in Python. We still do actually write some code in
Scheme, just in the later portion of the class.

