[HN Gopher] SICP in JavaScript
       ___________________________________________________________________
        
       SICP in JavaScript
        
       Author : behnamoh
       Score  : 129 points
       Date   : 2023-07-23 16:15 UTC (6 hours ago)
        
 (HTM) web link (sourceacademy.org)
 (TXT) w3m dump (sourceacademy.org)
        
       | decafbad wrote:
       | I thought my hatred of Javascript was at its peak.
        
       | paradite wrote:
       | I took this course as "CS101" back in 2013 in NUS. I've also been
       | coding in JS for the past 10 years.
       | 
       | Pretty happy with the content and the way it was taught.
        
       | IAmPaigeAT wrote:
       | I don't know if anyone has bothered to point this out but you
       | could keep your schemey SICP and go clojurescript if you wanna
       | run on JavaScript but then again you still have to contend with
       | cycles and reverse polish
        
       | LiamPowell wrote:
       | It seems like they have attempted to write scheme using
       | JavaScript syntax to avoid having to make any significant changes
       | to the non-code sections of the book.
       | 
       | Here is an excerpt, it's not good:                   function
       | deriv(exp, variable) {             return is_number(exp)
       | ? 0                    : is_variable(exp)                    ?
       | is_same_variable(exp, variable) ? 1 : 0                    :
       | is_sum(exp)                    ? make_sum(deriv(addend(exp),
       | variable),                               deriv(augend(exp),
       | variable))                    : is_product(exp)
       | ? make_sum(make_product(multiplier(exp),
       | deriv(multiplicand(exp),
       | variable)),
       | make_product(deriv(multiplier(exp),
       | variable),
       | multiplicand(exp)))                    : error(exp, "unknown
       | expression type -- deriv");         }
       | 
       | Here is the original code:                   (define (deriv exp
       | var)           (cond ((number? exp) 0)
       | ((variable? exp)                  (if (same-variable? exp var) 1
       | 0))                 ((sum? exp)                  (make-sum (deriv
       | (addend exp) var)                            (deriv (augend exp)
       | var)))                 ((product? exp)                  (make-sum
       | (make-product (multiplier exp)
       | (deriv (multiplicand exp) var))                    (make-product
       | (deriv (multiplier exp) var)
       | (multiplicand exp))))                 (else
       | (error "unknown expression type -- DERIV" exp))))
        
         | thr0waway42069 wrote:
         | [flagged]
        
         | [deleted]
        
         | akavi wrote:
         | The tragedy of JS if blocks being statements not expressions is
         | made explicit here
        
           | 3cats-in-a-coat wrote:
           | What's wrong with ternary?
        
             | vorticalbox wrote:
             | Nothing but when you nest them a whole bunch they are far
             | harder to read and understand that if/else.
        
               | pipeline_peak wrote:
               | (is(((it any) harder than) this?))
        
               | 3cats-in-a-coat wrote:
               | I frankly find it hard to imagine an expression form of
               | if...else that's more readable than either the JS or
               | Scheme versions of the code.
               | 
               | In fact, I believe the problem with the JS example's
               | readability is the formatting. Here's how I'd format the
               | same code, and I find this quite readable:
               | function deriv(exp, variable) {             return
               | is_number(exp)                 ? 0                 :
               | is_variable(exp)                 ? is_same_variable(exp,
               | variable)                      ? 1                      :
               | 0                 : is_sum(exp)                 ?
               | make_sum(                     deriv(addend(exp),
               | variable),                      deriv(augend(exp),
               | variable)                 )                 :
               | is_product(exp)                 ? make_sum(
               | make_product(multiplier(exp), deriv(multiplicand(exp),
               | variable)),
               | make_product(deriv(multiplier(exp), variable),
               | multiplicand(exp))                 )                 :
               | error(exp, "unknown expression type -- deriv");         }
        
               | 6510 wrote:
               | Just for looksies.                   function
               | deriv(exp,v){           //v = variable;
               | if(is_number(exp) ){ return 0 }
               | if(is_variable(exp){ return is_same_variable(exp,v) * 1 }
               | if(is_sum(exp)){               a = deriv(addend(exp),v);
               | return make_sum(a,a)           }
               | if(is_product(exp)){              m = multiplier(exp);
               | c = multiplicand(exp);               a =
               | make_product(m,deriv(c,v));              b =
               | make_product(deriv(m,v),c));              return
               | make_sum(a,b)           }           return error(exp,
               | "unknown expression type -- deriv");         }
        
               | MrJohz wrote:
               | I'd possibly make it even more syntactically simple by
               | removing the braces for one-line if statements. I know
               | this can be a bit controversial, but for cases like this
               | where the block consists only of a return statement, and
               | where that statement fits on a single line (and where you
               | have a formatter and a linter that will prevent you from
               | writing indentation that doesn't match the semantics),
               | it's very useful for removing visual clutter.
               | 
               | That said, this is pretty much how I'd write it, and
               | seems a lot simpler than the heavily nested ternary (and
               | I say that as a fan of nested ternaries!)
        
               | lmm wrote:
               | Scala-style if expressions would be significatly more
               | readable IMO (particularly if you also had the feature of
               | allowing a block to be used as an expression).
               | function deriv(exp, variable) {             return
               | if(is_number(exp))                   0
               | else if(is_variable(exp))
               | if(is_same_variable(exp, variable))                     1
               | else                      0                 else
               | if(is_sum(exp))                   make_sum(
               | deriv(addend(exp), variable),
               | deriv(augend(exp), variable)                   )
               | else if(is_product(exp))                   make_sum(
               | make_product(multiplier(exp), deriv(multiplicand(exp),
               | variable)),
               | make_product(deriv(multiplier(exp), variable),
               | multiplicand(exp))                 )                 else
               | error(exp, "unknown expression type -- deriv");         }
        
               | vorticalbox wrote:
               | The 0 and 1 are completely unnecessary though in some of
               | these.
               | 
               | Example
               | 
               | is_same_variable(exp, variable) ? 1 : 0
               | 
               | If is_same_variable returns a truthy value then return 1
               | else 0.
               | 
               | We can remove that and it will still follow the same
               | while also being more readable
        
               | Jtsummers wrote:
               | It's calculating the derivative. 0 and 1 aren't used for
               | their truthiness, but as values. d/dx x becomes 1 and
               | d/dx y becomes 0 (the two cases, same variable and
               | different variable).
        
               | vorticalbox wrote:
               | JavaScript will coerc the types. 1+1 and true+true both =
               | 2
        
               | 3cats-in-a-coat wrote:
               | I'm not trying to change the code, I'm only formatting
               | it.
        
           | paulddraper wrote:
           | They are, but you use ?-: instead of if-else
        
             | Akronymus wrote:
             | That still doesn't make all blocks expressions.
             | 
             | In f# everything is an expression and it simplifies the
             | language a lot. The last value in a block is considered the
             | value "return" value of the whole block, which has the
             | knockon effect of getting rid of most returns, allows you
             | to check an if/else to return the same type and such. This
             | also works in conjunction with the type inference, so you
             | get an error when you try to return a string in one branch
             | and an int in another.
        
               | paulddraper wrote:
               | I understand. Scala is the same.
               | 
               | JavaScript has a limited form of that via the comma
               | operator.
        
         | Animats wrote:
         | Uh oh. That's like the original Numerical Recipes in C. All the
         | arrays had their first value as 1, instead of 0. It was a
         | conversion from FORTRAN, where arrays really did start at 1.
         | The Numerical Recipes authors provided an array allocator which
         | generated an address offset before the beginning of the array
         | to make that work. It was awful. I rewrote the algorithms I
         | needed with sane layout.
         | 
         | The whole point of SCIP was mathematical beauty. Losing that in
         | translation is not good.
        
         | dimaor wrote:
         | One thing I have learnt very well from rewriting a legacy PHP
         | code written by amateur teams is: never ever nest ternary
         | operations.
         | 
         | maybe it's only me, but it's really hard to reason about this.
        
           | fbn79 wrote:
           | If you use a good indentation is not bad... more concise and
           | clear than if/then/else
        
           | lioeters wrote:
           | One thing I have learned from reading $any_lang code written
           | by professional teams is: use nested ternary operations where
           | it makes sense to do so, to tersely express a series of
           | if/else conditions that simply return a value for each
           | condition.
        
           | formulathree wrote:
           | There is strict reasoning why ternary expressions are, in
           | fact, logically better than a typical if statement.
           | 
           | The reasoning is because ternary operations eliminate
           | programming singularities.
           | 
           | Example:                  var x;        if (someExpression) {
           | x = True;        }        //var x is undefined
           | 
           | Example 2:                  var x;        x = someExpression
           | ? true : false;        // use of ternary expression prevents
           | var x from ever being undefined.
           | 
           | The ternary expression forces you to handle the alternative
           | case while the if expression can leave a singularity. A hole
           | where x remains undefined.
           | 
           | Some people say ternary expressions are less readable. But
           | Readability depends on your "opinion." There are no hard
           | logical facts about this. So it's a weak-ish argument.
           | 
           | It is actual fact (ie not an opinion) that ternary
           | expressions are categorically more Safe then if-statements.
           | Therefore, they are factually better in terms of hard logical
           | metrics.
           | 
           | This is the reasoning behind nested ternary statements. It's
           | also one of the strange cases in programming where
           | superficial qualitative attributes of "readability" trumps
           | hard and logical benefits. The overwhelming majority of the
           | population will in fact find many nested ternary operations
           | highly unreadable and this "opinion" overrides the logical
           | benefit.
           | 
           | Usually though, to maintain safety and readability I just
           | alias boolean statements with variable names. The complexity
           | of a conditional expression can be reduced by modularizing
           | parts of it under a symbolic name, you don't necessarily have
           | to reduce complexity by forcing the conditional into the more
           | readable bracketed spatial structures favored by if-
           | statements.
           | 
           | Example:                  isXgreaterThanY = x > y;
           | isWlessThan2 = w < 2;        isSubExpressionTrue =
           | isXgreaterThanY & isWlessThan2 ? False : True;
           | isFactNotTrue = isSubExpressionTrue ? False : True;
           | 
           | Yes technically the ternary expressions are still nested in a
           | way here, but when reading this code you don't have to dive
           | in deep past the symbolic name.
           | 
           | Imagine if you have a boolean condition that relies on
           | multitudes of these sub expressions. By defining the final
           | statement as a composition of Named ternary expressions you
           | eliminate the possibility of a hole;... a singularity where
           | one alternative wasn't considered. In my opinion this is the
           | best way to define your logic.
           | 
           | If-statements, imo, should be reserved for functions that are
           | impure (void return type).. code that mutates things and
           | touches IO which is something you as a programmer should keep
           | as minimal and segregated away from the rest of your pure
           | logic as possible.
           | 
           | Example:                    if true:
           | sendDataToIO(data)               //the alternative of not
           | sending data to IO is not a singularity. It is also
           | required... a ternary expression makes less sense here.
           | 
           | Last but not least: The ternary expression is also a bit weak
           | because it only deals with two possible branches: True/False.
           | The safest and most readable primitive to deal with multiple
           | branches of logic is exhaustive pattern matching. Both Rust
           | and Haskell have a form of this. In rust, it is the match
           | keyword.
        
           | stevekemp wrote:
           | I implemented the Monkey programming language as described in
           | the book Writing An Interpreter In Go. Over time I extended
           | it to support different things, and one of the additions I
           | made was to add support for the ternary operator.
           | 
           | In my implementation nested ternary operators were a parse
           | error.
        
             | flir wrote:
             | I've been thinking about diving into that book next. Would
             | you recommend? My alternative is Crafting Interpreters by
             | Robert Nystrom.
        
               | stevekemp wrote:
               | I would recommend, the writing is clear and concise, and
               | there's a lot of coverage and emphasis on testing.
               | 
               | That said Nystrom's book has adorable drawings, and feels
               | more "passionate".
               | 
               | I've read both, but I only followed the go-book because I
               | was learning Golang at the time. No regrets.
        
           | mostlylurks wrote:
           | I see this opinion voiced all the time, and I can never
           | understand how people can struggle with something like nested
           | ternaries. Surely a straightforward use (i.e. not a weird
           | edge case) of very basic syntax shared by most widely used
           | programming languages shouldn't cause much of an issue?
           | 
           | It should also be easier to reason about nested ternaries
           | than an equivalent set of nested if-elses, because at least
           | with ternaries you know that every branch is an expression
           | resulting in some value (and statically typed languages
           | ensure that these values have the correct type), whereas if-
           | else blocks can contain anything, are likely (and in most
           | languages (which lack if-else expressions), forced) to mutate
           | things, and have no guarantee of producing the result that
           | you were expecting, unlike ternaries (especially in
           | statically typed languages).
        
             | Akronymus wrote:
             | Should ternaries be left or right associative?
        
               | chiyc wrote:
               | Right associative! It's just one of the many rites of
               | passage for people working with PHP to get bitten by its
               | left associative ternaries. Naked nested ternaries are
               | deprecated now, but maybe one day, PHP can have right
               | associative ternaries.
        
               | retrocryptid wrote:
               | Except when it's not, like in perl.
        
           | jrajav wrote:
           | Unfortunately there is no if-expression in JS so sometimes
           | it's awkward _not_ to use ternaries in multi-line statements
           | - for instance, when writing in an expression only context
           | like a string interpolation or JSX. It's also just annoying
           | to not be able to assign conditionally without using it,
           | instead of a more clear and readable if/else. It's one of the
           | more annoying nits of the Algol legacy.
           | 
           | Oh, but fully agreed, nested ternaries is right out. In fact,
           | usually in those other cases too, it's just annoying that
           | there's not a good alternative.
        
             | bluepod4 wrote:
             | Or use a switch statement?
        
               | accrual wrote:
               | There's something satisfying about converting if/else
               | tables to switch statements. I find them so much more
               | readable.
        
             | paddw wrote:
             | a function _if(cond, a, b) would probably have been better.
        
               | danShumway wrote:
               | Beat me to it :)
               | 
               | It's not the biggest thing in the world, and I don't want
               | to distract from the rest of the book, but this is a
               | situation where writing a one or two line helper
               | function:                 const _ = (cond, a, b) => cond
               | ? a : b;
               | 
               | would have made the code much more readable without much
               | downside that I can see -- at least to my subjective
               | opinion. Maybe I'm missing something.
               | 
               |  _Edit: comment below correctly points out that if it 's
               | important for you to avoid immediate evaluation, you'll
               | need to wrap your conditionals in functions._
        
               | Jtsummers wrote:
               | JS is not lazily evaluated so that means `a` and `b`
               | would both be evaluated regardless of the result of the
               | cond expression. To make a proper version you have to
               | complicate things by calling it like this:
               | _(cond, () => a, () => b)
               | 
               | And _ becomes:                 const _ = (cond, a, b) =>
               | cond? a(): b();
               | 
               | And it does matter in this case when looking at the last
               | condition which signals an error (does not return an
               | error value if I understand it correctly). In which case
               | your _ would raise an error even when not appropriate.
        
               | danShumway wrote:
               | That is an excellent point, thanks for pointing that out.
               | 
               | I'm not sure it matters here, the error you're pointing
               | out looks to be getting returned (unless I'm
               | misunderstanding what the book intends the `error`
               | function to do), and creating an Error in Javascript is
               | fine, it doesn't break your program until it's actually
               | thrown.
               | 
               |  _Edit: just looked at your comment again, and you 're
               | saying it does actually throw the error rather than
               | returning it :) So double-corrected on my part :)_
               | 
               | But your point stands regardless. There will be scenarios
               | where what you're talking about matters -- JSX also
               | follows this pattern of immediate evaluation and yeah, I
               | see errors from that plenty of times. So it's good to
               | mention.
        
               | afiori wrote:
               | There is an example in the book showing why this would
               | not work, in short it is because js is not lazy
        
             | mrighele wrote:
             | If you want the equivalent of if-expression in JS, I think
             | it is much better to make a separate function with a number
             | of returns. In this case the function is already there:
             | function deriv(exp, variable) {         if (is_number(exp))
             | {           return 0;         }         if
             | (is_variable(exp)) {           if (is_same_variable(exp,
             | variable)) {             return 1;           } else {
             | return 0;           }         }         if (is_sum(exp)) {
             | return make_sum(deriv(addend(exp), variable),
             | deriv(augend(exp), variable));         }         if
             | (is_product(exp)) {           return
             | make_product(deriv(multiplier(exp),
             | variable),               multiplicand(exp)))         }
             | return error(exp, "unknown expression type -- deriv");
             | }
        
               | danShumway wrote:
               | It's subjective, but seconded (switch statements are also
               | great for this because they make fall-through logic more
               | obvious).
               | 
               | I'll add a couple of things onto this: early returns are
               | very helpful for me in avoiding nesting if statements
               | (although that's less applicable in this specific
               | example).                 function op(cond) {         if
               | (cond) {           //do something         }       }
               | function op (cond) {         if (!cond) { return; }
               | //do something       }
               | 
               | And it's good to remember that you can basically stick
               | functions anywhere including inline, so it's not
               | necessarily a requirement to take a function like this
               | and move it to a top level as a private function. If
               | you're only using it in one place you can just define it
               | and call it anonymously.
               | 
               | And don't be afraid to still use ternary operators non-
               | nested. There's a sibling comment complaining about the
               | nested if statement. If that really bothers you, you can
               | still do:                  if (is_variable(exp)) {
               | return is_same_variable(exp, variable) ? 1 : 0;        }
        
               | rezonant wrote:
               | Refreshing to see some love for early return. Often
               | people like to say they are an anti pattern, but then you
               | have to maintain each layer of if nesting in your head
               | (as they are sometimes off screen) when reasoning about
               | code in the middle instead of handling edge cases first
               | and leaving the rest of the method for the core/common
               | case.
        
               | paulddraper wrote:
               | if (is_same_variable(exp, variable)) {         return 1;
               | } else {         return 0;       }
               | 
               | should be                  return +is_same_variable(exp,
               | variable)
        
               | rezonant wrote:
               | Yeah, though might want to use
               | Number(is_same_variable(..)) for additional clarity.
        
               | thr0waway42069 wrote:
               | Get rid of the else in the is_variable(exp) block and
               | this is a lot more readable than the nested ternary
               | version and seems just as easy to transcode from Scheme.
               | Darn.
        
             | retrocryptid wrote:
             | Which is one of the reasons why it's difficult to interpret
             | javascript as suitably functional to apply SICP to it.
             | 
             | "Languages do not differ in what they make possible, but in
             | what they make easy."
        
       | andai wrote:
       | On my phone I just get a drawing of an alien spaceship? I tried
       | loading it through an archive (and I do get the front page of a
       | web book) but none of the links work there.
        
         | mi_lk wrote:
         | it's supposed to redirect to
         | https://sourceacademy.org/sicpjs/index
        
           | andai wrote:
           | That's the page I'm on: https://files.catbox.moe/kyql13.png
        
         | bryanrasmussen wrote:
         | seems to be some sort of loader, I got that but then it turned
         | to the SICP in JavaScript cover - I did scroll so maybe it was
         | the onScroll event.
        
       | retrocryptid wrote:
       | I believe you have misinterpreted the phrase "functional
       | programming"
        
       | dang wrote:
       | Related:
       | 
       |  _SICP - JavaScript Version (2022) [pdf]_ -
       | https://news.ycombinator.com/item?id=30033052 - Jan 2022 (2
       | comments)
       | 
       |  _SICP: JavaScript Edition available for pre-order_ -
       | https://news.ycombinator.com/item?id=30016323 - Jan 2022 (117
       | comments)
       | 
       |  _SICP - Upcoming JavaScript Edition_ -
       | https://news.ycombinator.com/item?id=27737942 - July 2021 (2
       | comments)
       | 
       |  _Structure and Interpretation of Computer Programs - JavaScript
       | Adaptation_ - https://news.ycombinator.com/item?id=21822903 - Dec
       | 2019 (180 comments)
       | 
       |  _SICP JavaScript Going Public_ -
       | https://news.ycombinator.com/item?id=21779397 - Dec 2019 (1
       | comment)
       | 
       |  _SICP translated to JavaScript_ -
       | https://news.ycombinator.com/item?id=6385617 - Sept 2013 (107
       | comments)
        
       | neilv wrote:
       | If you want to work through SICP in Scheme, but don't have an
       | easy way to run MIT Scheme, we made a compatibility thing, so you
       | could do SICP using Racket (with your choice of editor/IDE,
       | including DrRacket):
       | 
       | https://docs.racket-lang.org/sicp-manual/
        
       | eelhazred wrote:
       | There is also the interactive version of SICP[0].
       | 
       | [0]: http://xuanji.appspot.com/isicp/
        
       | chris_wot wrote:
       | Wasn't JavaScript influenced by Modula-3?
        
         | marcus0x62 wrote:
         | And Scheme, but the code in this book makes clear the limits of
         | that influence (or, perhaps, proves the idea of "the medium is
         | the message" in the context of language design.)
        
       | graypegg wrote:
       | If you're using Safari, ironically there's a JS syntax error
       | preventing the site from redirecting from a picture of a
       | spaceship to the actual book.
       | 
       | https://sourceacademy.org/sicpjs/index is the URL you get
       | redirected to in other browsers. (It still doesn't work in
       | safari.)
        
       | lispisok wrote:
       | Why does everything have to be Javascriptified? Scheme is a big
       | part of the SICP experience and trying to do it in another
       | language you are losing a lot. Do people learn Javascript when
       | starting their web development career then refuse to learn
       | anything else? Getting stuck with JS in the browser is an
       | artifact of history and given how bad the language is we should
       | avoid spreading it yet the opposite is happening. Funny for an
       | industry that's allegedly about doing things as smart as possible
       | the lowest common denominator dominates.
        
         | fuzztester wrote:
         | >Funny for an industry that's allegedly about doing things as
         | smart as possible the lowest common denominator dominates.
         | 
         | Yes.
         | 
         | The key word here is _allegedly_.
         | 
         | It's like how people rue the fact (a meme by now) that the
         | _(self-described) allegedly_ smartest minds in the world are
         | desperately busy trying to, guess what, make people click more
         | on ads(!), while largely ignoring ethics like giving people a
         | choice about it, via opt-in rather than opt-out, confusing
         | legalese in Privacy Policies and Terms and Conditions, fine
         | print, etc.
        
       | lolinder wrote:
       | I started this book with coworkers and it fell really flat.
       | 
       | I haven't read the original, but knowing Scheme I could see why
       | the book would be structured the way it is. In JavaScript,
       | though, it really just doesn't work. The code is horribly non-
       | idiomatic for JS, and because JS isn't actually Scheme the order
       | of the concepts introduced doesn't make sense. When it does talk
       | about JavaScript, it's condescending towards it in ways that were
       | off-putting to my coworkers (we're a TS shop), which is weird
       | given that it's a book _in JS_.
       | 
       | Someday I'm going to get around to reading the original, but I
       | can't recommend this one.
        
         | Tade0 wrote:
         | Thanks for the heads-up - I'm not going to bother with this
         | piece then.
         | 
         | Anyone with strong opinions about mainstream programming
         | languages is automatically suspicious to me.
         | 
         | I mean, I get it - plenty more elegant and better thought-out
         | languages than JavaScript, with their practitioners pounding
         | the floor, saying "it should have been me - not him!".
         | 
         | But, ultimately, who can't write good code just because they're
         | not using their favourite language?
        
           | Sterm wrote:
           | Indeed which is why I write everything in machine code. What
           | sort of elitist could possibly think this is a bad idea?
        
       | shaunxcode wrote:
       | The only way this would work: chapter 0 writing a scheme in js.
       | And the the rest of the chapters are just the standard SICP.
        
       | jedberg wrote:
       | What I loved most about my class based on SICP was that I learned
       | a whole new way to reason about code, and that came from using
       | Scheme. They changed the intro class at Berkeley to use Python a
       | while back, when the folks who knew lisp/scheme retired, and I
       | think it made the class much worse.
       | 
       | This is really the death knell of SICP isn't it?
        
         | horeszko wrote:
         | I think the Scheme version of SICP will live on outside of
         | academia and CS undergrad studies.
         | 
         | I'm using SICP for self-learning and I had the choice of
         | Scheme, JS, or Python. I still chose Scheme.
         | 
         | This is because I figured Scheme would offer something those
         | other languages didn't since Scheme is the original language of
         | the book and Scheme is just "different" than other languages.
         | It forces you to think differently about programming.
         | 
         | I'm glad I chose Scheme. SICP with Scheme is the best choice
         | imo since Scheme most clearly illustrates the lessons of the
         | book.
        
           | linguae wrote:
           | I actually used SICP when teaching a junior-level course on
           | programming language principles and paradigms at San Jose
           | State University, where the introductory language is Java. My
           | students programmed largely in Scheme and Prolog, and they
           | also got exposure to Haskell, Smalltalk, and Common Lisp.
           | 
           | I still believe there is room for SICP in the CS curriculum.
           | While as an introductory language SICP and Scheme may lose
           | out to more commercially popular languages like Python and
           | Java, I still believe that eventually students should be
           | exposed to Scheme as an introduction to functional
           | programming and to demonstrate a minimal, highly flexible
           | language as a vehicle for teaching programming language
           | design and implementation. Then eventually the students can
           | be introduced to the world of statically-typed functional
           | programming languages like the ML family and Haskell.
        
           | Lyngbakr wrote:
           | What's deterring me from pulling the trigger on the Scheme
           | version is the price. CAD$87 seems a bit steep for a
           | paperback edition that's almost 30 years old. The JavaScript
           | version is CAD$20 cheaper.
        
             | Jtsummers wrote:
             | Fortunately it's also freely available online. But if you
             | know anyone in the US, you can get it a lot cheaper (though
             | still paperback): https://www.amazon.com/Structure-
             | Interpretation-Computer-Pro...
             | 
             | Even having them ship it to you will probably be cheaper
             | than that CAD price. It's unfortunate the price has shot up
             | so much, I guess I'll be taking very good care of my
             | hardback edition.
             | 
             | https://mitp-content-
             | server.mit.edu/books/content/sectbyfn/b...
        
             | bamfly wrote:
             | Seeing a lot of $25-45 (USD) used price.
             | 
             | Used books are awesome. I have north of 500 books and I
             | doubt more than 50 were purchased new. Only that many
             | because some of my relatives want Christmas and birthday
             | wishlists every year, but won't shop anywhere but Amazon
             | and think it's weird to buy someone a used book as a gift
             | (I'd rather have 2-3x as many books for the same money, but
             | hey, I'm not the one paying, so whatever, I guess).
        
               | whartung wrote:
               | SICP, as a book, is very nice. It's a great size, not too
               | big, light and nimble to carry around. Many books,
               | notably text books, are pretty big and ungainly. But SICP
               | is just a really nice package. (Mind, I have not seen the
               | paperback, I have a hardback from _mutter mumble_ years
               | ago.)
        
               | Lyngbakr wrote:
               | I ended up at Alibris. CAD$45 + CAD$15 shipping for 'very
               | good' condition.
        
         | mathisfun123 wrote:
         | You know how people love to repeat that old saw about how
         | computer science is no more about computers than astronomy is
         | about telescopes (or whatever it is)? Well ironically (because
         | it's the same exact people but this time on the other side of
         | the misunderstanding) SICP is no more about scheme/lisp than
         | computer science is about computers.
        
           | jedberg wrote:
           | SICP is not about scheme or lisp, but its concepts are best
           | understood in scheme in lisp. Just like the best way to
           | understand what Saturn looks like is to look at it though a
           | telescope.
           | 
           | Sure you can use a spectrum scan or the output of a radio
           | telescope, but it's really not the same as looking at in a
           | telescope.
           | 
           | Same thing here -- SICP just isn't the same if it's not in
           | scheme or lisp.
        
             | mathisfun123 wrote:
             | > Just like the best way to understand what Saturn looks
             | like is to look at it though a telescope.
             | 
             | So then astronomy is about telescopes...?
             | 
             | I'm happy to accept SICP is intimately related to lisp
             | (which means it is less general than people claim) but just
             | as long as we're consistent.
        
               | [deleted]
        
           | lolinder wrote:
           | I've tried to go through the JS version, and I have to
           | disagree. I know enough Scheme to see why the book is
           | structured the way it is, but it doesn't work well in JS. The
           | patterns that seem so natural in Scheme are contrived to the
           | point of being distracting in JavaScript.
        
       | anon115 wrote:
       | overrated asf in my opinion
        
       | rmbyrro wrote:
       | I might be wrong, but I feel like writing SCIP on JS is like
       | "Sustainable Energy using Oil."
       | 
       | Not quite the right analogy... JS isn't as bad as Oil. But you
       | get the idea...
       | 
       | Kinda... don't make sense?
        
         | dgb23 wrote:
         | Projects like this (there's also a Python variation) are the
         | best examples of the difference in expressiveness.
        
         | fuzztester wrote:
         | >writing _SCIP_ ...
         | 
         | Then you should probably SCIP SCIP.
        
         | convolvatron wrote:
         | from old an lisp neckbeard - python and js are both just lisps
         | with off syntax. the both fit pretty well. the reader is a
         | little funny.
        
       | baz00 wrote:
       | At no point in my entire existence would I subject myself to
       | JavaScript voluntarily ever again. I would write my own damn
       | scheme environment and use that instead of this.
        
         | baq wrote:
         | Typescript is very nice. Too bad the JavaScript underneath is
         | so... unprofessional.
        
       | rambojohnson wrote:
       | why
        
       | lispm wrote:
       | The early sad parts of "SICP in JavaScript" are especially
       | section 2.2.1 Representing Sequences and chapter 2.3 Symbolic
       | Data:
       | 
       | "All the compound data objects we have used so far were
       | constructed ultimately from numbers. In this section we extend
       | the representational capability of our language by introducing
       | the ability to work with strings of characters as data."
       | 
       | In SICP there were Lisp's symbolic expressions (s-expressions).
       | They were removed without even mentioning them...
        
       | jll29 wrote:
       | I think SICP and Scheme go together like horse and carriage, and
       | neither Python, JavaScript or other "real world" languages should
       | taint the insight gained from that wonderful pairing.
       | 
       | Because Scheme - being a LISP - has the same syntax for code and
       | data, metalinguistic abstraction is facilitated. Nobody should
       | have to read through boilerplate code to dig up the core message
       | of SICP.
       | 
       | I took the Algorithmics I course based on SICP/Scheme in 1993 at
       | the University of Erlangen, and although I never used Scheme or
       | CommonLISP in production, it made me a better programmer
       | regardless in what language. Thanks to Abelson and Sussman!
        
         | hinkley wrote:
         | I think SICP would be just peachy in Elixir, but I'm coming
         | around to the notion that keeping functional programming for
         | functional programmers is a form of professional neglect.
         | 
         | Functional core, imperative wrapper is one of the few sane ways
         | to build a large (Conway's Law afflicted) system, and too many
         | of my peers never studies SICP in school. They don't even know
         | the damage they do, and as we've learned in many, many other
         | circles, vilifying people does not get them to change. It's a
         | tool of last resort, and most often used to publicly label
         | someone for ostracism, not help.
         | 
         | So excuse me, but y'all are crazy. We need SICP for JavaScript
         | developers more than we need SICP for every functional language
         | in the world, combined. And JavaScript is only one corner of
         | the programming world.
         | 
         | Write functional code in a language that does not force you to
         | write functional code. Take the training wheels off. Live in
         | the real world.
        
           | Sterm wrote:
           | Scheme is not a functional programming language. The last
           | 2/3rds of sicp are possible only because you can mutate
           | state.
        
         | zelphirkalt wrote:
         | In most implementations neither Python nor JS (except perhaps
         | partially in Safari) is up to the task of even running the code
         | of SICP properly, due to not having things like TCO.
         | 
         | So the code for versions of the book written using those
         | languages would need to be restructured, losing a big chunk of
         | elegance and possibly destroying the actual lessons about how
         | to express oneself as a computer programmer.
        
       ___________________________________________________________________
       (page generated 2023-07-23 23:00 UTC)