We Hate Lisp
wiki.c2.com
wiki.c2.com
"This site uses features not available in older browsers."
> not having the insight of Moon (whoever he was)
> …the Lisp guys start talking about the elegance of lambda and cons and PeanoArithmetic
Of all hackers, Dave Moon is about the least likely to want to focus on gratuitous lambdas or Peano arithmetic!
Something of a shame really. The lispers and Smalltalkers were their own worst enemies back in the day.
I do feel like there's much less snobbery/more inclusiveness these days. Anyone can open up a browser and start typing something executable, and there are so many sites willing to offer help.
has increasingly become to sound hollow or misleading, insofar as the properties and abilities described were solely found in "functional" languages of the time rather than being inherent benefits.
> Most functional languages provide a nice, protected environment, somewhat like JavaLanguage.
So Java, which isn't functional, provides a relatively "protected" environment. So what does "protected" mean and what does this have to do with functional languages again?
> FP encourages safe ways of programming
Depends on syntax and features. Only allowing one true way or providing one true api, is equivalent.
> Functional programs tend to be much more terse
The terseness can contain complicated subtlety. Up to the developer to read it carefully. Non-obviousness isn't a good thing and a level of verbose expression seems to be beneficial.
> FP encourages quick prototyping
Nope.
> FP is modular in the dimension of functionality
Not unique.
etc etc etc
The common assertions about having no-side effects are interesting because I was lured by this when I was younger. Sadly, there are always side effects, even if it's just resource usage or output to some device. The idea of limiting side effects is simple to achieve through modern language "static" functions and other mechanisms to the same degree. Has it made functional languages more popular/valuable or javascript (which has no such mechanism) less?
blah blah blah.
Only if that one true way is safe. I'd argue that hidden mutable state (which is the essence of non-functional programming) is inherently unsafe - non-threadsafe by default and, even more dangerously, confusing to the reader by default.
> The terseness can contain complicated subtlety.
Maybe it "can", but usually the terseness just comes from removing pointless clutter.
> a level of verbose expression seems to be beneficial.
Citation needed.
> Sadly, there are always side effects, even if it's just resource usage or output to some device.
Right, but you can isolate and control them, separate them from your business logic.
> The idea of limiting side effects is simple to achieve through modern language "static" functions and other mechanisms to the same degree.
No it isn't - if it were then we'd see non-functional languages that had effective control of side effects, and we don't.
Quorumlang did studies on this. Brainfuck is a sufficient example.
> Maybe it "can", but usually the terseness just comes from removing pointless clutter.
Abstraction is not clutter. FP adds new abstractions which have variable syntax across languages or even within the same language.
>> The idea of limiting side effects is simple to achieve through modern language "static" functions and other mechanisms to the same degree. > No it isn't - if it were then we'd see non-functional languages that had effective control of side effects, and we don't.
This is circular logic. Languages would use FP if they saw the value because FP is worth using.
A program can be written in a conceptually non-fp language, that is composed of functions without side effect. Practically, this has no advantage, so no effort is put into going farther in that direction with the syntax.
> I'd argue that hidden mutable state (which is the essence of non-functional programming) is inherently unsafe - non-threadsafe by default and, even more dangerously, confusing to the reader by default.
I know side effects are a feature that can be managed, but this requires discipline. People try FP-centric languages, but unless someone pays them, generally people stay away from it except in spurts (eg map, fluent chaining, etc). This should give some pause, as to what that means. GL with whatever.
How so? It's both very verbose and not very maintainable.
> Abstraction is not clutter.
Most of the overhead in non-functional languages is not abstraction.
> FP adds new abstractions which have variable syntax across languages or even within the same language.
What are you talking about? Generally FP languages have less special-case syntax and less special-case concepts, e.g. fewer control flow keywords, exceptions are less prominent, coroutines don't use special keywords or new concepts, mutable variables aren't needed.... I guess do notation is more common in functional languages, but it's a very lightweight piece of syntax sugar that obviates a bunch of what would be special-case syntax in less functional languages: http://philipnilsson.github.io/Badness10k/escaping-hell-with... .
> A program can be written in a conceptually non-fp language, that is composed of functions without side effect.
Static doesn't mean side-effect free, and a binary distinction between "side effect" and "not side effect", while somewhat useful, is very crude. But the biggest issue is that it's not practical to write without side effects unless the language's standard library, ecosystem, and most of all culture support it.
> People try FP-centric languages, but unless someone pays them, generally people stay away from it except in spurts (eg map, fluent chaining, etc). This should give some pause, as to what that means.
On the contrary, popular programming culture creeps slowly in the FP direction every year. Five or ten years ago map was some wacky far-out functional thing.
Of course “pure” functions will have memory/CPU overhead, but that is inevitable. Perhaps you would prefer idempotent and memoizable?
11 years ago, 44 comments: https://news.ycombinator.com/item?id=1777767
Dim sum
For Each thing In Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
sum = sum + thing
Next from(177).to(448).do(i -> { ... })
is easy to implement in Java.So I don’t see why would this base case have any significant overhead. Of course a complete stream api will have some.
sum(range(10))
In Rust: Vec![1..10].iter().reduce(|x,y| x+y) sum(1..10)
(1..10).sum
or just sum 1..10You can use any infix op (core or custom) to do a reduction:
[*] 1..10 # 3628800 basically faculty
Ha ha, "iota": great pun!
https://github.com/g000001/MacLISP-compat/blob/master/IOTA.l...
;;; -*- LISP -*-
;;; IOTA: Macros for doing I/O correctly.
;;; Bugs/suggestions/complaints to KMP@MC
[...] ;;; IOTA
;;;
;;; Mnemonic Basis: A form of Lambda for doing I/O binding.
;;;
;;; This is a LAMBDA binding macro that will open a lisp file object
;;; in such a way that it is automatically closed when the lambda binding
;;; range is exited.
https://www.maclisp.info/pitmanual/system.html The following is some sample code (complete with documentation) that I found in my notes and thought might be helpful:
;;; Notes about CLI interrupts:
;;;
;;; A CLI interrupt is what happens when another job sends to yours. It is
;;; normally the case that other jobs will send directly to a user's HACTRN.
;;; If, however, Lisp is interrupted by a CLI message, it can elect to handle
;;; handle the interrupt in an arbitrary way.
;;;
;;; To define a handler, two things must be done:
;;; [1] Place the name of the handler function (function of one arg)
;;; in the variable CLI-MESSAGE.
;;; [2] Enable CLI handling with (SSTATUS CLI T)
;;;
;;; The handler should take a single argument which it probably should ignore
;;; since I have no idea what it is likely to be.
;;;
;;; The handler should open the file "CLA:" in (CLA BLOCK) mode and immediately
;;; discard the first 8 characters which will be garbage.
;;;
;;; The remainder of the stream, until a control-C or an eof, will be the text
;;; of the message sent. It may be read with TYI, READ, etc. and handled
;;; however.
(eval-when (eval compile)
(cond ((not (get 'iota 'version))
(load "liblsp;iota"))))
(defun handle-cli-msg (ignore)
(iota ((stream '((cla)) '(cla block)))
(do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
(do ((c (tyi stream -1) (tyi stream -1)))
((or (= c -1) (= c 3)))
(format t "~&~3,'0O ~@:C~%" c c)))) ;print out chars seen
(setq cli-message 'handle-cli-msg)
(sstatus cli t)
; --------
(defun eval-cli-msg (ignore) ;alternate handler
(iota ((stream '((cla)) '(block cla)))
(do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
(do ((f (read stream nil) (read stream nil)))
((null f))
(errset (eval f) nil)))) ;Quietly evaluate forms...
;; Assumes the other lisp will have EVAL-CLI-MSG as value of CLI-MESSAGE
(defun eval-in-other-lisp (uname jname s-expression)
(iota ((stream `((cli) ,uname ,jname) '(out ascii block)))
(print s-expression stream)))