Live data from Hacker News

SICP in JavaScript

sourceacademy.org

31–40 of 126 posts

Re: SICP in JavaScript

#31
post #19

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) ? m…

The tragedy of JS if blocks being statements not expressions is made explicit here

What's wrong with ternary?

Re: SICP in JavaScript

#32
post #12

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) ? m…

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.

If you use a good indentation is not bad... more concise and clear than if/then/else

Re: SICP in JavaScript

#33

Earlier quoted context omitted.

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 ab…

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.

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...

Re: SICP in JavaScript

#34
post #29

Earlier quoted context omitted.

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.

I've been thinking about diving into that book next. Would you recommend? My alternative is Crafting Interpreters by Robert Nystrom.

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.

Re: SICP in JavaScript

#35
post #12

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) ? m…

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.

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.

Re: SICP in JavaScript

#36
post #12

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) ? m…

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.

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 
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.

Re: SICP in JavaScript

#37
post #20
post #16

Earlier quoted context omitted.

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,…

a function _if(cond, a, b) would probably have been better.

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.

Re: SICP in JavaScript

#38
post #20
post #16

Earlier quoted context omitted.

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,…

a function _if(cond, a, b) would probably have been better.

There is an example in the book showing why this would not work, in short it is because js is not lazy

Re: SICP in JavaScript

#39
post #3

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?

Projects like this (there’s also a Python variation) are the best examples of the difference in expressiveness.

Re: SICP in JavaScript

#40
post #20

Earlier quoted context omitted.

a function _if(cond, a, b) would probably have been better.

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…

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.
Post reply on HN