I only got to read SICP almost a decade after finishing my degree, it wasn't even a thing at my university. We got to learn FP via Caml Light, Standard ML, pure lambda calculus and we also had some LP classes via Prolog. Those of us that learned Lisp did it to customize Emacs.
> Caml Light, Standard ML, pure lambda calculus The first two being based lisp, and the third being what inspired lisp. It's like saying: I learned low level imperative programming from using Go, C++, and register machines. Which, sure, but the C language was hugely influential to all of that.
The objections the author had way back in the day are no longer the objections programmers of mainstream languages have to Lisp today. Today the objections I hear are more along the lines of: 1 - All those parenthesis. (Still a top objection) 2 - Lisp doesn't look like or work like what I'm used to. 3 - Lisp doesn't have as many libraries as the most popular mainstream programming languages. 4 - There aren't nearly a…
7 - It's too easy to make a mess. And the mess made by brilliant people who are looking for any excuse to put higher order metaprogramming and functional concepts into production is considerable. 8 - It has consistently lost in the marketplace in the last 20 years. We had most top CS grads in North America groomed on SICP at one point in history. You'd think many of them would want to use Lisp in production. Many of…
To be fair, all code bases tend to be horrifying legacy systems if you wait long enough, and "long enough" is pretty much always shorter than the amount of time you'd want the system to still be in use.
I'm working on FFI for TXR Lisp. Until this morning, it was in the stage of "collection of working API functions, written in C, exposed with Lisp bindings". I have almost everything I want working, including callbacks. There is a decently rich type system which supports pointers that annotate data passing directions for automatic malloc and free, and this works in both directions: out calls and callbacks (closures).…
That's a great look-and-feel :) How does memory management work? Do you have self-destructing structures (AKA automatic pointers) on the Lisp side?
It's all manual memory management in the FFI layer, driven by the semantics of the type expressions. The type expression syntax is compiled to a tree of objects. Those objects are walked before and after a FFI call to do the right actions related to memory management, encoding and decoding. Any temporary buffers needed by FFI are cleaned up by it. The Lisp objects going in and out are stock Lisp objects without any special memory management related to FFI.
Indeed, posts like this are of historical interest, but today, take Python: dx = 0.0001 def deriv(f): return lambda x: (f(x + dx) - f(x)) / dx This works just the same as the author's example and looks even more like the calculus formula people are used to.
f(x + dx) does look more conventional than (f (+ x dx)), but (/ numerator denominator) looks more like the conventional fraction syntax than putting a / somewhere in the middle of a line.
f(x + dx) does look more conventional than (f (+ x dx)), but (/ numerator denominator) looks more like the conventional fraction syntax than putting a / somewhere in the middle of a line.
I'll give you that but also, ask 100 random people what "3/4" means and what "(/ 3 4)" means.
Racket (and others?) gives you a sugar of (n . / . d) to infix any two-arg function if that's a stumbling block.
For (2) ( "Lisp doesn't look like or work like what I'm used to" ) I have something: * Lisp does look quite a bit like stuff you're used to: foo(bar(arg, (foo (bar arg arg arg2), arg2) arg2 xyzz()); (xyzz)) * Lisp does actually work a lot like stuff you are used to: evaluation of argument expressions to argument values, which are passed by value: much like C or Java. Functions return a value or multiple values. It ha…
> Lisp lists lack encapsulation; they are not opaque bags with which you do things like (add list item). That takes getting used to: always capturing the result value of a list construction. You're conflating two properties: lack of encapsulation and functional update. It's true that lists expose their internal structure as conses, and it's also true that they're usually updated functionally (requiring, as you say, c…
You're right; encapsulation doesn't mean mutable state; it means combining code and data (making a capsule).
Lisp list aren't ... whatever you call those stateful collection things that you can mutate with a list.add(42) type code that people are used to in a lot of scripting languages nowadays. That will trip up people who are used to that sort of thing.
>> 1 - All those parenthesis. (Still a top objection) > If you actually count parens fairly you will find that Lisp has no more than any other language Bull. For example, compare the Lisp factorial function from the article: (define (fact x) (if (zero? x) 1 (* x (fact (- x 1))))) with the corresponding F# implementation: let rec fact x = if x = 0 then 1 else x * fact (x - 1) That's 7 vs. 1 pair of parens. Also, the p…
Try putting the closing parens on a line aligned with the opening one, as if they were K&R style closing braces (ignoring that open-paren goes before keyword/func-name, rather than after ) (define (fact x) (if (zero? x) 1 (* x (fact (- x 1))) ) ) Square brackets work in some dialects, as well: [define (fact x) (if (zero? x) 1 (* x (fact (- x 1 ]
Almost all Lisp code will put the closing parens all together at the end. And the idea is to not care about how many there are by using an editor that provides the appropriate assistance.
I only got to read SICP almost a decade after finishing my degree, it wasn't even a thing at my university. We got to learn FP via Caml Light, Standard ML, pure lambda calculus and we also had some LP classes via Prolog. Those of us that learned Lisp did it to customize Emacs.
> Caml Light, Standard ML, pure lambda calculus The first two being based lisp, and the third being what inspired lisp. It's like saying: I learned low level imperative programming from using Go, C++, and register machines. Which, sure, but the C language was hugely influential to all of that.
What does ML, initially developed for theorem proving, have to do with Lisp?
7 - It's too easy to make a mess. And the mess made by brilliant people who are looking for any excuse to put higher order metaprogramming and functional concepts into production is considerable. 8 - It has consistently lost in the marketplace in the last 20 years. We had most top CS grads in North America groomed on SICP at one point in history. You'd think many of them would want to use Lisp in production. Many of…
SICP uses Scheme, which is not Lisp. It was taught at an introductory level because some concepts of computation can be taught nicely with Scheme, up to making a compiler for another language (perhaps a "real" language in the student's minds?), but it doesn't actually teach you Lisp, and I imagine leaves a bad taste in many students' mouth at the nonsense no-for-looping-no-mutation they had to suffer through which is…
Not only does SICP use Scheme, but it uses a really old and primitive Scheme, so that's what a lot of students who've only had exposure to SICP think all Schemes are like -- almost a toy language. They usually have no idea what a modern, full-featured Scheme like Chicken Scheme or Racket is like: light years ahead of the Scheme used in SICP, with a rich ecosystem of libraries.
This was back in 1983 where most (all?) other languages did not have first-class procedures. If you can imagine programming without them and then being exposed to that, it would be a big deal. We take them for granted today.
Well, in 1992 (IIRC), I did a numerical integration in C. For a "first class function", it just took a function pointer. That approach would have been available in C in 1983...
And indeed it was: qsort() takes a lambda as a parameter, and it's probably as old as C itself.