Chez Scheme is now free
github.com
github.com
I did SICP nearly 19 years ago as a freshman, in 1997. And then a few months ago, I ported the metacircular-evaluator -- the "crown" of the course -- to femtolisp (the Lisp implementation underlying Julia).
My thoughts were:
1) It sure is awkward to represent struct fields 1 2 3 as (cdr struct), (cadr struct), (caddr), ... Yes this is nice to show that car and cdr are all you need as axiomatic primitives, but for practical purposes it's annoying. You end up with lots of little functions with long names.
2) Scheme code is very imperative! Even the metacircular evaluator uses set-cdr! and so forth. I don't like imperative code with the Lisp syntax.
3) It is awkward to represent environments with assoc lists. I feel that having a language which is really bootstrapped requires some kind of hash table/dictionary. Because you need that to implement scopes with O(1) access rather than O(n). I believe there are experimental lisps that try to fix this.
4) Macros also seem to have a needlessly different syntax than regular functions. There are Lisps with f-exprs rather than s-exprs that try to fix this: https://en.wikipedia.org/wiki/Fexpr
I was surprised by #3 and #4 -- it some sense Scheme is less "meta" and foundational than it could be. #2 is also a fundamental issue... at least if you want to call it the "foundation" of computing and build Lisp machines; I think this is evidence that this idea is a fundamentally flawed. #1 just makes it pale into languages like Python or even JavaScript.
4: As I understand it, there are many macro systems available for Scheme. It's one of the languages in which "hygienic" macros has been explored, etc. So if you don't like the femtolisp bundled version, there might be another out there more to your taste.
Every Scheme implementation I know of supports record types aka SRFI-9[0]. No one actually makes new data types from cons cells.
>2) Scheme code is very imperative!
Scheme supports many programming paradigms. Imperative programming is one. Functional programming, object-oriented programming, and relational programming are others. Not all Scheme code is imperative.
>3) It is awkward to represent environments with assoc lists.
Every Scheme implementation I know of has traditional mutable hash tables. Sometimes you want a hash table, sometimes you want an alist. It depends.
>4) Macros also seem to have a needlessly different syntax than regular functions.
I don't really understand this point. Are you talking about syntax-rules? If so, then I must disagree. syntax-rules is a very elegant language for defining hygienic macros.
SICP does not teach you everything that Scheme has to offer, and the Scheme implementations of the 1980s are a lot different than the Scheme implementations of 2016.
But #2 and #3 are what I would call bootstrapping problems... in other words, there is a reason that C is the foundation of computing rather than Lisp. I don't think anybody really thinks otherwise anymore. But for example, set-cdr! is not in the lambda calculus, and you need it even for basic things.
Likewise, Scheme implementations have mutable hash tables, but they're written in C and not Scheme. I don't know how you even write a hash table based on cons cells rather than O(1) indexing.
Regarding #4, here is a good link. The basic idea is that macros could just be functions on lists, and then you get composition of macros like you have composition of functions. Paul Graham incorporated this into Arc.
http://matt.might.net/articles/metacircular-evaluation-and-f...
My point is you could say Scheme sits at a somewhat awkward place between "not foundational enough" (not fully bootstrapped) and "awkward in practice" (compared to say Python). Though I wouldn't go as far as to say that... Obviously it was groundbreaking work that influenced Python and R and tons of stuff we use today. It's outstanding research, but it feels like it has been almost fully incorporated into the computing culture now.
C is not the foundation of computing. Why would you say this?
>Likewise, Scheme implementations have mutable hash tables, but they're written in C and not Scheme.
A native code compiler written in Scheme would have its hash table implementation also written in Scheme.
>I don't know how you even write a hash table based on cons cells rather than O(1) indexing.
You wouldn't do that! Cons cells are not the only primitive data type! Another primitive type in Scheme is the vector, which is a mutable array.
I'm sorry, but you greatly misunderstand Lisp and how compilers work.
I guess I could have been more precise and said that the lambda calculus (rather than Scheme/Lisp) is not the foundation of computing. It seems like there are people who still think this; see my recent response here:
https://news.ycombinator.com/item?id=11412392
You could say Lisp and Scheme are proof of that. To actually be bootstrapped, they had to add all this other stuff like vectors and hash tables. I don't know the details of how well those are axiomatized. Paul Graham's Arc tried to a little further down, i.e. unifying functions and macros, defining numbers in terms of lists a la Peano arithmetic, etc., but I'm not sure how far that effort went.
I mentioned all my experience with Lisp... doing SICP 19 years ago, and then coming back to it. As I said, I think it's outstanding research, but if you are trying to build an entire computing universe out of it, that's folly. Good luck. It's just not powerful enough -- once you add all the stuff you actually need, you're not far from the complexity of C.
You are conflating minimalism with the Scheme language because Scheme is often used to illustrate minimalism. Vectors and hash tables are not "all this other stuff", they're part of the language spec[1]. You're also throwing Lisp in there even though minimalism is not a central theme of Lisp.
[1] When you did SICP hash tables were not part of the language spec although implementations generally had them; they got standardized in 2007 with R6RS. But vectors were in the language spec since at least 1985.
Just like C had to add things like arrays to the Turing machine? C doesn't even have hash tables in the spec! According to your definitions, C is a toy language.
cons cells are not sufficient to implement hash tables. Scheme needs arrays for that. cons cells can be implemented efficiently using arrays, but the converse isn't true, so arrays are more fundamental in some sense.
If you don't care about algorithmic efficiency, then you could choose either cons cells or arrays as your primitive. But obviously we do care, so arrays were the right choice. IOW, C was the right choice, not Scheme.
Because each architecture has a C compiler that's been highly optimized. Popularity plus money invested. That's it. If you were right, we'd see optimizations coded in C even when alternative, optimizing compilers were available. I got a one-word counter to that interestingly enough from "high-performance computing" field: FORTRAN. Free Pascal people are doing fine in performance and low-level code as well despite little to no investment in them.
Seems throwing money at a turd (eg FORTRAN, C) can get a lot of people's hands on it despite some of us shuddering and saying "Get that pile of crap away from me!"
One step above a portable macro assembler, developed in a decade where research labs outside AT&T were already using safe systems programming languages for about a decade.
Their big failure was that they were selling their work, instead of doing like AT&T that initially gave UNIX for free, because it was forbidden to sell it.
Unfortunately free always wins, regardless of quality.
Obviously a false statement.
Again, cons cells are not the only primitive type for making compound data structures.
Care to elaborate on that?
Because all the popular OSes, drivers, userlands, servers, GUI libraries, and compilers/languages are 99% written in C (or C++ which is close enough).
And the basis upon which computing sits upon.
Take away all C/C++ code and we have nothing or almost nothing.
Take away all Lisp/Scheme code and people will barely notice.
>Makes so much sense when I explain above that C's prevalence is due to social and economic reasons given you argued it won a popularity contest.
If by economic you mean "pragmatic" and "engineering considerations", then yes.
In that meaning, it's true but only as an accident of history that has little to nothing to do with C's design itself.
"If by economic you mean "pragmatic" and "engineering considerations", then yes."
BCPL was whatever compiled on a machine from the 1960's. C was what compiled on a machine from the 1970's. ALGOL was engineered. C was what compiled and ran fast on old hardware. That's it.
The rest was social factors. Even when alternative languages did better, most people didn't adopt them. Most buyers also paid for performance per dollar totally ignoring reliability, security, maintenance, and so on. Unless you argue these don't matter, then the dominance of C and UNIX is once again due to something other than their technical merits. Plus, the fact that their problems stayed in... intentionally... once better hardware came online while other players fixed them in various ways.
I don't believe that for a second. C had very specific performance and memory characteristics that alternatives didn't have.
>C was what compiled and ran fast on old hardware. That's it.
That's a HUGE pragmatic benefit, not a "historical accident".
Nah, we didn't need C. Thompson just really liked BCPL. It was crap. So they tweaked it into C. It still couldn't write UNIX. Ritchie added structs and that version finally did the job. All in the papers I cited. It's facts in their own writings and predecessor papers (eg BCPL) why each decision was made.
Well, Pascal was also inspired by languages that were crap compared to modern (70s/80s needs), and early Pascal's also had tons of missing features -- so I'm not sure what this "C wasn't good enough from the start" is supposed to mean, especially since C already had structs and all by the time it caught on.
One group tried to implement a version of it, CPL, on horrific hardware in batches on punchcards. Not best way to do state-of-the-art language compilers. Upon failing, they applied this method to CPL: chop off a feature, try to finish compiler, repeat. Result was easiest features to implement on a 1960's EDSAC in form of BCPL. Thompson preferred it over alternatives and tweaked it to his preferences, including assignments from := to =. Admits he just liked that better. That's the amount of science that went into his modifications.
Eventually, Ritchie tweaking it a bit, they got their toy OS to run on a toy machine. Many design decisions they made were due to its own design and limitations. Then, after UNIX spread everywhere and many apps were made, they just kept all that because fixing it would break something. That's the opposite of engineering a good system language. It's an acceptable, but not ideal, hack to make their crappy computers work. After they got better ones, they should've started migrating toward something better incrementally. They didn't and many defended the language as if it was designed well upfront instead of what compiled on an EDSAC and PDP. Facts don't lie.
Plenty of better stuff and techniques. For example, MULTICS project that gave them OS and BCPL experience had critical stuff in PL/0. In MULTICS, a microkernel, prefixed strings, and a reverse-flowing stack would've prevented tons of data loss and hacks that happened in UNIX. Why didn't they use those? Hardware expected a bad stack and other two techniques were too slow on it. Once hardware sped up, they kept the bad techniques to not rewrite stuff. I mean, this shows up over and over in UNIX/C. Its history really defines it.
Now, stop and go look at Modula-3 on Wikipedia. A few of us think it was one of best compromises between a safe, C alternative like Modula-2 and a heavyweight, ALGOL or C++ alternative. It was the product of professionals engineering, as done for ALGOL, an industrial language based on Wirth's prior work. Simple syntax that compiles fast as Go, a Wirth-style language. Has safety by default with off button where necessary, has basic OOP, has GC by default with off button for specific variables, built-in concurrency, mathematically verified stdlib (partially), runs efficient code, and was used for an OS (SPIN) w/ type-safe linking of 3rd-party code into kernel.
So, we know it could've been done better if it was engineered or addressed more programming needs than runs fast on 1960's hardware. Unfortunately, that's basically all BCPL and C did while ignoring good techniques then and later. Fortunately, we can learn from their mistakes for use in new languages or projects. :)
No, C is the basis of a lot of programs. It is not, nor could it be, the basis of a sane system of computation.
From a pragmatic perspective computing is just "a lot of programs".
It's not what "should be" -- it's what it is.
Common Lisp, of course, is a hell of a lot more than just the lambda calculus, but it's also a hell of a lot better a language than is C.
How does being the basis follow from being popular
> Take away all C/C++ code and we have nothing or almost nothing.
We had Lisp machines in the 70s, Oberon system in the 90s, Forth systems basically throughout history... take away C and C++ and something else would've become popular. Probably Pascal, some random low-level Lisp dialect, or Forth, given that those were all reasonably popular in a similar timeframe as C. For something that is a ‘basis’, C had an awful lot of competition.
> Take away all Lisp/Scheme code and people will barely notice.
Well, aside from every Emacs and AutoCAD user in the world.
Also HN wouldn't exist, so there's that.
The basis is by definition popular.
If it's not popular (at least where it matters) it's not the basis. Basis is the fundamental thing on top of which something (the IT world as we know it) stands.
One could argue that algorithms are more basic, but we're talking about programming languages here, and at that level, C/C++ has been, and remains king for anything crucial. Even Java, the CLR and V8 are written in C/C++ (to name but a few environments standing on this "base").
>We had Lisp machines in the 70s, Oberon system in the 90s, Forth systems basically throughout history... take away C and C++ and something else would've become popular. Probably Pascal, some random low-level Lisp dialect, or Forth, given that those were all reasonably popular in a similar timeframe as C. For something that is a ‘basis’, C had an awful lot of competition.
Not sure how this argument is supposed to work.
To be the basis of something doesn't mean you don't have competition. Just that you prevailed over it.
>Well, aside from every Emacs and AutoCAD user in the world. Also HN wouldn't exist, so there's that.
Still people would barely notice. If you think Emacs and AutoCAD would make a huge difference to the world if they disappeared (compared to say, Windows, Linux, Android, or, if we're to talk about sites and apps, Google, Facebook, Photoshop, Word, etc) then you've been on an echo chamber for too long.
(Not to mention that most Emacs users use it for if not C/C++ then for languages whose compilers are written with C/C++, on OSes written in C/C++, and that Emacs itself is written in C -- the base were elisp stands on is C).
C didn't won because of "engineering" or "pragmatic" reasons, it won because it run faster on cheap hardware, which was a big selling point. It wasn't a pragmatic choice, but a stupid and short-sighted one - but those tend to usually win. Computing in the last 30 years was done in spite of, not because of, C.
Given that I remember the days junior Assembly developers could easily outperform C code, I don't agree with that point.
I bet if it wasn't for the rise of free UNIX clones, C would already be sharing drinks with Pascal at some retirement home.
https://en.wikipedia.org/wiki/PRIMOS
That's a CPU and OS for Fortran. I found a web framework for Fortran, too. Today, we could do Hacker News in FORTRAN from the metal up. We'll leave that monstrosity to our imaginations, though. Not even that. ;)
Isn't that the very definition of an engineering/pragmatic reason?
--- Begin Quote ---
-Seibel-: When do you think was the last time that you programmed?
-Allen-: Oh, it was quite a while ago. I kind of stopped when C came out. That was a big blow. We were making so much good progress on optimizations and transformations. We were getting rid of just one nice problem after another. When C came out, at one of the SIGPLAN compiler conferences, there was a debate between Steve Johnson from Bell Labs, who was supporting C, and one of our people, Bill Harrison, who was working on a project that I had at that time supporting automatic optimization.
The nubbin of the debate was Steve's defense of not having to build optimizers anymore because the programmer would take care of it. That it was really a programmer's issue. The motivation for the design of C was three problems they couldn't solve in the high-level languages: One of them was interrupt handling. Another was scheduling resources, taking over the machine and scheduling a process that was in the queue. And a third one was allocating memory. And you couldn't do that from a high-level language. So that was the excuse for C.
-Seibel-: Do you think C is a reasonable language if they had restricted its use to operating-system kernels?
-Allen-: Oh, yeah. That would have been fine. And, in fact, you need to have something like that, something where experts can really fine-tune without big bottlenecks because those are key problems to solve.
By 1960, we had a long list of amazing languages: Lisp, APL, Fortran, COBOL, Algol 60. These are higher-level than C. We have seriously regressed, since C developed. C has destroyed our ability to advance the state of the art in automatic optimization, automatic parallelization, automatic mapping of a high-level language to the machine. This is one of the reasons compilers are... basically not taught much anymore in colleges and universities.
--- End Quote ---
(taken from pp. 501-502)
I agree C is necessary for low-level programming, but for the meat of all the other applications and usages, higher-level languages are needed. I don't mind programming certain things in C, but I thoroughly enjoy the mental exercise when programming in the J programming language, Lisp, or Forth. Yes, Forth. C programmers can have the Earth; I would like to be coding with the fellas who design mission-critical software for satellites like Rosetta, and groups like NASA and the ESA, using Forth in Rosetta's case [1].
Slim Whitman sold more records than the Beatles, or so I think I heard that on a late-night TV commercial back in the 80s, but I never owned a record from him ;)
[1] http://adsabs.harvard.edu/full/2003ESASP.532E..72BI actually disagree with this for the most part.
C's main advantage as a systems language is its ubiquity -- virtually every platform released in at least the last 25 years has had a reliable C compiler available. Before JavaScript hit it big with Web 2.0, C was a lingua franca among programmers. Starting in the late 80s and continuing throughout much of the 90s, pretty much every textbook that had used Pascal or Pidgin Algol for code listings was edited to contain code listings in C instead.
Of course, as Java gained momentum in the education space in the late 90s and early 00s, many were again updated for code listings in Java. Although a great deal of computer science curricula now crowd around Java, most of them also have at least one required course either on C or that makes good use of C (my own track at NC State contained, beyond the introductory Java courses, "C & Software Tools", "Operating Systems", and "Computer Graphics", all in C).
That all being said, there were historically quite a few systems languages that were better than C in almost every way[1]: they were (typically both memory- and type-) safe, they were higher level in the sense that they offered more and better tools for abstraction (and were therefore considerably more expressive), they offered more opportunities for automatic optimization, they were easier to port to new platforms, many of them were easier to read and had far fewer nuances/"gotchas"/"footguns" than C, the languages themselves were designed in such a way that better tooling was possible, the list goes on and on. The one thing that C had on them was that it was already default. Programmers could (and can) count on the target platform having a C compiler. C programs have access to the wide assortment of C libraries. C was good enough. In a sense, C's popularity was and is perpetuated by the fact that it's the path of least resistance. Once C managed to get into that position, of course it became the "king of systems languages".
I think C's days are numbered. There was a time when systems programming was how you went about learning to program professionally on microcomputers. (Unstructured) BASIC was popular among hobbyists but right-out for professional programs due to abysmal performance. So, you learned assembly/machine language, or, if you were lucky, Turbo Pascal, a similar-in-spirit C system, or QuickBASIC (a compiled, structured language that I'd actually classify as a systems language, given that its feature set is mostly isomorphic to C's). Nothing else offered the level of performance you needed for commercial applications. This continued from the mid 80s through to the early 00s, yielding several generations of programmers who were systems programmers by training.
But things are different now: most programmers nowadays are cutting their teeth on high-level languages like JavaScript, Ruby, Python, Lua, etc., and if they become systems programmers it's due to their own desires and interests rather than out of any real necessity. These programmers know better, and are in an excellent position to notice the many shortcomings of C, and some even outright reject it due to its gnarliness in comparison with the high-level languages they're accustomed to. They know, deep down in their bones, that systems programming doesn't have to be so unsafe, so intricate, so field-of-landmine-ish, so... shitty. And some of them intend to do something about it.
I think we're already seeing the results of this: languages like Rust, Nim, and Myrddin strike me as products of these happenings. And now, I think, is a good time for it, because C's ubiquity has never been less relevant since its rise to power: there's only a handful of platforms anyone needs to support nowadays (POSIX and Windows, desktop and mobile; you can count OS X/iOS as a separate platform if you're feeling squirrely, but even then you haven't reached an unattainable set of targets, and it seems as if soon you may be able to strike Windows from the list as well); if you offer ABI compatibility with C, you get libraries for free; parsing is practically a solved problem; .... And then there's the LLVM, which can handle roughly a third of the compilation process for you -- and it's the backend: the hardest part!
I imagine that within another 20 years to 30 years, C will be hiding within its final strongholds of legacy code and embedded programs. Outside the embedded space, new projects in C will be exceedingly rare, and another decade or two after that will see even the embedded programmers breathing a collective sigh of relief as they become gradually liberated from the tyranny of C.
Only time will tell if the newcomers can usurp C's throne, but I have my fingers crossed. When C gasps its last breath, I will say "good riddance", and happily return to my safe, expressive, pleasant systems language, whatever that may happen to be at that time.
[1]: Just to name a few: Algol 60, Modula-2, Oberon, Ada, Modula-3(one of my personal favorites), ATS, even several non-standard dialects of Pascal such as the ones from UCSD, Apple, and Borland. Then, of course, there are the newcomers: Clay, Rust, Go, D, (does Nim count?), Myrddin (definitely one to keep an eye on), even some dialect(s) of C# were used at Microsoft Research for systems programming. I'd also be remiss not to mention PreScheme (another one of my favorites), used by Jonathan Rees and Richard Kelsey to implement the Scheme48 virtual machine, and its nephew RPython, used for implementing the PyPy JIT framework. I'm sure there are quite a few I'm leaving out, but these are the ones that come to mind at the moment (also, do keep in mind that I'm restricting this to systems languages that are strictly better than C, so some otherwise neat ones like BCPL and BLISS have been intentionally omitted).
Not sure if by 'disagree with this' you mean the whole piece, or just the quoted sentence. Addressing the obvious quoted sentence:
Don't get me wrong, I like C. I am currently writing a Lisp in C, playing with ImGui and Nuklear immediate-mode GUI kits. That is why I used the word 'needed' vs. something like 'are majorly used'. C pulled me from my Vic-20 6502 assembly language days (I lie, I had moved to Basic before C!). When I program in a higher-level language (Lisp/Scheme, Python, Julia), I find I am dealing with what I actually want to get done, and in the end my programs are not AAA games, or large deep learning neural networks, so they are plenty fast for my needs. I start out clearly with an objective in C, but usually get mired in some C-specific, non-goal-related task, whether I need to refresh my knowledge of pointers, or platform-specific idiosyncrasies. I certainly would choose C over Java any day, or move to another higher-level language. I think Java's VM is a fantastic piece of work, and Java syntax is very C-like, but I'd rather not use it. I use a lot of programs written it though! I prefer Lisp/Scheme, and compiled SBCL is fast. And now with the opensourcing of Chez Scheme, I will be busy this next week. The Spring 2016 Lisp Game Jam is starting in about 24 hours [1].
[1] https://itch.io/jam/spring-2016-lisp-game-jam> Great summary.
Thanks!
> Not sure if by ’disagree with this’ you mean the whole piece, or just the quoted sentence.
Just the quoted sentence, though it does make two assertions: 1) that C is necessary for low-level programming; and 2) that higher-level languages are necessary for all other applications. My previous comment focused primarily on the first one, but I disagree with both. One only need look at the sheer number of applications written in C [1] to see that C is suitable for applications outside of the “low-level” realm.
> I especially like your point about the programmers migrating to systems programming having a different mindset than an older person like me, who started with assembly.
We’re in a similar boat, I think. I cut my teeth on QuickBASIC, quickly picking up some 8086 assembly to get some fancy-schmancy VGA graphics and some SoundBlaster goodness. After around two years, I got my hands on Turbo C 2.0 and never looked back. Although I now prefer higher-level languages, I’m a systems programmer at heart, and that affects how I approach the art and the act of programming. I have a hunch that many programmers “suffer” from the same affliction: that however they learned the ropes still affects their approach to programming in some way; and that’s the thought that underlies my suspicion that we’re about to see a “systems programming renaissance” of sorts.
> Don’t get me wrong, I like C.
Don’t get me wrong, either. I also like C. But it’s also just not a good language. Even at the systems level, there are so many better alternatives. I don’t know if it’s familiarity (most of the lines of code I write are in C), nostalgia (C was one of the first languages I learned), laziness (C’s ubiquity makes it pretty convenient), tradition (these days I’m a UNIX™ guy through-and-through), some combination, or something else entirely. I’ve also noticed that many C programmers have an attitude of “if you don’t know all the ins-and-outs, nuances, footguns, hazards, dark corners, unspecified and implementation-dependent behaviors, and compiler optimizations, then you’re stupid and a bad programmer and you should feel bad” — so maybe it’s narcissistic elitism…
> I am currently writing a Lisp in C, …
Care to elaborate? Is it a naïve interpreter, bytecode compiler & VM, native code compiler, …? Is it an existing dialect or one of your own design? Is there anything about it that you feel is distinctive? Anything you feel particularly proud of?
I’m working on a Lisp of my own, too. It’s based primarily on EuLisp, but with some influences from Scheme, Common Lisp, and some older Lisps like Le-Lisp. I’m still in the design process, though, and am not ready to talk about it at length yet.
> I certainly would choose C over Java any day, or move to another higher-level language. I think Java's VM is a fantastic piece of work, and Java syntax is very C-like, but I'd rather not use it.
I’d originally written a rather lengthy response to this, going over various shortcomings of Java and various trade-offs involved in making that decision, and cases where Java might be a good choice, but honestly I don’t feel like reproducing it now. I don’t care enough for Java to defend it, really.
> I use a lot of programs written it though!
Of course! It’d be silly to say “X does exactly what I want/need, but it’s written in language Y, and I don’t like Y, so I refuse to use X”, though sadly I do know some people who say such things. It baffles me. What an idiotic attitude.
> I prefer Lisp/Scheme, and compiled SBCL is fast.
As do I. I’m a smug Lisp weenie and proud! In fact, up until recently, I would’ve told you that Scheme is my favorite programming language, followed by ML. Then, being disenchanted with the current state of Scheme — the divisive and controversial standards, the inability of the community to unite behind the language — and my “discovery” of EuLisp have lead me to say that my favorite programming language is my own breed of Lisp. I took a couple days of vacation from work, and I’d planned to spend them working on my Lisp, but…
> And now with the opensourcing of Chez Scheme, I will be busy this next week.
Me too. I completely changed my vacation plans when I saw this announcement. I’ve spent some time, and will continue to spend time, playing Chez and studying the source :)
> The Spring 2016 Lisp Game Jam is starting in about 24 hours….
I hadn’t heard about this. Thanks!
P.S. Hit me up sometime if you want to talk about Lisp or programming languages in general. I’m definitely a PL nerd, and I like to talk about this stuff (including implementation strategies and history). My e-mail address is in my profile.
[1] https://github.com/search?q=language%3Ac
Besides the obvious low-level stuff, like the Linux kernel, there are quite a few applications that don’t require the low-level offerings of C: git, redis, the-silver-searcher, awesomeWM, etc.
Any advice on getting over this hump?
[1] http://thinking-forth.sourceforge.net/
[2] https://factorcode.org/
[3] http://forthworks.com/retro/
[4] http://flashforth.com/tutorials.html
[5] http://home.iae.nl/users/mhx/And we can really ignore it software wise. We only use its theoritical heritage now.
If UNIX had been commercially licensed, like every other OS back then, the C foundation would never had happened.
That's a myth. Try using first-hand sources like the papers from people who designed BCPL, B, and C to understand why it's that way. Answer: terrible hardware back then. That's it. Its popularity was result of prevalence of terrible hardware and that UNIX was written in C. I broke it's history down in just a few pages with a timeline and references here:
Likewise, before the social effect, the OS's were coded in a number of HLL's with capabilities UNIX lacked. Languages included ALGOL, PL/0, and Pascal. Later, they were done in Modula, Oberon, Ada, Fortran (yeah lol), LISP, and so on as hardware improved beyond 1970's minicomputers. Here's some UNIX alternatives and their capabilities that developed... some of which you still don't have. :)
https://news.ycombinator.com/item?id=10957020
Far as LISP, it's been implemented in hardware multiple times. This included naive ones that worked like a simple evaluator with garbage collection built into the memory-management unit. There was also one that had four specialized units for more sophisticated execution. One Scheme was designed and mathematically verified using the DDD toolkit that was also LISP if I recall.
http://www.cs.indiana.edu/pub/techreports/TR544.pdf
Oh heck, forgot they did it with VLISP. That was a Scheme48 interpreter and PreScheme compiler rigorously verified for correctness. PreScheme was a Scheme subset for systems programming. So, the work actually took a verified Scheme then mechanically derived verified HW from that Scheme code using a LISP-based tool. I recall from other papers they got it working on a FPGA and some PAL's.
Whereas, I don't know many small teams producing verifiable C code on verifiable C processors from verifiable C tools. Nah, I don't think your favorite language is anywhere near where you think it is. I don't even find LISP ideal here by far. It just did more in functionality & bare metal. Also, first LISP machine was started when UNIX was released interesting enough.
I must not be anybody, then, because I think that Lisp provides a wonderful notation for thinking about symbolic computation which will last for millennia while C is … a successful programming language of the late 20th century.
> I don't know how you even write a hash table based on cons cells rather than O(1) indexing.
A cons cell is just a double-pointer. You can write a hash table using conses just as easily as you would using pointers (note, I'm not saying that'd be efficient, which is why Lisp offers arrays as well as conses).
The operating system I currently run uses a Scheme program as its init system and a Scheme program as its package manager. Scheme is a practical language.
Edit: remove useless commentary
Emacs Lisp is probably a better example of practical.
#2 - preach it.
#3 - The "big" schemes provide hash tables for you.
#4 - Well... fexprs used to be standard in lisp, but implementers didn't enjoy figuring out what a symbol meant at compile time.
I dunno, I really enjoy coding in scheme. Especially syntax-rules. I know syntax-case is the bees knees, but syntax-rules is pretty easy for me to model quickly.
It's interesting looking back on the history of Scheme. Probably because of the order of presentation of SICP, along with hearsay, people seem to get an impression of Scheme being all about functional programming (and if it's because functions are values you can pass around... well even Algol and Pascal could do that). It's true the original paper was called "Scheme: an interpreter for the extended lambda calculus" [1], but the big idea was that if variables were bound lexically, and if the environment structures used to close the variables were mutable, then you would have something like the actor model -- functions could have state and respond to messages. As they admit in the abstract, the purpose was to demonstrate the core interpreter for implementations of contemporary AI systems. The chapter on register machines in SICP is just an elaboration of their methods in this paper.
[1] http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-...
Something about porting a metacircular evaluator seems odd to me. Not that it's a bad exercise -- it's a good one. But rather, that it's no longer a _metacircular_ evaluator. The progression of the book is 1) abstracting processes and names with procedures 2) abstracting data representation 3) abstracting interface as a module, along with the theory and practice of mutation 4) abstracting semantics with interpreters (programs which take programs as data). The proof that 4 is a thing is by implementing an interpreter for the language in the language and then extending the interpreter in various ways. Even procedure calls are implemented by calling a procedure in the host language. (All I'm saying is that you exercised the metalinguistic abstraction by writing a scheme interpreter in femtolisp. Metacircularity in itself is not much more than an interesting phenomenon to demonstrate.)
(P.S. The language in SICP is not the Scheme which was later standardized, say R5RS + SRFIs. Mutation of lexical closures didn't change. You can't really (cleanly) get away from that until you invent something like a monad to model state.)
And yes, I've been programming a lot in the intervening 19 years, and doing imperative programming with ((Lisp)) syntax is hugely annoying. OCaml actually annoyed me in this regard too. Maybe I will like Haskell, since it seems principled about mutation.
This is a real misunderstanding, see my response to this comment here: https://news.ycombinator.com/item?id=11412392
People think that there could have been some "Church basis" for computing. In other words, the whole Lisp machines thing was folly. It's rightly in the dustbin of computing history.
FWIW I did many experiments in bootstrapping languages, with Python/Lua, OCaml, femtolisp, C, ... I eventually ended up with (a tasteful subset) of C++, which somewhat amazed me, since I've never been one to like C++. This is a whole other story, but it had to do with the fact that OCaml "needs" code generation with ocamllex and ocamlyacc/menhir, and I was looking at how Julia is bootstrapped Lisp (impressive, but not what I want), etc.
[0] http://axisofeval.blogspot.com/2011/09/kernel-underground.ht...
Hashing lexicals will not necessarily speed up an interpreter. It depends on what kind of code and how you do it. A lot of code has only a few lexicals at any binding level. If you construct a new hash table on each entry into a binding construct which has only a handful of variables, that could end up performing worse than the original assoc lists. You still have to cascade through multiple hash tables under that approach to resolve nesting. One hash table for an entire lexical scope leaves you with problems like how to resolve shadowing, and how to capture closures at different sub-nestings of that scope that have different lifetimes from containing scopes.
The Right Way to do this is with a D-List, or Detached List, analogous to an A-List or a P-List. An A-List, if you recall, is a list of key-value conses. A P-List is a list of alternating key-value pairs. A D-list is a cons of a list of keys and a list of values, i.e.:
((key1 key2 ...) val1 val2 ...)
D-lists are superior to A-Lists and P-Lists because:
1. The key list structure can be re-used
2. D-ASSOC only requires one traversal down the key list, after which the index of the key can be cached. This is usually the first step in writing a "fast" interpreter, but if you use A-Lists or P-Lists then you have to change data structures. If you use a D-List you already have the optimized structure in the CDR of the D-List pair.
3. Going from optimized interpreter to full compiler is a simple matter of replacing the linked list of values with a vector of values.
It's a shame that D-Lists are very rarely taught.
With the A-list method you typically need to write a "zipper" function, that recursively conses the heads of two lists to generate the A-list. Makes "apply" an expensive operation with needless allocations.
What's great about D-lists is that the "make-env" method is just a single cons operation. Clearly superior. I'm surprised its not more well known.
Thanks.
> I'm surprised its not more well known.
Yeah, me too :-(
Also, some people just really hate the parentheses (not me).
Also, some people really hate the Beatles (not me). More so in the '60s as contemporary artists, less so now when they're more likely to be referred to in a historical context. But still. The White Album had no shortage of devastating reviews when it came out.
I'd imagine Scheme as a teaching language would be less controversial in schools where the CS students are more likely to already know some programming when they start, and/or don't have as much of a trade school mentality.
You're lucky it isn't Fortran and a homegrown (crappy) macro language.... You can't fairly judge Scheme or C from a legacy codebase unless you judge every other language that way too.
Why would you need anything else for debugging?!?
There is no big difference between building with contracts and logs on (log level is selected dynamically, no need to recompile) and building with debug symbols/suppressed optimisations.
[0] - https://github.com/prakhar1989/type-inference
[1] - http://www.scheme.com/tspl4/examples.html#./examples:h10
I tried looking the course materials online but the Indiana University website gave me a 404 error page when I tried to access the course from Dybvig's website.
Thanks.
Good on Cisco for open sourcing it.
I'm interested to hear what regular scheme programmers feel about this news.
Also, does Gambit not support native threads? That's surprising considering Marc Feeley did quite a bit of research on multiprocessing in Scheme, and he wrote the SRFI for threads.
The racket/place library provides support for performance improvement through parallelism with the place form. The place form creates a place, which is effectively a new Racket instance that can run in parallel to other places, including the initial place. The full power of the Racket language is available at each place, but places can communicate only through message passing—using the place-channel-put and place-channel-get functions on a limited set of values—which helps ensure the safety and independence of parallel computations.
Compare to current Guile, where the documentation says sharing a hash table without using a mutex will not corrupt memory, but probably won't give you the results you desire.
On the other hand, there's an intellectual idea that for many companies, existing software should perhaps be seen as a liability in double entry accounting due to it's need for ongoing maintenance, upgrades, potential for catastrophic failure, and the cost associated with alterations for new business processes.
Companies offload some of those costs by open sourcing and allowing developers to happily "give back" to their bottom line.
On a longer timeline, hiring developers experienced in the technology from the open source community saves on the cost of training them for a proprietary code base.
Ideally, the open source community develops new features, identifies and patchs bugs, writes tests and libraries, etc. adding value realized by the company's paying customers. In the meantime the company still can devote staff to its business priorities and ignore those of the larger community: e.g. no `map` in go-lang and no `react new myapp` at the CLI for React.
To put it another way, why would a business open source code for anything other than business reasons?
The part where Cisco open sourced it is a bit unusual, but it's not uncommon for people to close source and sell systems they create during college or grad school and continue to use them in research.
SP-SW-LMIX0CH0 SP BASE Chez Scheme Dev Env for Wind, Per Unit $65.00
SP-SW-LMIX0CHL SP BASE Chez Scheme Dev Env for Linux, Per 10 $325.00
SP-SW-LMIX0CHW SP BASE Chez Scheme Dev Env for Wwind, Per 10 $325.00
SP-SW-LMIX0CH1 SP BASE Chez Scheme Dev Env for Apple Mac,Per 10 $325.00
SP-SW-LMIX0CHA SP BASE Chez Scheme Developm $65.00
SP-SW-LMX01CHL SP BASE Chez Scheme Developm $65.00 Chez Scheme Version 6
Software License Fee Schedule
V60901f
Supported machine types:
Intel 80x86 Linux 2.x
Intel 80x86 Windows 95/98/ME/NT/2000
Silicon Graphics IRIX 6.x
Sun Sparc Solaris 2.x
Classification License fee (USD)
-----------------------------------------------------------------
Single Machines
first machine per machine type $4000
each additional machine 3000
-----------------------------------------------------------------
Site
first machine type 9000
two machine types 14000
three or more machine types 19000
-----------------------------------------------------------------
Academic Site (for qualified academic institutions)
first machine type 4500
two machine types 7000
three or more machine types 9500
-----------------------------------------------------------------
Corporate
each machine type 24500the Apache 2.0 license includes not just copyright but patent licensing, so the software will contain no hidden patent restrictions for patents owned by the creators and contributors.
In my experience both terms are ambiguous. Many people seem to believe that "open source" simply means the source is available for examination. For example:
If you want to make an unambiguous statement, use "OSI approved license".
Other than Solidworks (which has everything from industrial machining stock cold-rolled steel and the finite-element analysis of your components all the way to computational fluid dynamics of anything your engineering heart could desire) I've never seen a company cover such an industry so thoroughly, so well[1].)
[1] Maybeeee Adobe has equal coverage re: for vector work with Illustrator/image manipulation with PS/page layout and typesetting with PageMaker/Indesign and doing post on Video with After Effects and such. And I don't think anyone would disagree, the degree of complexity for this genre of software is on a different tier.
edit: Haha. Confused Cadence Design Systems with Cadence Research Systems. Thanks for correcting me. Mea culpa. Keeping this up just for continuity sake. Viva la Scheme though! Have an upvote, @beering ;)
Biggest "independent" semiconductor foundry company (independent = they make customer designs, not their own)
Mentor has an advantage since they acquired Tanner, best of the budget ones.
I'm not usually given to short, low-content comments here on HN, but:
wow!
Also, for what it's worth, Ada has quite a few Wirthisms and I personally quite enjoy it. But it technically isn't a Wirth language.
Instead I just switched to guile (scheme implementation) trunk and got a 3x speedup. Did some optimizing work and it ended up at 4x, which is good enough.
We thought about using chicken, but it depends quite a lot on using syntax-case to deconstruct everything, and I didn't want to learn their implicit renaming stuff.
Apparently the 2.2 branch has full elisp support. Can't wait for Emacs to run on it.
I really wish folks would spend the time they spent porting elisp to guile Scheme porting elisp to Lisp instead. Scheme's great for what it is (really), but what it is not is an industrial-strength systems programming language. Common Lisp is.
This is a common misunderstanding. Emacs Lisp is not being rewritten as Scheme. What is actually happening is that there is a compiler for Emacs Lisp that runs on Guile's virtual machine. Elisp isn't going anywhere.
And, regardless, I wish that they'd not used Scheme. I really, really wish that they'd not used Scheme.
Good.
I had trouble building it on Linux if I tried to set --installprefix= to a non-standard location, it built fine using the defaults. Nice!
On OS X, I have a clang version of gcc installed and perhaps because of that my build broke.
I installed gcc-5 using brew, set "alias gcc=gcc-5", and then ./configure ; sudo make install worked fine.
Maybe someone have managed to build the Windows version?