SICP general

Looking for your first programming language, or some help with SICP, or lisp in general? This is the thread for you.

Scheme is the ultimate language to learn or advance your programming on account of the trumendous ammount of resources available for learning the language and the core concepts of most languages. It also has a exceedingly simple syntax which allows you to jump into higher level conscepts quickly without having to drudge through the significant amounts of brute memorization that most languages have. Whether you're a rustfag or a expendable java code monkeys based scheme can help you improve your programming by introducing you to new paradimes aswell.

The holy grail of intro to computer science is attachted.

>more easier problems to work on if you're strugling with the book.

Other urls found in this thread:


Old MIT course number: 6.001
Current MIT courser number: 6.037

I have The Little Schemer, and a book on CL. It seems beyond me.

HTML5/EPUB3 version of SICP

Very unfortunate in my eyes. The lectures provided are for the old course number, and are pretty great. I haven't taken a look at the new one. I'm not sure the new lectures are available online

Lectures are massively helpful. I'm not aware of any for The Little Schemer but I'm confident there are some for CL. Also you've now got some people to ask if you get stuck. :)

Nice addition user.

Autists who only pretend to program will disagree, but I highly recommend Clojure. It's a modern practical Lisp. If you're doing SICP use mit scheme though.

SICP is tremendous for learning the concepts of programming. I followed the course over the summer before I started CS at university (about 8 years ago now) and it reshaped the entire way I looked at programming. I don't write much to any Scheme/Lisp today (other than Emacs Lisp), but it really does change the way you think about programming.

agreed. Clojure and Common Lisp are really the only games in town for Lispy practical programming. Common Lisp seems to be becoming slowly stagnant, though.

Why does DrRacket print lists as nested cons?

For some reason I could not really convince myself to make serious effort learning LISP and its friends. Which is quite weird as I really loved ML languages and still try to use ocaml whenever I can when my duty as a c++ monkey ends.

What kind of mental model should I develop while reading SICP or little schemer? Like when I'm using imperative language it's all about tracking down the change of state and trying not to introduce unintended course of action and for ocaml I start with clear goal of what needs to be done and describe what should be done as how I would deal with abstract mathematics.

With lisp or scheme my primitive mind cannot capture any bigger picture hiding beyond endless parentheses. Should I start by learning to use emacs? What brought you to lisp family and what is keeping you on that camp?


What mode are you in, I don't recall that behaviour.

The mental model is to think about the flow of expressions. You know from imperative the difference between an statement and an expression.

x = 5; is a statement
x = 5 * 2; is a statement assigning the result of the expression 5 * 2.

In scheme, everything is an expression.

cont'd: Also think of let and define forms in Racket as providing names for the results of expressions, not as statements assigning results to variables.

Well yes I can see that much but my question was more about code readability of lisp family. For example to define range function that returns the list of all numbers between two operands ocaml version would look like :

let rec range a b =
if a > b then []
else a :: range (a+1) b;;

even if you don't know ocaml if I tell you [] is empty list and :: means cons operator you would realize this is natural description of a list structure that has a desired property returned by range function.

CLISP alternative might look like this :

(defun range (min max)
(when (

*by step I meant (integer) 1

SCHEME is a programming language that manages to be less functional and usable than fucking Haskell.
It's solely used to jack off academics.
If you want any of the advantages that you rattled off, pick up CL instead.

but what about muh embeddable tinyscheme? If Apple and other goys are using it surely there must be some practical usage of it.

Speaking of embedded scheme how many GNU projects are using guile as extension language these days? I remember old talk where one Japanese guy made tracing JIT compiler for guile but don't think it got merged to upstream. What are they trying to achieve exactly?

CL is less functional than scheme and has a more complex standard, also it lacks the teaching infrastructure of scheme, scheme being a academic language and all. I'm not advocating using scheme as a general purpose language but as a learning tool. I feel like too often people just obsess over what language to learn trying to access the practicality of each one, and it just results in them not learning anything. This thread is meant to address this problem and give encouragement along the way. In addition to this to encourage experienced programmers to pick up a copy of SICP because there is much to learn from it for everyone.
If people are looking for a lisp language to use for general purpose programming though, Common Lisp, Clojure are certainly the way to go as mentioned earlier in the thread.

They keep trying to port emacs over to it but other than that their is just guix using it as far as major projects go.

Fundamentally you seem to grasp it well. As for comprehension, I really don't think scheme/lisp code is the easiest to parse at a glance, and it does take effort to see what is going on until you build up some experience. While scheme is nice to teach semantics, as a learning language it's syntax is far less clear than something like Pascal. That said, if you know OCaml, Scheme should be easy for you, it's much simpler.

One thing I will say is that your range function isn't taking advantage of tail-call optimization. If your range were large, you'd run out of space on your call stack. The solution is to use an accumulator. Here's how that might look in Racket. The inner form of let is just a short hand for defining a function and evaluating it with initial arguments.

(define (range min max) (let iter ([x min] [acc '()]) (if (> x max) (reverse acc) (iter (+ x 1) (cons x acc)))))(range 1 10)

How different is it from OCaML?

The best way to think of Lisp syntax is not to think of it as a syntax, but the lack of a syntax. In other languages you have certain rules on how you can write your code so that the compiler can parse the code and internally assemble it into a tree-structure called the AST (abstract syntax tree). In Lisp you just skip the syntax and straight-up write the AST directly.

Take for example the math expression
you need to know the order of operations in order to evaluate it and you have to jump around in the expression. Writing the same expression as an S-expression:
(Scheme has no ^ operator, but you could define it if you wanted to) It becomes easier to see if we write it two-dimensionally:
(/ (* 3 (+ 2 x)) (^ 7 2))
You can now see the tree-structure, and this is also why Lisp code is usually indented this way. Let's now define the range function in Scheme.
(define (range min max) (cond ((= min max) '()) (else (cons min (range (+1 min) max)))))
(There is no error checking to make sure that the initial arguments are valid, but neither does you OCaml code) This is pretty much a 1:1 translation of your OCaml code. We have a conditional (could have used an if, but cond is more common) with two cases.

Note that the lack of syntax means that we have to explicitly state that we want to have a conditional check, whereas it was implicit in your OCaml code because the syntax filled in that information. The same goes for the cons: there is no list comprehension syntax, so we explicitly have to say that we want to construct a list.

So if we have to be explicit about everything, then what is the point of this non-syntax? Well, I call it a non-syntax, but of course it is a syntax, a homoiconic one: everything looks the same. The cond operator for example is not a function, but it is used the same way as a function. For one, this means there are no surprises, if you know this one rule you know all of Lisp's syntax. The other big thing is that adding your own operators is possible and thus you can expand the language using the language itself. It's all just transforming one tree structure into another.

Let's take local binding as an example: We want to bind some value to a specific environment context and then throw them away again. In Scheme the only operator that can construct a new environment is the lambda λ.
((λ (foo bar baz) (display foo) (display bar) (display baz)) 1 2 3)
WTF is this shit? We are creating a new anonymous function with the λ that has three parameters (foo, bar, baz). This expression is surrounded in another pair of parentheses because we are immediately calling it and we are passing 1, 2 and 3 as its arguments. Now the function body can use these values to do anything it wants with them. This code is ugly, unidiomatic and easy to get wrong. How about we invent a new operator?
(let ((foo 1) (bar 2) (baz 3)) (display foo) (display bar) (display baz))
Even if you have never seen Scheme in your life you can guess what this is doing. The let operator is part of the standard, but you could just as well retrofit it as a macro so that the let-tree gets rewritten into the define-tree above. In fact, this is usually how a Scheme implementation is going to implement the let operator.

This is a general-purpose operator, but you could just as well invent a series of operators for your particular problem domain. Then you can write your program in this domain-specific language instead of messing about with the entire underlying language.

Common Lisp is a rather ugly Lisp, but prefix-notation is something you have to get used to in any Lisp. It's weird at first, but the precision and unambiguity is a huge win. I do a lot with math and sometimes standard notation becomes so ugly that I rewrite it in S-expressions on paper for myself just so that I can make sense of it. It's weird, but in a good way.

(define (range a b) (if (> a b) '() (cons a (range (+ a 1) b))))
don't see the difference to ocaml really

I think you are being a bit too positive. Lisp is pretty terrible to read if functions aren't broken into a million little pieces. SICP makes out that this is some revolutionary idea and I guess people believe it but it quickly becomes confusing.
Also the near requirement of emacs or some other ide due to matching parens issues and the pain of altering functions should tell you something about how easy the syntax is to use.

New lectures aren't available online but the course has been slightly updated to use Racket's implementation of Scheme.
It's just another source if you're planning on doing the course yourself, and it also offers homework which you could try.

Necessary post, thanks user.

Why use mit-scheme and not Racket's R5RS?
Is there any use of Lisps other than Clojure in the industry?

Anyone here noticed the similarities between lisp and tcl?

in my own experience, the only Lisp I've ever come across in a corporate environment is Common Lisp. I know guys working on projects in Clojure, though. They're the two big guys.

Sure. It can look a bit like Lisp in certain circumstances. As an aside, RMS said in a speech[1] that his dislike of Tcl was the reason he pushed for the development of Guile.


I'm pretty new to the language and even I've experienced issues and annoyance with this tbh.

Seems like he's just shitting on tcl because he didn't like it.
Do you know which language won as an extension language? I know the VLSI industry uses tcl, but no idea what happens in other fields

Reminder that funcprogfags literally condone the following.
(define (choose n k) (cond ((or (< n 0) (< k 0)) 0) ((> k n) 0) ((or (= k 0) (= k n)) 1) (else (+ (choose (- n 1) k) (choose (- n 1) (- k 1))))))

I don't condone bad formatting

well I know it's not guile. That never got off the ground, even within GNU.

Reminder that funcprogfags literally condone the following.
(define (choose n k) (cond ((or (< n 0) (< k 0)) 0) ((> k n) 0) ((or (= k 0) (= k n)) 1) (else (+ (choose (- n 1) k) (choose (- n 1) (- k 1))))))

So I've put all additional resources to SICP (like interactive SICP, ready exercises) :
Feel free to contribute!

Well of course, it's a bare minimum example of a recursive function, it will look the same in any langauge
void range(int *arr, int a, int b) { if (a > b) { return; } else { range(++arr, ++a, b); }}

The same is true for any language though. I have a rule of thumb that the line count of a function should not be larger than the size of my hand (palm plus fingers) on the screen, otherwise it become horrible to read.

Yes, you should use an editor that helps highlight matching parentheses and auto-close them, but it doesn't have to be Emacs. I use the delimt-mate plugin with Vim and I never have to think about closing and balancing. I don't know what you mean by pain of altering functions.

Surely functional programmers must know about the dynamic programming algorithm for computing combinations?

What's the point of using SCHEME if it isn't good for general purpose use?
You may pick up some skills but most of them can be learned through any other language with skills in a good language.
CL is slightly more complex than SCHEME, sure but you can learn more with it.
You can pick up imperative, OOP, and functional using it AND you get skills in a general purpose language to boot!

Quite a few of my packages have it built in but I've never seen any making a big use of it.
Lua seems to be a bit more popular.

The closest I have seen to a practically useful Scheme are Guile and Racket. Scheme's problem is that it's so small that every implementation ends up being its own language, and with a fractured landscape you cannot build a good ecosystem. The real killer feature of a language like Python is not the language itself, it's the huge number of libraries. The R7RS large standard might finally give us a practical language, but that's still years off. In the meantime just stick with Racket.

Lua was designed for embedding from day one, while Guile is recommended to be extended. With Lua you just compile the library, stick it into your program and done. Guile tries to be actually useful on its own, but it seems to be stuck in an awkward spot in between embedding and extending.

Your function looks the same but does literally nothing. It doesn't come close to the function I posted and I'm not sure what it was supposed to do other than look the same.

It's not the same because it's not equivalent.

My point was the syntax is hardly easy to use when you need a plugin. It's might be simple to understand but it isn't easy to use.
By alter I mean like you could easily add/remove a conditional in a lot of languages but in Lisp/Scheme, and others too, it's a huge pain. In Lisp/Scheme because you need to nest everything, so find the right depth which is never obvious and then match the parens. For example try commenting out a conditional, you'll probably find that is yet another reason to use even more functions.
Also before you say plugin again I get it but it's the equivalent of saying Java is easy to write because you use an auto-complete IDE.

I wouldn't really say it's in an awkward spot. JavaScript and Python both can be put in things AND work well on their own and no one ever talks about how they're in an odd spot.

pretty cool user

Do you mean "Determine language from source"? I am using the sicp package from the package manager. When I write (list 1 2 3 4) I get : (mcons 1 (mcons 2 (mcons 3 (mcons 4 '()))))

What is it? 1980? Go be a hacker in C or in assembly or something.

It fills an array with the numbers of the range. You have to pass the array as the first argument, which will decay into a pointer inside the function body. With each iteration the pointer to the "first" item is advanced by one. The only difference is that you have to pre-allocate the array (on the stack or heap) because arrays are not first-class objects in C.

I had installed that plugin even before I knew what Lisp is. Every decent programmer's editor should have this feature. Every syntax is shit without the editor helping you. Could you imagine manually inserting indentation in Python?

In Racket you can place #; in front of an S-expression and it will be commented out, regardless of how many lines it takes. Otherwise, just put the expression on its own line and add a ; in front of it. It's easier than commenting out expressions in C.

JavaScript is made for embedding though. Node.js is just an interpreter that embeds JavaScript and adds a bunch of its own stuff. Python can be embedded, but it's usually not encouraged. I remember the OpenMW project lead being very adamantly against Python because it would open all sorts of security concerns unless they went out of their way to make it secure. Lua is secure by default and you would have to go out of your way to make it unsecure. Here is a good talk about Lua.

The Scheme equivalent of Lua would be Chibi Scheme. Even Andy Wingo, the SJW faggot who is maintaining Guile, recommends Chibi for embedding:

Why not just create a Python-like language that is 100% functional?

Any more one-page resources like this, but for Python and Haskell?

lol the function really does nothing. I know Holla Forums isn't known for programming but seriously.

Pretty sure you are trolling now.

Oh great, so I forgot a line while I was hastily writing a reply on an image board. Have a (you) and the working function:
void range(int *arr, int a, int b) { if (a > b) { return; } else { arr[0] = a; range(++arr, ++a, b); }}
Now if you want to be really fancy you could also write
(arr++)[0] = a++;range(arr, a, b);

Yep you just need to also build the list recursively now. Then we can see how it looks the same in any language.

Is your dildo stuck up too deep in your ass or why are you so anal? Here you go:
struct node { struct node *next; int value;}struct node *range(int a, int b) { if (a > b) { return NULL; } else { struct node *node = malloc(sizeof (struct node)); node.value = a; = range(++a, b); return node; }}

Rate my c code. i made it for generating every 4 number permutation of 0-9 i needed it for making a bruteforce dictionary of PINs


int X;
while (X < 10){
printf ("000%d\n", X);
X = X + 1;
while (X < 100){
printf ("00%d\n", X);
X = X + 1;
while (X < 1000){
printf ("0%d\n", X);
X = X + 1;
while (X

You have 3 unnecessary loops and are not initialising X to 0.

int X=0;while(X < 10000)printf("%.4d\n", X++);

Why would you need a dictionary for bruteforcing pins? Unless you can determine patterns of commonly used "phrases" a dictionary has no use.

Have fun. Keep programming!

Is there an advantage to initialising x to 0? it seems like it's unnecessary. i need the pins for cracking student email at my school, the default password scheme is 'schoolname'pw0000, 0000 being a random pin.

It's not so much that there is an advantage to it, but it is absolutely fucking necessary. In C the initial value of a variable is undefined, which means it can literally be anything. The value could depend on the current moon phase for all you know and it would be legal. It could even be 10000, which would cause the loop to not even run once.

That said, if you don't need the variable X outside the loop you should use a for-loop for more idiomatic code:
for (int X = 0; X < 10000; ++X) { printf("%.4d\n", X)}
And always remember to surround the body of a loop in curly braces just in case.

How do I turn this C thread back into a Lisp thread?

it *was* nice of British Telecom to force Sun to rename their white pages service to be something other than "yp") ...A crying shame too. After all, even though Sun's "yellowpages" service was really a white pages (name lookup)service, they should have been able to use whateverdeceptive name they wanted. Renaming things for marketposition is really a modern (not just unix) tradition:Build a presentation manager: call it Presentation Manager...Build a personal computer: call it The ibm Personal Computer...Build a machine with an 8-bit byte: Define "byte" to be 8 bits...Build a IO subroutine package: call it DOS (an OS).But the unix weenies have refined it to a high art.Everything must be "open" and a "standard." Why, my companyalready supports at least a dozen "standards!"The latest Sun entry is their new "free" window system.Their salesman called me proudly: all you need to do is sendthem a thousand dollars a copy, plus pay a royalty onprograms which use it, and you can use their new free openstandard window system (called "open look" of course).Hm, maybe I can add cons to C and call the result Lisp...

Where to begin with Lisp? Let's start there. Is it really easy enough to learn Scheme if lower level stuff like C scares me as a total noob?


Lisp is not a language, but a family of languages. The three main relevant Lisps today are Common Lisp, Scheme and Clojure. Scheme is really neat and SICP is a good book. Just keep in mind that SICP is not a Scheme book, it's a computer science book that just happens to use Scheme. It's not about learning Scheme, it will instead teach you how to think about programming in general and the knowledge you gain you will be able to transfer to other languages. Make sure you do the exercises though.

You will need a Scheme implementation to follow along. I recommend Racket and the SICP language package.

I'd really appreciate it if you wouldn't throw Common Lisp, Scheme and Clojure together. CL and Scheme have almost nothing in common and Clojure is more of wrapper over Java than a Lisp.

I'm working on 1.29 from sicp and I'm a little confused why my solution won't run properly. I'm supposed to write a program which uses Simpson’s Rule to calculate integrals, but I just get 1 for everything.

(define (S b a f n) (integral b a f n 0))(define (integral b a f n k) (define (h b a n) (/ (- b a) n) ) (define (y f a n h) (f (+ a (* h k))) ) (cond ((

(integral b a f n 0) ;; k = 0((

I often see Berkley's SICP lectures recommended over Sussman's (MIT). Which do you prefer?

wow there was actually a whole load of stupid issues, that's a bit embarrassing, thanks user.
(define (S f b a n) (integral f b a n 0))(define (integral f b a n k) (define (y f b a n k) (f (+ a (* (/ (- b a) n) k))) ) (cond ((>= k n) 1) ((= n 0) (+ (y f b a n k) (integral f b a n (+ k 1)))) ((even? n) (+ (* 2 (y f b a n k)) (integral f b a n (+ k 1)))) (else (+ (* 4 (y f b a n k)) (integral f b a n (+ k 1)))) ))

I've not seen the Berkley lectures but I really like the Sussman lectures so if they are roughly equal you can't go wrong. Just pick one and get started :)

I'm going through Sussman, but have often heard Berkley's are better.

Not the same user but try giving meaningful names to your variables and procedures.
It doesn't cost anything and it'll make your code more readable

I only do this in scheme, I'm not sure why, I guess because it feels mathy. I'll fix it.

I wouldn't worry about it tbh, if you're already working through one you should probably stick with it.

I'm just interested to see if anyone has an opinion on it, I'll likely utilize it down the road at some point as some sort of review and come to my own conclusion then.