Lisp

{"content":{"id":581,"title":"'Build Your Own Lisp' Solutions: 4.4","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What does the \\n mean in those strings?\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e '\\n' signifies a newline character, so the startup information doesn't appear on the same line as the first prompt.\u003c/p\u003e","publication_date":"2019-04-03T00:00:00.000Z","created_at":"2019-03-04T20:45:01.000Z","updated_at":"2019-03-04T20:45:01.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 4.4

Q: What does the \n mean in those strings?


A: '\n' signifies a newline character, so the startup information doesn't appear on the same line as the first prompt.

{"content":{"id":552,"title":"'Build Your Own Lisp' Solutions: 4.3","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Add an extra message to the \u003ci\u003eVersion\u003c/i\u003e and \u003ci\u003eExit\u003c/i\u003e Information.\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e...\r\nint main(int argc, char** argv) {\r\n\r\n puts(\"Lispy Version 0.0.0.0.1, Something Something Something\");\r\n puts(\"Press Ctrl+c to Exit. Happy Trails!\\n\");\r\n\r\n while (1) {\r\n\r\n /* Now in either case readline will be correctly defined */\r\n char* input = readline(\"lispy\u003e \");\r\n add_history(input);\r\n\r\n printf(\"No you're a %s\\n\", input);\r\n free(input);\r\n\r\n }\r\n\r\n return 0;\r\n}\r\n...\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-17T00:00:00.000Z","created_at":"2019-02-15T00:00:14.000Z","updated_at":"2019-02-15T00:00:29.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 4.3

Q: Add an extra message to the Version and Exit Information.


A:

...
int main(int argc, char** argv) {

  puts("Lispy Version 0.0.0.0.1, Something Something Something");
  puts("Press Ctrl+c to Exit. Happy Trails!\n");

  while (1) {

    /* Now in either case readline will be correctly defined */
    char* input = readline("lispy> ");
    add_history(input);

    printf("No you're a %s\n", input);
    free(input);

  }

  return 0;
}
...
{"content":{"id":527,"title":"'Build Your Own Lisp' Solutions: 4.2","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Change what is echoed back to the user.\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e...\r\n while (1) { \r\n /* Now, in either case, readline will be correctly defined */\r\n char* input = readline(\"something of my choice\u003e \");\r\n add_history(input);\r\n\r\n printf(\"%s\\n\", input);\r\n free(input); \r\n }\r\n...\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-09T00:00:00.000Z","created_at":"2019-02-06T19:10:26.000Z","updated_at":"2019-06-30T15:30:09.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 4.2

Q: Change what is echoed back to the user.


A:

...
  while (1) {    
    /* Now, in either case, readline will be correctly defined */
    char* input = readline("something of my choice> ");
    add_history(input);

    printf("%s\n", input);
    free(input);    
  }
...
{"content":{"id":517,"title":"'Build Your Own Lisp' Solutions: 4.1","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Change the prompt from \"lispy\u003e\" to something of your choice.\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e...\r\n while (1) {\r\n \r\n char* input = readline(\"something of my choice\u003e \");\r\n add_history(input);\r\n\r\n printf(\"No you're a %s\\n\", input);\r\n free(input);\r\n \r\n }\r\n...\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-02-04T12:00:00.000Z","created_at":"2019-02-01T19:02:26.000Z","updated_at":"2019-02-07T20:17:55.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 4.1

Q: Change the prompt from "lispy>" to something of your choice.


A:

...
  while (1) {
    
    char* input = readline("something of my choice> ");
    add_history(input);

    printf("No you're a %s\n", input);
    free(input);
    
  }
...
{"content":{"id":311,"title":"'Build Your Own Lisp' Solutions: 3.12","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What does the 'typedef' keyword do exactly?\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e 'typedef' lets you define a type, which is to say, it lets you give a new name to a pre-existing type (which can be useful for organizational/readability purposes), or to define a struct as a new type, unique to your program.\u003c/p\u003e","publication_date":"2018-10-10T02:00:00.000Z","created_at":"2018-10-09T17:32:06.000Z","updated_at":"2018-10-10T03:27:32.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.12

Q: What does the 'typedef' keyword do exactly?


A: 'typedef' lets you define a type, which is to say, it lets you give a new name to a pre-existing type (which can be useful for organizational/readability purposes), or to define a struct as a new type, unique to your program.

{"content":{"id":261,"title":"SICP Solutions - 1.8","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Newton's method for cube roots is based on the fact that if y is an approximation to the cube root of x, then a better approximation is given by the value:\r\n\u003c/p\u003e\r\n\u003cimg src=\"/uploads/c7.gif\" class=\"card-image\"\u003e\r\n\u003cp\u003e\r\nUse this formula to implement a cube-root procedure analogous to the square-root procedure. (In section 1.3.4 we will see how to implement Newton's method in general as an abstraction of these square-root and cube-root procedures.)\r\n\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e \r\n\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e;; The setup is the same, except for the names.\r\n(define (cbrt-iter guess x)\r\n (if (good-enough? guess x)\r\n guess\r\n (cbrt-iter (improve guess x)\r\n x)))\r\n\r\n(define (cube x)\r\n (* x x x))\r\n\r\n(define (good-enough? guess x)\r\n (\u003c (abs (- (cube guess) x)) 0.001))\r\n\r\n(define (cbrt x)\r\n (cbrt-iter 1.0 x))\r\n\r\n;; The formula in scheme.\r\n(define (improve guess x)\r\n (/ \r\n (+ (/ x (* guess guess)) (* 2 guess))\r\n 3))\r\n\r\n;; A few guesses.\r\n(display (cbrt 8))\r\n(newline)\r\n(display (cbrt 27))\r\n(newline)\r\n(display (cbrt 60))\r\n(newline)\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e2.0000049116755\r\n3.00000054106418\r\n3.91487458417134 ; My calculator gives 3.91486764117\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-09-15T03:00:00.000Z","created_at":"2018-09-08T03:13:03.000Z","updated_at":"2019-01-16T02:28:24.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=sicp\"\u003esicp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=scheme\"\u003escheme\u003c/a\u003e"}

SICP Solutions - 1.8

Q: Newton's method for cube roots is based on the fact that if y is an approximation to the cube root of x, then a better approximation is given by the value:

Use this formula to implement a cube-root procedure analogous to the square-root procedure. (In section 1.3.4 we will see how to implement Newton's method in general as an abstraction of these square-root and cube-root procedures.)


A:

;; The setup is the same, except for the names.
(define (cbrt-iter guess x)
  (if (good-enough? guess x)
    guess
    (cbrt-iter (improve guess x)
               x)))

(define (cube x)
  (* x x x))

(define (good-enough? guess x)
  (< (abs (- (cube guess) x)) 0.001))

(define (cbrt x)
  (cbrt-iter 1.0 x))

;; The formula in scheme.
(define (improve guess x)
  (/ 
    (+ (/ x (* guess guess)) (* 2 guess))
    3))

;; A few guesses.
(display (cbrt 8))
(newline)
(display (cbrt 27))
(newline)
(display (cbrt 60))
(newline)
2.0000049116755
3.00000054106418
3.91487458417134 ; My calculator gives 3.91486764117
{"content":{"id":159,"title":"'Build Your Own Lisp' Solutions: 3.11","body":"\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What is the continue keyword and what does it do?\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e In a while or for loop, 'continue' will skip the rest of the block and go straight to the next iteration of the loop. Here is a program that counts to twenty, using 'continue' to filter out undesirable multiples of three:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n int i = 0;\r\n\r\n while (++i \u003c= 20) {\r\n if (i % 3 == 0) {\r\n continue;\r\n }\r\n printf(\"%d\\n\", i);\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e1\r\n2\r\n4\r\n5\r\n7\r\n8\r\n10\r\n11\r\n13\r\n14\r\n16\r\n17\r\n19\r\n20\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-07-08T06:00:00.000Z","created_at":"2018-07-01T16:39:40.000Z","updated_at":"2018-07-01T16:41:37.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.11


Q: What is the continue keyword and what does it do?


A: In a while or for loop, 'continue' will skip the rest of the block and go straight to the next iteration of the loop. Here is a program that counts to twenty, using 'continue' to filter out undesirable multiples of three:

#include <stdio.h>

int main(void)
{
  int i = 0;

  while (++i <= 20) {
    if (i % 3 == 0) {
      continue;
    }
    printf("%d\n", i);
  }

  return 0;
}
1
2
4
5
7
8
10
11
13
14
16
17
19
20
{"content":{"id":158,"title":"'Build Your Own Lisp' Solutions: 3.10","body":"\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What is the break keyword and what does it do?\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e Break breaks out of a while loop or a for loop, from within the body of that loop. Here is a program that will run a loop over nine quintillion times on most computers, before the number gets too bug for 'unsigned int' and goes back to zero:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n unsigned int i = 0;\r\n\r\n while (++i) {\r\n printf(\"%d: Looping...\\n\", i);\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e1: Looping...\r\n2: Looping...\r\n3: Looping...\r\n4: Looping...\r\n5: Looping...\r\n6: Looping...\r\n7: Looping...\r\n8: Looping...\r\n9: Looping...\r\n10: Looping...\r\n...\r\n9223372036854775806: Looping...\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eSince nine quintillion is overkill for most programs, we can use a break statement to stop it at, say, three.\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n unsigned int i = 0;\r\n\r\n while (++i) {\r\n printf(\"%d: Looping...\\n\", i);\r\n if (i == 3) {\r\n break;\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e1: Looping...\r\n2: Looping...\r\n3: Looping...\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-07-08T03:00:00.000Z","created_at":"2018-07-01T16:28:48.000Z","updated_at":"2018-07-01T16:31:55.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.10


Q: What is the break keyword and what does it do?


A: Break breaks out of a while loop or a for loop, from within the body of that loop. Here is a program that will run a loop over nine quintillion times on most computers, before the number gets too bug for 'unsigned int' and goes back to zero:

#include <stdio.h>

int main(void)
{
  unsigned int i = 0;

  while (++i) {
    printf("%d: Looping...\n", i);
  }

  return 0;
}
1: Looping...
2: Looping...
3: Looping...
4: Looping...
5: Looping...
6: Looping...
7: Looping...
8: Looping...
9: Looping...
10: Looping...
...
9223372036854775806: Looping...

Since nine quintillion is overkill for most programs, we can use a break statement to stop it at, say, three.

#include <stdio.h>

int main(void)
{
  unsigned int i = 0;

  while (++i) {
    printf("%d: Looping...\n", i);
    if (i == 3) {
      break;
    }
  }

  return 0;
}
1: Looping...
2: Looping...
3: Looping...
{"content":{"id":132,"title":"'Build Your Own Lisp' Solutions: 3.9","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What is the switch statement and how does it work?\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e A switch statement syntactic sugar for certain combinations of 'if' and 'else', which is typically used where there are very many different possible conditions.\u003c/p\u003e\r\n\u003cp\u003eIt is wildly controversial. Some feel that it is extremely convenient and clear, others feel that it can cause unexpected bugs (and they dislike it for other reasons a bit too technical for this post). I'm part of the former group, but I sympathize with the latter.\u003c/p\u003e\r\n\u003cp\u003eHere is an example:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nvoid c_finder(char c)\r\n{\r\n switch(c) {\r\n case 'a':\r\n case 'b':\r\n printf(\"The letter is too small!\\n\");\r\n break;\r\n case 'c':\r\n printf(\"The letter is just right!\\n\");\r\n break;\r\n default:\r\n printf(\"The letter is too large!\\n\");\r\n }\r\n}\r\n\r\nint main(void)\r\n{\r\n c_finder('a');\r\n c_finder('b');\r\n c_finder('c');\r\n c_finder('z');\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003eThe letter is too small!\r\nThe letter is too small!\r\nThe letter is just right!\r\nThe letter is too large!\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eThat switch statement is equivalent to:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e if (c == 'a' || c == 'b') {\r\n printf(\"The letter is too small!\\n\");\r\n } else if (c == 'c') {\r\n printf(\"The letter is just right!\\n\");\r\n } else {\r\n printf(\"The letter is too large!\\n\");\r\n }\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eNotice that 'switch' only tests equality with a constant. Something like 'else if (a \u003e b)' doesn't really have a direct equivalent.\u003c/p\u003e\r\n\u003cp\u003eThe reason some people dislike switch is the fall-through behaviour in the example. If a case is true, switch will execute all code down to the next 'break'. If you forget to write your breaks, you can end up with unexpected bugs. I think switch can be a useful tool, and can make code more readable, but caution and discipline are heavily recommended.\u003c/p\u003e","publication_date":"2018-06-28T15:00:00.000Z","created_at":"2018-06-21T22:56:32.000Z","updated_at":"2020-07-11T13:49:22.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.9

Q: What is the switch statement and how does it work?

A: A switch statement syntactic sugar for certain combinations of 'if' and 'else', which is typically used where there are very many different possible conditions.

It is wildly controversial. Some feel that it is extremely convenient and clear, others feel that it can cause unexpected bugs (and they dislike it for other reasons a bit too technical for this post). I'm part of the former group, but I sympathize with the latter.

Here is an example:

#include <stdio.h>

void c_finder(char c)
{
  switch(c) {
    case 'a':
    case 'b':
      printf("The letter is too small!\n");
      break;
    case 'c':
      printf("The letter is just right!\n");
      break;
    default:
      printf("The letter is too large!\n");
  }
}

int main(void)
{
  c_finder('a');
  c_finder('b');
  c_finder('c');
  c_finder('z');

  return 0;
}
The letter is too small!
The letter is too small!
The letter is just right!
The letter is too large!

That switch statement is equivalent to:

  if (c == 'a' || c == 'b') {
    printf("The letter is too small!\n");
  } else if (c == 'c') {
    printf("The letter is just right!\n");
  } else {
    printf("The letter is too large!\n");
  }

Notice that 'switch' only tests equality with a constant. Something like 'else if (a > b)' doesn't really have a direct equivalent.

The reason some people dislike switch is the fall-through behaviour in the example. If a case is true, switch will execute all code down to the next 'break'. If you forget to write your breaks, you can end up with unexpected bugs. I think switch can be a useful tool, and can make code more readable, but caution and discipline are heavily recommended.

{"content":{"id":117,"title":"SICP Solutions - 1.7","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e The good-enough? test used in computing square roots will not be very effective for finding the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always performed with limited precision. This makes our test inadequate for very large numbers. Explain these statements, with examples showing how the test fails for small and large numbers. An alternative strategy for implementing good-enough? is to watch how guess changes from one iteration to the next and to stop when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of end test. Does this work better for small and large numbers?\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e This is best demonstrated through examples using perfect squares:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e\u0026gt (sqrt 1000000000000)\r\n1000000.0\r\n\u0026gt (sqrt 10000000000000)\r\n; Infinite loop. \r\n\u0026gt (sqrt 0.01)\r\n0.100325785109606\r\n\u0026gt (sqrt 0.001)\r\n0.0412454260749911 ; Good enough for government work.\r\n\u0026gt (sqrt 0.0001)\r\n0.0323084483304812 ; Uh oh!\r\n\u0026gt (sqrt 0.0001)\r\n0.0323084483304812\r\n\u0026gt (sqrt 0.00001)\r\n0.0313564901077172\r\n\u0026gt (sqrt 0.000001)\r\n0.0312606555254453\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eVery big numbers run into the limitations of your implementation of Scheme and/or how your machine handles decimals, and good-enough? doesn't work for numbers less than its threshold. Now, let's try changing good-enough? as the question suggests:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (good-enough? guess old-guess)\r\n (\u003c (abs (- guess old-guess)) (* guess 0.001)))\r\n\r\n; It's a good thing I already read Little Schemer,\r\n; because this book really glosses over recursion.\r\n(define (sqrt-iter guess old-guess x)\r\n (if (good-enough? guess old-guess)\r\n guess\r\n (sqrt-iter (improve guess x) guess x)))\r\n\r\n(define (sqrt x)\r\n (sqrt-iter 1.0 2.0 x))\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e\u0026gt (sqrt 1000000000000)\r\n1000000.10346124 ; Not better, but carrying on...\r\n\u0026gt (sqrt 10000000000000)\r\n3162277.66401048\r\n\u0026gt (sqrt 100000000000000) \r\n10000000.000044\r\n\u0026gt (sqrt 1000000000000000) \r\n31622779.2799952 ; And so on. Wowie!\r\n; Now the small numbers\r\n\u0026gt (sqrt 0.01)\r\n0.100000000001399\r\n\u0026gt (sqrt 0.001)\r\n0.031622782450701\r\n\u0026gt (sqrt 0.0001)\r\n0.0100000000254907\r\n\u0026gt (sqrt 0.00001)\r\n0.0031622776602039\r\n\u0026gt (sqrt 0.000001)\r\n0.00100000015330166 ; And so on.\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eThis new way is obviously better. To get some intuition as to why, you can modify the new good-enough? to print each iteration, and play around in a REPL. This post is already pretty long, so I'll leave it as an exercise to the answer-reader.\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (good-enough? guess old-guess)\r\n (display (abs (- guess old-guess)))\r\n (newline)\r\n (display (* guess 0.001))\r\n (newline)\r\n (newline)\r\n (\u003c (abs (- guess old-guess)) (* guess 0.001)))\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-06-26T15:00:00.000Z","created_at":"2018-06-20T16:33:23.000Z","updated_at":"2018-07-05T16:30:50.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=sicp\"\u003esicp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=scheme\"\u003escheme\u003c/a\u003e"}

SICP Solutions - 1.7

Q: The good-enough? test used in computing square roots will not be very effective for finding the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always performed with limited precision. This makes our test inadequate for very large numbers. Explain these statements, with examples showing how the test fails for small and large numbers. An alternative strategy for implementing good-enough? is to watch how guess changes from one iteration to the next and to stop when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of end test. Does this work better for small and large numbers?


A: This is best demonstrated through examples using perfect squares:

> (sqrt 1000000000000)
1000000.0
> (sqrt 10000000000000)
; Infinite loop. 
> (sqrt 0.01)
0.100325785109606
> (sqrt 0.001)
0.0412454260749911 ; Good enough for government work.
> (sqrt 0.0001)
0.0323084483304812 ; Uh oh!
> (sqrt 0.0001)
0.0323084483304812
> (sqrt 0.00001)
0.0313564901077172
> (sqrt 0.000001)
0.0312606555254453

Very big numbers run into the limitations of your implementation of Scheme and/or how your machine handles decimals, and good-enough? doesn't work for numbers less than its threshold. Now, let's try changing good-enough? as the question suggests:

(define (good-enough? guess old-guess)
  (< (abs (- guess old-guess)) (* guess 0.001)))

; It's a good thing I already read Little Schemer,
; because this book really glosses over recursion.
(define (sqrt-iter guess old-guess x)
  (if (good-enough? guess old-guess)
    guess
    (sqrt-iter (improve guess x) guess x)))

(define (sqrt x)
  (sqrt-iter 1.0 2.0 x))
> (sqrt 1000000000000)
1000000.10346124 ; Not better, but carrying on...
> (sqrt 10000000000000)
3162277.66401048
> (sqrt 100000000000000)   
10000000.000044
> (sqrt 1000000000000000)  
31622779.2799952 ; And so on. Wowie!
; Now the small numbers
> (sqrt 0.01)
0.100000000001399
> (sqrt 0.001)
0.031622782450701
> (sqrt 0.0001)
0.0100000000254907
> (sqrt 0.00001)
0.0031622776602039
> (sqrt 0.000001)
0.00100000015330166 ; And so on.

This new way is obviously better. To get some intuition as to why, you can modify the new good-enough? to print each iteration, and play around in a REPL. This post is already pretty long, so I'll leave it as an exercise to the answer-reader.

(define (good-enough? guess old-guess)
  (display (abs (- guess old-guess)))
  (newline)
  (display (* guess 0.001))
  (newline)
  (newline)
  (< (abs (- guess old-guess)) (* guess 0.001)))
{"content":{"id":116,"title":"'Build Your Own Lisp' Solutions: 3.8","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What is the do loop, and how does it work?\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e A do loop is like a while loop, except that it checks the while condition \u003ci\u003eafter\u003c/i\u003e the block. In practice, this means that the block will always execute at least once. For example:\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n int n = 1;\r\n\r\n while (n != 1) {\r\n printf(\"This will not be printed.\\n\");\r\n }\r\n\r\n do {\r\n printf(\"This will be printed.\\n\");\r\n } while(n != 1);\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003eThis will be printed.\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-06-26T12:00:00.000Z","created_at":"2018-06-19T23:16:51.000Z","updated_at":"2018-06-19T23:17:44.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.8

Q: What is the do loop, and how does it work?

A: A do loop is like a while loop, except that it checks the while condition after the block. In practice, this means that the block will always execute at least once. For example:


#include <stdio.h>

int main(void)
{
  int n = 1;

  while (n != 1) {
    printf("This will not be printed.\n");
  }

  do {
    printf("This will be printed.\n");
  } while(n != 1);

  return 0;
}
This will be printed.
{"content":{"id":115,"title":"'Build Your Own Lisp' Solutions: 3.7","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What other mathematical operators are there other than add +, and subtract -?\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e \"n += 3\" is equivalent to \"n = n + 3\". For example:\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n int a, b;\r\n a = b = 0;\r\n\r\n a = a + 3;\r\n b += 3;\r\n\r\n printf(\"%d\\n\", a);\r\n printf(\"%d\\n\", b);\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e3\r\n3\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-06-26T09:00:00.000Z","created_at":"2018-06-19T23:04:27.000Z","updated_at":"2018-06-19T23:06:38.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.7

Q: What other mathematical operators are there other than add +, and subtract -?

A: "n += 3" is equivalent to "n = n + 3". For example:


#include <stdio.h>

int main(void)
{
  int a, b;
  a = b = 0;

  a = a + 3;
  b += 3;

  printf("%d\n", a);
  printf("%d\n", b);

  return 0;
}
3
3
{"content":{"id":113,"title":"'Build Your Own Lisp' Solutions: 3.6","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e What other mathematical operators are there other than add +, and subtract -?\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e\r\n\u003cul\u003e\r\n\u003cli\u003e\r\n* multiplication\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n/ division\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n% modulo\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n++ increment by one\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n-- decrement by one\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2018-06-24T03:00:00.000Z","created_at":"2018-06-19T22:42:43.000Z","updated_at":"2020-08-05T16:54:42.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=build_your_own_lisp\"\u003ebuild_your_own_lisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e"}

'Build Your Own Lisp' Solutions: 3.6

Q: What other mathematical operators are there other than add +, and subtract -?

A:

  • * multiplication
  • / division
  • % modulo
  • ++ increment by one
  • -- decrement by one
{"content":{"id":109,"title":"SICP Solutions - 1.6","body":"\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Alyssa P. Hacker doesn't see why if needs to be provided as a special form. ``Why can't I just define it as an ordinary procedure in terms of cond?'' she asks. Alyssa's friend Eva Lu Ator claims this can indeed be done, and she defines a new version of if: \u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (new-if predicate then-clause else-clause)\r\n (cond (predicate then-clause)\r\n (else else-clause)))\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003e\r\nEva demonstrates the program for Alyssa:\r\n\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(new-if (= 2 3) 0 5)\r\n5\r\n\r\n(new-if (= 1 1) 0 5)\r\n0\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eDelighted, Alyssa uses new-if to rewrite the square-root program:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (sqrt-iter guess x)\r\n (new-if (good-enough? guess x)\r\n guess\r\n (sqrt-iter (improve guess x)\r\n x)))\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eWhat happens when Alyssa attempts to use this to compute square roots? Explain.\u003c/p\u003e\r\n\u003cbr\u003e\r\n\u003cp\u003e \u003cb\u003eA:\u003c/b\u003e The program hangs forever. This is a similar issue to the \u003ca href=\"https://sananab.ca/posts/106\" target=\"_blank\"\u003elast problem\u003c/a\u003e. Because of application order, it will continuously evaluate sqrt-iter in an infinite loop. Normal 'if' in Scheme is a special procedure built into the language and does not have that behaviour.\u003c/p\u003e","publication_date":"2018-06-23T03:00:00.000Z","created_at":"2018-06-17T17:53:06.000Z","updated_at":"2018-06-22T14:14:07.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=sicp\"\u003esicp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=scheme\"\u003escheme\u003c/a\u003e"}

SICP Solutions - 1.6


Q: Alyssa P. Hacker doesn't see why if needs to be provided as a special form. ``Why can't I just define it as an ordinary procedure in terms of cond?'' she asks. Alyssa's friend Eva Lu Ator claims this can indeed be done, and she defines a new version of if:

(define (new-if predicate then-clause else-clause)
  (cond (predicate then-clause)
        (else else-clause)))

Eva demonstrates the program for Alyssa:

(new-if (= 2 3) 0 5)
5

(new-if (= 1 1) 0 5)
0

Delighted, Alyssa uses new-if to rewrite the square-root program:

(define (sqrt-iter guess x)
  (new-if (good-enough? guess x)
          guess
          (sqrt-iter (improve guess x)
                     x)))

What happens when Alyssa attempts to use this to compute square roots? Explain.


A: The program hangs forever. This is a similar issue to the last problem. Because of application order, it will continuously evaluate sqrt-iter in an infinite loop. Normal 'if' in Scheme is a special procedure built into the language and does not have that behaviour.

{"content":{"id":106,"title":"SICP Solutions - 1.5","body":"\u003cbr\u003e\r\n\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (p) (p))\r\n\r\n(define (test x y)\r\n (if (= x 0)\r\n 0\r\n y))\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eThen he evaluates the expression:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(test 0 (p))\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eWhat behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e; Normal Order:\r\n(if (= 0 0) 0 (p))\r\n(if #t 0 (p))\r\n0\r\n\r\n; Applicative: Because the interpreter evaluates (p)\r\n; independently of any condition, you are stuck in\r\n; an infinite loop as each instance of (p) evaluates\r\n; (p), independently of the results of the if condition.\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-06-21T15:00:00.000Z","created_at":"2018-06-15T19:24:06.000Z","updated_at":"2018-06-22T02:37:27.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=sicp\"\u003esicp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=scheme\"\u003escheme\u003c/a\u003e"}

SICP Solutions - 1.5


Q: Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:

(define (p) (p))

(define (test x y)
       (if (= x 0)
           0
           y))

Then he evaluates the expression:

(test 0 (p))

What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)

A:

; Normal Order:
(if (= 0 0) 0 (p))
(if #t 0 (p))
0

; Applicative: Because the interpreter evaluates (p)
; independently of any condition, you are stuck in
; an infinite loop as each instance of (p) evaluates
; (p), independently of the results of the if condition.
{"content":{"id":92,"title":"SICP Solutions - 1.4","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e(define (a-plus-abs-b a b)\r\n ((if (\u003e b 0) + -) a b))\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e The procedure checks if b is greater than 0, and returns the addition procedure if true, giving us (+ a b), and the subtraction procedure if false, giving us (- a b).\u003c/p\u003e","publication_date":"2018-06-21T00:00:00.000Z","created_at":"2018-06-12T18:02:20.000Z","updated_at":"2020-07-06T19:08:51.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=sicp\"\u003esicp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=lisp\"\u003elisp\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=scheme\"\u003escheme\u003c/a\u003e"}

SICP Solutions - 1.4

Q: Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

A: The procedure checks if b is greater than 0, and returns the addition procedure if true, giving us (+ a b), and the subtraction procedure if false, giving us (- a b).