Another acerbic article from Richard Eng critiquing javascript.
Granted that javascript is inconsistent and poorly designed. But what does he expect a beginner programmer to do? Learn a language has neither widespread acceptance nor community support, in an attempt to get away from javascript's deficiencies?
Even Google could not wean sophisticated programmers (who appreciate the issues way better than I and many others do) away from javascript despite its incredible efforts.
I for one am interested in getting the job done quickly and as painlessly as possible. I dont make the tools I just use them.
All good points. Personally, its an idealism versus practicality argument. I personally believe (take this with a grain of salt) that we should deprecate awful languages like JS if there is truly a better alternative out there that gives superior power, ease of use, and safety. The economist in me points out that this would've already happened had they really been that much better. Kind of like one-hit wonders like "ice-ice baby" are actually not crappy songs but amazing works of art according to the masses. Maybe one day P6 will get optimized and polished enough to where all users of (P5, Python, Ruby, and TCL) say "I want that" and switch. Individuals might do that. Companies are more like glaciers.
I don't think whether or not it happens (or has already happened) depends solely on whether the other languages are better. Isn't it a lot of it a co-ordination problems? People want to write in the languages that are widely used and have a lot of libraries; people write libraries for languages that are already widely used; that sort of thing?
I see it as popularity vs merit. A lot of things feed into popularity, like familiarity and network effects. Also, you can be popular by appealing to the sentiments or taste of the masses or influencers, regardless of merit, unless there are strong corrective market forces.
Haha, you're right that there is a chicken and egg problem, but if DART was really an order of magnitude greater than JS, there would be a lot more DART programmers after this many years.
Well, I agree that the article can annoy some people. But... as an avid Smalltalker with a LOT of experience with it - and a lot of experience with Javascript too (and tons of other languages) - there is a "truth" in here.
Smalltalk is immensely cleaner and gives you IMHO a much deeper more gratifying experience working in it. Yes, it's OO all the way, while Javascript is... well, not sure what to call it these days ;) A hodgepodge perhaps. But the real magic in Smalltalk is in the live environment.
It all boils down to the Right Tool for the Right Job. If you are looking for a really powerful tool for abstraction and working interactively with advanced domain models, often using meta capabilities - then Smalltalk totally rocks. The more advanced, the more it shines.
But of course Smalltalk has its negative sides too, and it depends on your specific use case. It's (if we consider the Cog VM which is the most common one) pretty fast, but comes short of V8. It can interoperate with other languages, but it's not as easy as in some other languages. It has a decent community, but not as large as Javascript/Python/Ruby. And so on.
But when your use case fits - it's really good. So my advice is learn many languages, it will make you a better developer, and its fun!
<promotion>Personally I am trying to evolve Smalltalk by merging it with ideas from Lisp, JavaScript and Rebol: sprylang.org</promotion>
Java is currently the most popular language in the world. There are far more job postings for Java than for any other programming language. Java is the enterprise standard language. Java has a tremendous ecosystem and a vast user community. Java is pretty much unassailable.
However, in 1995 Java was nothing more than a hopeful upstart from Sun Microsystems. There were no job opportunities for it. It had no ecosystem to speak of and relatively few users. Performance-wise, it ran like a slug (today, the JVM is well-optimized). How did Java achieve today's status?
To a large extent, it was thanks to Sun Microsystem's marketing efforts. People were drawn to the promise of "write once, run everywhere." They also liked that Java was a fairly simple and easy-to-learn language. In time, Java developed a large community and widespread usage.
The point is, all programming languages have to start from zero. They either grow from grassroots, or they grow from corporate sponsorship and marketing. Incumbent languages with their large ecosystems and user communities eventually yield to newer languages with their promise of greater ease, productivity, flexibility, power, etc. Getting the job done is important, but one should also look to the future. That's the hope of languages such as Go, Swift, Dart, Julia, Rust, Elixir, Smalltalk, and so on.
Interesting how he critiques something cryptic in Scheme and doesn't show the Smalltalk equivalent. One thing that should have its own full section is performance as it is slower than Java, compiled Scheme, and I'm guessing V8 optimized JS. I know the whole hotspot JIT thing was maybe pioneered in Smalltalk though? I do like certain things about Smalltalk (Pharo looks nice), but it is hard to do certain things with it like a GUI. Well I mean it is hard to find out how to do that....not necessarily hard to implement.
> I know the whole hotspot JIT thing was maybe pioneered in Smalltalk though?
As far as I'm aware the ideas used in hotspot began with Self[1], which was also the inspiration for Javascript's prototypical inheritance. Strongtalk[2] adapted these to the class/instance programming style of Smalltalk, then Sun bought them for application to Java.
Many programmers obsess over performance, but the fact is, in today's computing world, performance is a non-issue in most situations. That's why Python, PHP, Ruby, and Perl are so useful and popular. That's why Erlang/Elixir absolutely rock for concurrent systems. That's why Smalltalk is used commercially around the world. Performance is not the be-all, end-all of computing.
Please don't format code with ))))))) at the end for the love of code! Use readable indentation instead as your whole point is to make things look simple to understand. That actually warrants a slap the back of your head from a team of onlookers, one at a time.
The collection of closing parentheses at the end is considered good style for all of the Lisp languages I'm familiar with (Scheme, Common Lisp, Elisp). Here's an example of the style in a file from the SBCL implementation of Common Lisp: https://github.com/sbcl/sbcl/blob/master/src/code/bignum-ran...
Any decent editor will balance the parentheses for you.
Once you look at enough of it, your brain starts to see lisps differently. The parens fade away, and you mostly just see the indentation. It looks a little like Python once you adjust.
Which is why lisp proponents have such a hard time understanding lisp critics:
"Wait, you mean you were willing to reason through pointer arithmetic, monads, implementing a b-tree, etc. but you simply saw the parens and decided that would forever be the thing that you cannot, will not overcome? I mean in spite of all the fairly objective benefits of having a perfectly regular syntax, and code that can be processed by computers?"
You're over-generalizing. This is very much a matter of personal taste/inclination. Do ALL Lispers love the Lisp style of syntax? Of course not.
Moreover, for many programmers, it's asking too much of them to wrap their heads around a syntax where you need to give it time for the parens to "fade" away. This cognitive hurdle is real and it's why Lisp isn't more popular.
It's not just the parentheses. It's the whole code-as-data and interactive development thing. Code is different. Programming is different.
Lisp uses different working styles and tools. You have to learn the whole set. It's possible to learn that and to learn it well, but it might take some time.
Lisp code can be very readable, but it's also to write very complex code - more complex that in most languages, since Lisp provides many mechanisms under developer control.
Even if you don't care about using code as data, Lisp is simply more readable, period.
You don't have to crack open a reference manual to look at grammar rules or precedence tables to work out what the shape of the syntax tree is; you can read anything just from the symbolic prefix, plus a smattering of minor notations like sharpsign-this and sharpsign-that.
A programmer who doesn't know Lisp can still instinctively tell that in (foo (x y) (z w)), the x and y go together more tightly than foo and x, or y and z.
The meaning is determined by foo. But foo is a word. And words have the nice property that you can look them up easily in manuals (potentially with just a mouse click).
Those who say Lisp is not readable are trolls and liars. They are liars because they see it's obviously more readable, but it threatens their self-image of being a competent programmer. It does that because their self-image is rooted in having memorized a bunch of arcane syntax and believing that that is what makes a software developer.
> You don't have to crack open a reference manual to look at grammar rules or precedence tables to work out what the shape of the syntax tree is; you can read anything just from the symbolic prefix, plus a smattering of minor notations like sharpsign-this and sharpsign-that.
You can't. Any macro may support arbitrary syntax. If all you know is the macro name, you don't know nothing about the syntax it implements.
> (foo (x y) (z w))
There are many many much more complex forms in Lisp.
> And words have the nice property that you can look them up easily in manuals
Then you need to know the set of precedence order names. What is a GF-DECLARACTION?
What is a method-qualifier? what is the specialized-lambda-list? What are valid declaration expressions...?
> Those who say Lisp is not readable are trolls and liars.
I don't think you add credibility with these statements. Sorry, this is just dumb.
Even though macros can contain any syntax, and in principle we can have a macro such that:
(mac token1 token2 token3 ... tokenN)
where the tokens are parsed according to some LALR(1) (or worse) grammar, in practice, macros are usually not designed that way. The nested list syntax is used for grouping units together.
So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear.
Of course you need the manual to know what they mean if you don't remember (gee, which is the class name and which is the instance, location or point?), but you don't have to implement the LARL(1) parser in your head.
I was talking about DEFGENERIC syntax, not a trivial example of DEFGENERIC/DEFMETHOD.
> Even though macros can contain any syntax...practice, macros are usually not designed that way.
The LOOP and ITERATE macros are examples of macros with lots of syntax.
> So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear.
The syntax of DECLARE, DEFGENERIC, HANDLER-CASE, HANDLER-BIND, DEFINE-CONDITION, DEFINE-METHOD-COMBINATION, LOOP, FORMAT, ... are far from 'crystal clear'.
One of the macros which is very hard to get right and to understand what it actually does is CLIM:DEFINE-APPLICATION-FRAME
Which of the following forms are valid Common Lisp:
(defun foo (a b)
(declare (fixnum a))
"foo"
(declare (fixnum b))
(+ a b))
(defun foo (a b)
"foo"
(declare (fixnum a))
(declare (fixnum b))
(+ a b))
(defun foo (a b)
(declare (fixnum a))
(declare (type fixnum b))
"foo"
(+ a b))
(defun foo (a b)
(declare (type fixnum b))
"foo"
"bar"
(declare (fixnum a))
(+ a b))
(defun foo (a b)
(declare (fixnum a))
(declare (type fixnum b))
"foo"
"bar"
(+ a b))
(defun foo (a b)
(declare (fixnum a))
"foo"
"bar"
(+ a b))
I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body; then there can be declarations. Not sure if there can be two or more declares. I would always write (declare (fixnum a) (fixnum b)) and don't recall seeing multiple declares in other people's code. (I might be suffering from a form of amnesia which merges multiple ANSI Lisp declares into one.)
This is the sort of thing I'd look into closely if I were tasked with parsing a function body (like for the sake of making some body rearranging-and-reassembling macro fully conforming with the surrounding language). I'm not going to write such code myself, and won't likely see it in other people's code.
Until I see such instances, I won't bother looking at the spec to see what the exact rules are and confirm/refute whether those examples are conforming.
In any case, whether or not some of the examples are correct, I can see what they are trying to say. Be they mistakes, they are still well-formed surface syntax and are readable. Things could plausibly work in some CL dialect such that they are all correct, if they aren't.
A literal string near the beginning of a function, which is only evaluated for its side effect (which it doesn't have) looks suspiciously like a doc string. Either it is correctly positioned or it isn't. The (declare ...) syntax is clearly a declaration, whether or not correctly positioned. (declare ...) isn't a form. I suspect it would be undefined behavior for a program to define a function or macro called declare; not sure about that. Defined or not, it would be a incredibly bad idea.
I'm a competent Lisp programmer and implementor too, and don't have to have this memorized; it's likely not an impediment to anyone else. Which kind of makes my point.
A Lisp programmer has to care, if he wants to write Lisp code.
> I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body
That's wrong.
> I won't bother looking at the spec to see what the exact rules are
Which confirms what I'm saying: even for seemingly trivial DEFUNs the syntax is not obvious.
> Be they mistakes, they are still well-formed surface syntax and are readable.
But the reader does not implement Lisp syntax. The reader just implements s-expression syntax. If the reader can read the form, then it is a valid s-expression. But not necessarily valid Lisp.
(defun foo (a) a) ; valid s-expression, valid Lisp
(defun (foo) a a) ; valid s-expression, not valid Lisp
(defun (bar foo) (a) a) ; valid s-expression, not valid Lisp
(defun (setf foo) (a) a) ; valid s-expression, valid Lisp syntax
(defun foo (&key a &optional b) (list a b)) ; not valid Lisp
(defun foo ($key a &optional b) (list a b)) ; valid Lisp
The Lisp interpreter/compiler and the macros implement Lisp syntax. Not the reader.
> it's likely not an impediment to anyone else.
That you don't know the syntax of DEFUN confirms what I'm saying: the syntax is non-obvious.
Explain this:
* (defun foo (a b)
(declare (fixnum a))
"foo"
"bar"
(+ a b))
debugger invoked on a SIMPLE-ERROR: duplicate doc string "bar"
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:PARSE-BODY ((DECLARE (FIXNUM A)) "foo" "bar" (+ A B)) T NIL)
0]
> That you don't know the syntax of DEFUN confirms what I'm saying.
Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!!
If I don't have to know, few people do.
You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course. I don't have some "requirements don't matter" attitude; but not all requirements matter all the time to all people.
I'd like to add, though, this: you can't be safe in ignorance in Common Lisp. Things you don't know can hurt you. Less than in some other languages, but they are there. You probably won't be hurt by not knowing all the possibilities for combining docstrings and declares. But if you're ignorant of some things, you may get burned. Undefined behavior situations like modifying literal tree structure, or writing a program that parses untrusted Lisp data, not knowing about the #. syntax and * read-eval* . I'm not advocating unsafe ignorance. Not knowing the full flexibility of some syntax is generally safe, though.
> Explain this:
Which aspect of that error scenario isn't self-explanatory; what is left to explain?
From that one error, the listener has just taught us several important facts about the syntax which it accepts (which may be a superset of ANSI CL for all we know). It shows us that it accepts a docstring after a declare just fine, but that there must be at most one docstring. (At least, when the two are in that order, if we are to be strict in our guessing.)
So without looking at a shred of documentation outside of that error message, I'm already better informed.
The interactive nature of Lisp teaches! (Especially if the implementation is tight on error checking and has good diagnostics.)
What's left unsettled from that error situation is whether or not there may be multiple declares, since that case isn't being probed.
Which says: any number of declarations and at most one documentation, in any order.
(defun foo (a b)
(declare (fixnum a)) ; declaration
"foo" ; documentation
"bar" ; form
(+ a b))
Which indicates that SBCL rejects a valid program. I would not trust you to get it right as an implementor, given that you haven't even tried to verify it and that you are ignorant to Lisp syntax. I would not trust my own implementation without trying to come up with an extensive syntax test suite.
Why not? A code review has topics. It could be to enforce a coding convention.
Firstly, I would not pass code that uses multiple docstrings or a funny order for docstrings and declares or multiple declares; a coding convention should forbid such pointless shenanigans, whether or not they are ANSI conforming.
If the topic of the review was to determine whether the code is ANSI CL conforming, then I wouldn't just feed it to the listener of SBCL or any other implementation. Obviously, implementations can be nonconforming. They can accept, without diagnostic, inputs that require a diagnostic, as well as inputs that are nonportable or entirely undefined.
You can't determine conformance of the code, or of the implementation, or both, without reading and interpreting the applicable standard, obviously. (You didn't have to labor this far if you just wanted me to say that.)
> Does SBCL implement the syntax correctly or does it reject valid programs?
Even if we determine that SBCL is rejecting valid programs, that version of SBCL will forever continue to do so. We have to change to a working construct to get the code working.
Once we do that, the status of the nonworking construct that we replaced with a working one is rather moot. We have found all instances of that construct and replaced it, after which it no longer occurs in our code.
We may submit a bug report against SBCL. Since we fixed the code not to interact with the bug/noncompliance, we don't care when, if ever, SBCL issues a fix.
The nonworking construct could have been avoided in the first place by sticking to the simplified "canonical" syntax:
You can program defun-s for the rest of your Lisp programming life this way and never know the full syntax. You're also vanishingly unlikely to run into an implementation which doesn't accept the variations on this canonical syntax.
Deviations from this form can be rewritten into this form.
The exception might be machine-generated deviations. Like multiple declares or docstrings that are piled on by some macrology: if you want their output to be canonicalized, you have to insert some processing pass to do that normalization. That is annoying, and so we will feel better if we can blame it on a nonconformance in the implementation, even if we still have to do this work.
> (defun foo () "a" "b" "c") ; sbcl rejects
That's somewhat nasty; yet, there is no reason to write this kind of defun by hand. "a" is obviously a docstring, and "c" the return value. But "b" is superfluous in the sense that it has no effect.
If "b" contains documentation, it should be merged into "a" to produce the canonical form (defun foo () "ab" "c"): "ab" is the doc, "c" the returned object. If that doesn't work, then I care; that is uproarious.
I might be interested in knowing whether the above "a" "b" "c" is in fact invalid ANSI CL, if I'm more invested in that rejected form; like I have some macrology that produces it (so fixing the situation requires more work than just hunting down a couple of bad defuns). That macrology could be reused in other projects and so on.
Still, the fact that SBCL rejects it means that I can't have it if we are targetting SBCL. A workaround for SBCL (if that's what it is) might as well be applied all across the board.
This [[]] notation is a special "splicing" extension of the BNF syntax which here indicates that there may be at most one docstring and any number of declarations, and these may appear in any order (so that a docstring can come between declares).
Hi lispm. I investigated this more deeply and I'm afraid I cannot conclude that SBCL is wrong.
The root of the problem is this splicing [[ ]] extended BNF notational concoction, in whose description we find this:
... For example, the expression
(x [[A | B* | C]] y)
means that at most one A, any number of B's, and at most one C can occur in any order. It is a description of any of these:
(x y)
(x B A C y)
(x A B B B B B C y)
(x C B A B B B y)
but not any of these:
(x B B A A C C y)
(x C B C y)
In the first case, both A and C appear too often, and in the second case C appears too often.
In the case of defun, we can identify C with documentation and y with forms. But documentation is a kind of form. According to the above, if we are given documentation documentation form, it doesn't match: documentation appears "too often". That appears to rule out "foo" "bar" as ill-formed, if "bar" is interpreted as documentation rather than form.
This is woefully badly specified; it is not clear how to unambiguously determine the extent of the symbols matched by a given [[ ]] notation.
There needs to be a clearly stated requirement that [[ ]], independently of what follows it, denotes (say) the longest possible sequence of symbols which is consistent with its constraints. The material which follows [[ ]] must then match against the remaining symbols in the form. Then it will be clear that given "foo" "bar", the "bar" string isn't part of the [[ declare(star) | documentation ]] spec, because the longest match ends with "foo" (if no declares follow).
Maybe it does. I'm afraid I cannot make head or tail out of the sentence "such that if n /=m and 1<=n,m<=j, then either Oin/=Oim or Oin = Oim = Qk, where for some 1<=k <=n, Ok is of the form Qk {star} . Furthermore, for each Oin that is of the form {Qk}1 , that element is required to appear somewhere in the list to be spliced. " Perhaps that rescues it somehow.
> This cognitive hurdle is real and it's why Lisp isn't more popular.
Nobody has the answer why language or language family X isn't more popular.
Thousands and thousands of languages have been invented since the dawn of computing. Only a handful are popular at any one time.
Simply by probability and statistics alone, a language is unlikely to be popular.
Some languages with awful, difficult syntax have enjoyed popularity.
Perl became popular because of cryptic syntax. Cryptic syntax is what is populist, not clean syntax.
Programming wannabes outnumber actual developers N:1 for rather large N. Programming wannabes feel smart when they remember and correctly use cryptic syntax. "Hey, look, I didn't use any parentheses in this because I memorized all 17 precedence levels!" "Wow, this linenoise-like sausage of symbols totally works! That is AWESOME!" "Bubble sort in 13 characters of code; I'm floored ...".
C is popular because of the reverence for the tricks that it allows, like Duff's device:
Lisp threatens these types of people whose competence is rooted in arcane syntax. It does that precisely because it's ultra-readable.
Even if you've never programmed Lisp, you can probably guess what this does with great accuracy:
(loop for x from 1 to 10
collecting x into list
maximizing x into max
finally (return (list max x)))
You certainly won't stumble over any issues of cryptic syntax, or precedence or whatever. You might face an impediment if you don't speak English, due to that language being used to name symbols like "loop" and "collecting".
People who claim that Lisp is not readable are disingenuous (promoting something else or jealously protecting their self-image of competence when the bulk of their CS and programming knowledge rests in the mastery of a handful of cryptic syntaxes), crazy/trolling or else cognitively different (such as dyslexics genuinely struggling with the syntax).
That is actually perfectly well formatted Lisp/Scheme code, indented exactly the way Emacs does it for you. Presumably you would want to close of one paren per line (C-style), but speaking as a Lisp programmer I would say that that just wastes vertical space while not improving legibility.
It works like this: suppose you have an expression all in one line:
(and (or (foo) (bar)) (not (xyzzy)))
Of course you close the parens together; just like in any other notation that uses parens. When the line is broken into mutiple lines, the parens just stay where they are:
The wonderful thing about "or" is that you can keep adding on to it and only one statement has to be true. "or not". I'll go with "or not". In any world where you have beginning programmers, or programmers not used to Lisp seeing ))))))))) at the end of a line, this is cognitively difficult to keep track of the number of closing braces without having some editor assist you doing the counting for you. This reminds me of indenting in python being touted as easier than having brackets as whitespace matters but editing is terrible without having line guides turned on when any deeper nesting arises.
> without having some editor assist you doing the counting for you
The problem with your statement is in just this point: everybody does have an editor that does this for you ;-) Unless you write code with ed, or Windows Notepad, I don't know of a single editor out there that doesn't do this.
Let me guess: you don't program lisps much? This is the preferred style of almost every lisp. After a week of it you don't see the parens, and after learning to program using paredit you won't even have to bother with them ever again.
I write object pascal for a living, and every second of it makes me long for the comfort of parens everywhere.
I think the reason you are being downvoted is because you obviously never spent much time learning scheme (or even looked at much scheme code). Yet you still condemn the code and say the person deserves "slaps". To anyone that actually knows scheme, this comes off as pretty ignorant, and _very_ arrogant.
This is the way people write lisps, and using tools like paredit, you don't really notice (or deal with) parentheses at all. They just end up there, and that's much better than having them on a new line. They are unimportant. If the code is properly aligned, having the parens on a new line would just be line noise.
To the contrary, Scheme's prefix notation reads quite well, particularly if you use indentation well. But that's just my opinion.
Several of the statements in this article about Scheme are, however, objectively wrong.
-Scheme isn't functional. It makes no effort to control side-effects, and a lot of Scheme is heavily stateful. In fact, the very Scheme example you wrote isn't functional at all!
-Scheme isn't uncomfortable for OO. Multiple OO frameworks have been written in Scheme (most of them based upon CLOS), and many of them are very comfortable and quite excellent. If you don't like multiple-dispatch functions, it's also possible to implement smalltalk-style object-message syntax (and indeed, people have done so).
In fact, if you look into the history of Scheme, it was orginally written by Sussman and Steele to help them understand the Actor Model, which is quite similar to OO: a program is modeled as many stateful actors, which can only communicate through messages.
Finally, the "confusing" Scheme code in this article is not very well written. If you split the definitions like so, it becomes much more readable (also, vector-map! is already defined in many schemes, so you don't even have to evaluate the top part):
(define (vector-map! f v)
(do ((i 0 (+ i 1)))
((= i 0) v)
(vector-set! v i (f (vector-ref v i)))))
(define (make-matrix rows columns)
(vector-map!
(lambda (a) (make-vector columns))
(make-vector rows)))
Again, there are several common extensions (in various SRFIs) that would make this even cleaner. In the upcoming R7RS-large (the Red standard, which has these functions, has just been released), I would merely need to import one library, and vector-map! would be defined for me, as is already true in many implementations.
Any readability problem in vector-map! there is an issue with some given Scheme and the available primitives that it has out of the box for writing it.
I should provide mappers that iterate over the places in a sequence.
;; Fantasy:
(each-place ((elem seq)) ;; seq is vector, string or list or whatever
(set elem [f elem])) ;; elem is mutable place alias
Good idea. Like non-const iterators in C++ or whatever.
If `[v i]` is repeated a lot in the body of the each, we can currently approximate this now with placelet, an invention of mine:
(each ((i (range (length v))))
(placelet ((elem [v i])) ;; once-only evaluation of [v i]!
(set elem [f elem]))) ;; elem can be used many times
That translation for the each-place fanatasy construct would work, but would be inefficient for lists; it has to use some type-specific iterator object under the hood to designate the place with constant-time access.
Lisp is forever malleable and can overcome any ergonomic problem that anyone wants; you just have to articulate the requirements clearly: "I don't like writing X; why can't it be expressed as Y".
Well, part of my point was that new primitives (vector-map!) are being introduced that makes this more convenient (and already exist in most Schemes). To your point, there are numerous loop macro sets that make the do in my vector-map! simpler, but I didn't want to introduce any external dependancies (or implementation dependancies), and I thought it was clear enough.
Well, that's the whole lisp family (and knowing Doug Hoyte's distaste for Scheme, he's probably explicitly talking about CL), but the arguments still apply.
I don't think it reads well. I came from ALGOL family as you'd expect. I always hated LISP syntax unless I was doing a parser or 4GL. LISP lovers have always acted like it's impossible to give in on this point to increase adoption whereas some had saner strategies:
Much more beautiful to read. You could almost turn syntax that looks like that into a scripting language with a good standard library. Would probably get widespread, commercial and FOSS adoption plus make Hacker News a lot. Just speculation on my part over ten years ago. Maybe give it a cute-looking, snake logo to symbolize making people like something they hate.
Nah, I'm sure lispers will miss this obvious strategy for success of their favorite language. :P
I do get your point, Nick, but I'm not sure I agree. Dylan, Nim, and other programming languages that try to have Lisp's macro facilities (which are the main reason we stick to the sexpr code format) may be nice to program in, but they're am absolute pain to metaprogram in. Just look at Nim's procedural macros, for crying out loud!
Also, many of us lispers like the regularity and simplicity of syntax that sexprs allow (no syntax, no precedence).
OTOH, a more direct sexpr mapping might work, a la wisp.
Seriously, if your main object to lisp is the syntax, wisp may be something you want to try.
Another thing to consider is how often people need to write macros. The vast majority of programmers will just use base language and libraries. The libraries contain the macros. Advanced programmers can create the macro libraries. This provides the massive benefit on adoption for regular programming without the drawback of metaprogramming. Further, the macro language might even use s-expr syntax that prettier language is converted to in first pass of parsing. So, instead of paren language as default, it's an ALGOL-like language as default with syntax extensions or mods being made for macro work. In reverse of of lispers normally do it.
Re WISP. Looks better but still prefix. The prefix notation is the problem as it's designed to be easy for computers & compiler writers, not humans reading it.
Yeah, that's closer to the WISP model, which works well, as opposed to what Dylan and Nim did.
As for the lack of infix in WISP, IIRC WISP supports use with SRFI-105 (a part of another project to introduce a different syntax to Scheme, SRFI-110, aka readable), which provides exactly this.
>>[Smalltalk is] the perfect instructional language for teaching programming to both children and adults alike. It’s very easy to learn and extremely versatile...
Where's the data to support this? Has anyone done a randomized double-blind study on new programming students using smalltalk vs groups using Scheme, JS, or Java? Why is someones biased opinion enough to justify this claim? We need to hold ourselves to a higher standard than to accept unsupported arguments (meaning they havent been tested empirically) [1].
Just curious, have you learned ST ? I went through a good deal of languages and I have to admit, ST surprised me more than expected and mostly positively.
I don't like the smug some STers glow when they talk about REALOO but except that it really has some exceptional qualities (self consistency, humane interface, small size of the basic system).
I haven't learned ST yet but look forward to someday; currently I'm learning a bit of Ruby. I don't doubt that it is an excellent language, but is it actually easier to learn without any prior programming experience, or is that claim it just based on opinions?
I don't know any methodical study, so it may only be opinions. That said, after suffering years of bad language features, you feel weird when one actually delivers on some bold claims. Smalltalk is not even a language, it's a system, a self contained system that is quite small, consistent, yet somehow devoid of ceremony (FP languages are small, but one has to read through the culture, ST stay low in intellectualization). I don't see many of the things that tripped me up as a noob, and lots of stuff that I ended up seeing as valuable (how booleans are defined for instance).
To support your claim, people have been learning BASIC, Oberon, and [on kid side] Scratch very well for a long time. I'd love to see Smalltalk with its OOP testing against those. My guess is structured programming in BASIC or Scratch will come out ahead.
Anecdotal: my 8-year old daughter loves Scratch, and I noticed that what she found the most intuitive was the message passing aspect of it. Assuming my kid is average in this respect, Smalltalk might have an edge in teaching kids how to code.
That makes sense. Kids will have passed messages person to person or place to place. Taking turns drawing on the same area is a bit less common. Doing math together exclusively by writing & erasing numbers on same, physical space would be extremely weird. Might be a better metaphor for shared-state concurrency. That's just what popped into my head thinking of the common examples people start out with like bank transfers.
Scheme: Show me the code comparison. How is FP vs OOP relevant, even if true?
JavaScript: How is the comparison to Lisp relevant, especially after the preceding? Author just chose some appealing praise of JavaScript to tear down.
Java: This reduces to an argument you should consider SmallTalk at all for systems programming.
I found the critique unconvincing, especially since I don't see any Smalltalk examples in the article to support his position. Not I that I doubt there are languages better than both JavaScript and Java.
Since it is addressing beginning programmers, I would like to add my take. I'm not a programmer but I have many years worth of computer experience. Programming never appealed to me because it never came naturally.
Lately I (once again) started paying attention to programming and started looking around. I went from one e-book and MOOC to another with much of the python hype (previously in my - failed - attempt, I tried Perl, PhP etc, when they were in vogue). Well I have eventually concluded, that the problem with programming is not necessarily me, but it is the lack of proper padagogy itself. There are programmers galore out there trying to teach via YouTube and MOOCs, but most are code monkeys who know what they're doing but I wouldn't call them "teachers".
So my search eventually led me to Scheme/Racket where I see some signs and hope of proper learning (I'm not going to be able to afford myself to take a college level CS). I looked into Small Talk as well but as of now I don't see a proper MOOC on it. I have started Racket course (BSL) on EdX. After spending much time and energy chasing Python basics and going nowhere, i feel I can possibly and eventually learn programming the way it is meant to be.
77 comments
[ 2.9 ms ] story [ 73.0 ms ] threadGranted that javascript is inconsistent and poorly designed. But what does he expect a beginner programmer to do? Learn a language has neither widespread acceptance nor community support, in an attempt to get away from javascript's deficiencies?
Even Google could not wean sophisticated programmers (who appreciate the issues way better than I and many others do) away from javascript despite its incredible efforts.
I for one am interested in getting the job done quickly and as painlessly as possible. I dont make the tools I just use them.
Thoughts anyone?
You're right about Ice Ice Baby, though.
But a successful language requires those things, for the masses (not the early adopters). That creates glacial inertia, even for individuals.
Not sure what you mean.
Angular 2 is typescript-first.
Smalltalk is immensely cleaner and gives you IMHO a much deeper more gratifying experience working in it. Yes, it's OO all the way, while Javascript is... well, not sure what to call it these days ;) A hodgepodge perhaps. But the real magic in Smalltalk is in the live environment.
It all boils down to the Right Tool for the Right Job. If you are looking for a really powerful tool for abstraction and working interactively with advanced domain models, often using meta capabilities - then Smalltalk totally rocks. The more advanced, the more it shines.
But of course Smalltalk has its negative sides too, and it depends on your specific use case. It's (if we consider the Cog VM which is the most common one) pretty fast, but comes short of V8. It can interoperate with other languages, but it's not as easy as in some other languages. It has a decent community, but not as large as Javascript/Python/Ruby. And so on.
But when your use case fits - it's really good. So my advice is learn many languages, it will make you a better developer, and its fun!
<promotion>Personally I am trying to evolve Smalltalk by merging it with ideas from Lisp, JavaScript and Rebol: sprylang.org</promotion>
However, in 1995 Java was nothing more than a hopeful upstart from Sun Microsystems. There were no job opportunities for it. It had no ecosystem to speak of and relatively few users. Performance-wise, it ran like a slug (today, the JVM is well-optimized). How did Java achieve today's status?
To a large extent, it was thanks to Sun Microsystem's marketing efforts. People were drawn to the promise of "write once, run everywhere." They also liked that Java was a fairly simple and easy-to-learn language. In time, Java developed a large community and widespread usage.
The point is, all programming languages have to start from zero. They either grow from grassroots, or they grow from corporate sponsorship and marketing. Incumbent languages with their large ecosystems and user communities eventually yield to newer languages with their promise of greater ease, productivity, flexibility, power, etc. Getting the job done is important, but one should also look to the future. That's the hope of languages such as Go, Swift, Dart, Julia, Rust, Elixir, Smalltalk, and so on.
As far as I'm aware the ideas used in hotspot began with Self[1], which was also the inspiration for Javascript's prototypical inheritance. Strongtalk[2] adapted these to the class/instance programming style of Smalltalk, then Sun bought them for application to Java.
[1] https://en.wikipedia.org/wiki/Self_(programming_language)
[2] https://en.wikipedia.org/wiki/Strongtalk
Many programmers obsess over performance, but the fact is, in today's computing world, performance is a non-issue in most situations. That's why Python, PHP, Ruby, and Perl are so useful and popular. That's why Erlang/Elixir absolutely rock for concurrent systems. That's why Smalltalk is used commercially around the world. Performance is not the be-all, end-all of computing.
Any decent editor will balance the parentheses for you.
Further, once the brain flip happens, languages that don't use S-expressions start to feel uncomfortably... uncontained.
In my experience, the parens nonsense comes almost entirely from programmers with no Lisp coding experience.
It's based on "that looks as if it might be hard to edit".
"Wait, you mean you were willing to reason through pointer arithmetic, monads, implementing a b-tree, etc. but you simply saw the parens and decided that would forever be the thing that you cannot, will not overcome? I mean in spite of all the fairly objective benefits of having a perfectly regular syntax, and code that can be processed by computers?"
Moreover, for many programmers, it's asking too much of them to wrap their heads around a syntax where you need to give it time for the parens to "fade" away. This cognitive hurdle is real and it's why Lisp isn't more popular.
Let's not bury our heads in the sand.
Lisp uses different working styles and tools. You have to learn the whole set. It's possible to learn that and to learn it well, but it might take some time.
Lisp code can be very readable, but it's also to write very complex code - more complex that in most languages, since Lisp provides many mechanisms under developer control.
You don't have to crack open a reference manual to look at grammar rules or precedence tables to work out what the shape of the syntax tree is; you can read anything just from the symbolic prefix, plus a smattering of minor notations like sharpsign-this and sharpsign-that.
A programmer who doesn't know Lisp can still instinctively tell that in (foo (x y) (z w)), the x and y go together more tightly than foo and x, or y and z.
The meaning is determined by foo. But foo is a word. And words have the nice property that you can look them up easily in manuals (potentially with just a mouse click).
Those who say Lisp is not readable are trolls and liars. They are liars because they see it's obviously more readable, but it threatens their self-image of being a competent programmer. It does that because their self-image is rooted in having memorized a bunch of arcane syntax and believing that that is what makes a software developer.
Look at this comment, for instance:
https://news.ycombinator.com/item?id=12883362
"If only the LISP syntax looked like a programming language and made logical sense."
Very good representative comment which captures the mindset aptly.
A programming language can only possibly be legit only if programs in that look like what you already know.
You can't. Any macro may support arbitrary syntax. If all you know is the macro name, you don't know nothing about the syntax it implements.
> (foo (x y) (z w))
There are many many much more complex forms in Lisp.
> And words have the nice property that you can look them up easily in manuals
Then you have to read the syntax FOO implements.
DEFGENERIC:
Then you need to know the set of precedence order names. What is a GF-DECLARACTION? What is a method-qualifier? what is the specialized-lambda-list? What are valid declaration expressions...?> Those who say Lisp is not readable are trolls and liars.
I don't think you add credibility with these statements. Sorry, this is just dumb.
Even though macros can contain any syntax, and in principle we can have a macro such that:
where the tokens are parsed according to some LALR(1) (or worse) grammar, in practice, macros are usually not designed that way. The nested list syntax is used for grouping units together.So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear.
Of course you need the manual to know what they mean if you don't remember (gee, which is the class name and which is the instance, location or point?), but you don't have to implement the LARL(1) parser in your head.
I was talking about DEFGENERIC syntax, not a trivial example of DEFGENERIC/DEFMETHOD.
> Even though macros can contain any syntax...practice, macros are usually not designed that way.
The LOOP and ITERATE macros are examples of macros with lots of syntax.
> So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear.
The syntax of DECLARE, DEFGENERIC, HANDLER-CASE, HANDLER-BIND, DEFINE-CONDITION, DEFINE-METHOD-COMBINATION, LOOP, FORMAT, ... are far from 'crystal clear'.
One of the macros which is very hard to get right and to understand what it actually does is CLIM:DEFINE-APPLICATION-FRAME
Example:
Which of the following forms are valid Common Lisp:
I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body; then there can be declarations. Not sure if there can be two or more declares. I would always write (declare (fixnum a) (fixnum b)) and don't recall seeing multiple declares in other people's code. (I might be suffering from a form of amnesia which merges multiple ANSI Lisp declares into one.)
This is the sort of thing I'd look into closely if I were tasked with parsing a function body (like for the sake of making some body rearranging-and-reassembling macro fully conforming with the surrounding language). I'm not going to write such code myself, and won't likely see it in other people's code.
Until I see such instances, I won't bother looking at the spec to see what the exact rules are and confirm/refute whether those examples are conforming.
In any case, whether or not some of the examples are correct, I can see what they are trying to say. Be they mistakes, they are still well-formed surface syntax and are readable. Things could plausibly work in some CL dialect such that they are all correct, if they aren't.
A literal string near the beginning of a function, which is only evaluated for its side effect (which it doesn't have) looks suspiciously like a doc string. Either it is correctly positioned or it isn't. The (declare ...) syntax is clearly a declaration, whether or not correctly positioned. (declare ...) isn't a form. I suspect it would be undefined behavior for a program to define a function or macro called declare; not sure about that. Defined or not, it would be a incredibly bad idea.
I'm a competent Lisp programmer and implementor too, and don't have to have this memorized; it's likely not an impediment to anyone else. Which kind of makes my point.
A Lisp programmer has to care, if he wants to write Lisp code.
> I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body
That's wrong.
> I won't bother looking at the spec to see what the exact rules are
Which confirms what I'm saying: even for seemingly trivial DEFUNs the syntax is not obvious.
> Be they mistakes, they are still well-formed surface syntax and are readable.
But the reader does not implement Lisp syntax. The reader just implements s-expression syntax. If the reader can read the form, then it is a valid s-expression. But not necessarily valid Lisp.
The Lisp interpreter/compiler and the macros implement Lisp syntax. Not the reader.> it's likely not an impediment to anyone else.
That you don't know the syntax of DEFUN confirms what I'm saying: the syntax is non-obvious.
Explain this:
Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!!
If I don't have to know, few people do.
You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course. I don't have some "requirements don't matter" attitude; but not all requirements matter all the time to all people.
I'd like to add, though, this: you can't be safe in ignorance in Common Lisp. Things you don't know can hurt you. Less than in some other languages, but they are there. You probably won't be hurt by not knowing all the possibilities for combining docstrings and declares. But if you're ignorant of some things, you may get burned. Undefined behavior situations like modifying literal tree structure, or writing a program that parses untrusted Lisp data, not knowing about the #. syntax and * read-eval* . I'm not advocating unsafe ignorance. Not knowing the full flexibility of some syntax is generally safe, though.
> Explain this:
Which aspect of that error scenario isn't self-explanatory; what is left to explain?
From that one error, the listener has just taught us several important facts about the syntax which it accepts (which may be a superset of ANSI CL for all we know). It shows us that it accepts a docstring after a declare just fine, but that there must be at most one docstring. (At least, when the two are in that order, if we are to be strict in our guessing.)
So without looking at a shred of documentation outside of that error message, I'm already better informed.
The interactive nature of Lisp teaches! (Especially if the implementation is tight on error checking and has good diagnostics.)
What's left unsettled from that error situation is whether or not there may be multiple declares, since that case isn't being probed.
That you don't know the relatively trivial syntax of DEFUN, shows that it is already non-obvious and you have to look it up.
You have failed to explain the syntax of DEFUN and you can't distinguish valid from invalid forms. I would never trust a code review done by you.
> You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course.
Maybe. Maybe not.
> Which aspect of that error scenario isn't self-explanatory; what is left to explain?
Is that valid or not, given the syntax of Common Lisp? Does SBCL implement the syntax correctly or does it reject valid programs?
The syntax of DEFUN is:
Which says: any number of declarations and at most one documentation, in any order. Which indicates that SBCL rejects a valid program. I would not trust you to get it right as an implementor, given that you haven't even tried to verify it and that you are ignorant to Lisp syntax. I would not trust my own implementation without trying to come up with an extensive syntax test suite.Similar:
Why not? A code review has topics. It could be to enforce a coding convention.
Firstly, I would not pass code that uses multiple docstrings or a funny order for docstrings and declares or multiple declares; a coding convention should forbid such pointless shenanigans, whether or not they are ANSI conforming.
If the topic of the review was to determine whether the code is ANSI CL conforming, then I wouldn't just feed it to the listener of SBCL or any other implementation. Obviously, implementations can be nonconforming. They can accept, without diagnostic, inputs that require a diagnostic, as well as inputs that are nonportable or entirely undefined.
You can't determine conformance of the code, or of the implementation, or both, without reading and interpreting the applicable standard, obviously. (You didn't have to labor this far if you just wanted me to say that.)
> Does SBCL implement the syntax correctly or does it reject valid programs?
Even if we determine that SBCL is rejecting valid programs, that version of SBCL will forever continue to do so. We have to change to a working construct to get the code working.
Once we do that, the status of the nonworking construct that we replaced with a working one is rather moot. We have found all instances of that construct and replaced it, after which it no longer occurs in our code.
We may submit a bug report against SBCL. Since we fixed the code not to interact with the bug/noncompliance, we don't care when, if ever, SBCL issues a fix.
The nonworking construct could have been avoided in the first place by sticking to the simplified "canonical" syntax:
You can program defun-s for the rest of your Lisp programming life this way and never know the full syntax. You're also vanishingly unlikely to run into an implementation which doesn't accept the variations on this canonical syntax.Deviations from this form can be rewritten into this form.
The exception might be machine-generated deviations. Like multiple declares or docstrings that are piled on by some macrology: if you want their output to be canonicalized, you have to insert some processing pass to do that normalization. That is annoying, and so we will feel better if we can blame it on a nonconformance in the implementation, even if we still have to do this work.
> (defun foo () "a" "b" "c") ; sbcl rejects
That's somewhat nasty; yet, there is no reason to write this kind of defun by hand. "a" is obviously a docstring, and "c" the return value. But "b" is superfluous in the sense that it has no effect.
If "b" contains documentation, it should be merged into "a" to produce the canonical form (defun foo () "ab" "c"): "ab" is the doc, "c" the returned object. If that doesn't work, then I care; that is uproarious.
I might be interested in knowing whether the above "a" "b" "c" is in fact invalid ANSI CL, if I'm more invested in that rejected form; like I have some macrology that produces it (so fixing the situation requires more work than just hunting down a couple of bad defuns). That macrology could be reused in other projects and so on.
Still, the fact that SBCL rejects it means that I can't have it if we are targetting SBCL. A workaround for SBCL (if that's what it is) might as well be applied all across the board.
So is it ANSI CL or not? The syntax is:
This [[]] notation is a special "splicing" extension of the BNF syntax which here indicates that there may be at most one docstring and any number of declarations, and these may appear in any order (so that a docstring can come between declares).The root of the problem is this splicing [[ ]] extended BNF notational concoction, in whose description we find this:
... For example, the expression
means that at most one A, any number of B's, and at most one C can occur in any order. It is a description of any of these: but not any of these: In the first case, both A and C appear too often, and in the second case C appears too often.In the case of defun, we can identify C with documentation and y with forms. But documentation is a kind of form. According to the above, if we are given documentation documentation form, it doesn't match: documentation appears "too often". That appears to rule out "foo" "bar" as ill-formed, if "bar" is interpreted as documentation rather than form.
This is woefully badly specified; it is not clear how to unambiguously determine the extent of the symbols matched by a given [[ ]] notation.
There needs to be a clearly stated requirement that [[ ]], independently of what follows it, denotes (say) the longest possible sequence of symbols which is consistent with its constraints. The material which follows [[ ]] must then match against the remaining symbols in the form. Then it will be clear that given "foo" "bar", the "bar" string isn't part of the [[ declare(star) | documentation ]] spec, because the longest match ends with "foo" (if no declares follow).
Maybe it does. I'm afraid I cannot make head or tail out of the sentence "such that if n /=m and 1<=n,m<=j, then either Oin/=Oim or Oin = Oim = Qk, where for some 1<=k <=n, Ok is of the form Qk {star} . Furthermore, for each Oin that is of the form {Qk}1 , that element is required to appear somewhere in the list to be spliced. " Perhaps that rescues it somehow.
Nobody has the answer why language or language family X isn't more popular.
Thousands and thousands of languages have been invented since the dawn of computing. Only a handful are popular at any one time.
Simply by probability and statistics alone, a language is unlikely to be popular.
Some languages with awful, difficult syntax have enjoyed popularity.
Perl became popular because of cryptic syntax. Cryptic syntax is what is populist, not clean syntax.
Programming wannabes outnumber actual developers N:1 for rather large N. Programming wannabes feel smart when they remember and correctly use cryptic syntax. "Hey, look, I didn't use any parentheses in this because I memorized all 17 precedence levels!" "Wow, this linenoise-like sausage of symbols totally works! That is AWESOME!" "Bubble sort in 13 characters of code; I'm floored ...".
C is popular because of the reverence for the tricks that it allows, like Duff's device:
https://en.wikipedia.org/wiki/Duff's_device
Lisp threatens these types of people whose competence is rooted in arcane syntax. It does that precisely because it's ultra-readable.
Even if you've never programmed Lisp, you can probably guess what this does with great accuracy:
You certainly won't stumble over any issues of cryptic syntax, or precedence or whatever. You might face an impediment if you don't speak English, due to that language being used to name symbols like "loop" and "collecting".People who claim that Lisp is not readable are disingenuous (promoting something else or jealously protecting their self-image of competence when the bulk of their CS and programming knowledge rests in the mastery of a handful of cryptic syntaxes), crazy/trolling or else cognitively different (such as dyslexics genuinely struggling with the syntax).
Compare these two links:
https://www.emacswiki.org/emacs/CodingStyle
http://stackoverflow.com/questions/2207255/lisp-parentheses
It works like this: suppose you have an expression all in one line:
Of course you close the parens together; just like in any other notation that uses parens. When the line is broken into mutiple lines, the parens just stay where they are: Beauty. This does not require additional editing to make: Yikes! If you do this you will get flak from almost every Lisp programmer. (Why piss off those nice five or six people?)This is done the same way in common coding styles in other languages, like, C:
It's not commonly done with braces in C-family languages, but that is neither here nor there; and it can be done fairly nicely with those braces.The problem with your statement is in just this point: everybody does have an editor that does this for you ;-) Unless you write code with ed, or Windows Notepad, I don't know of a single editor out there that doesn't do this.
We.
Have.
Those.
I wouldn't use any editor which can't do this and would have no reason to.
I wouldn't use it for Lisp. I also wouldn't use it for editing C, Makefiles, shell scripts, or anything else.
Speaking of makefiles, here is a quote:
That is from: https://github.com/torvalds/linux/blob/master/MakefileMaybe you should try arguing your inane point on the Linux kernel mailing list!
I write object pascal for a living, and every second of it makes me long for the comfort of parens everywhere.
This is the way people write lisps, and using tools like paredit, you don't really notice (or deal with) parentheses at all. They just end up there, and that's much better than having them on a new line. They are unimportant. If the code is properly aligned, having the parens on a new line would just be line noise.
Several of the statements in this article about Scheme are, however, objectively wrong.
-Scheme isn't functional. It makes no effort to control side-effects, and a lot of Scheme is heavily stateful. In fact, the very Scheme example you wrote isn't functional at all!
-Scheme isn't uncomfortable for OO. Multiple OO frameworks have been written in Scheme (most of them based upon CLOS), and many of them are very comfortable and quite excellent. If you don't like multiple-dispatch functions, it's also possible to implement smalltalk-style object-message syntax (and indeed, people have done so).
In fact, if you look into the history of Scheme, it was orginally written by Sussman and Steele to help them understand the Actor Model, which is quite similar to OO: a program is modeled as many stateful actors, which can only communicate through messages.
Finally, the "confusing" Scheme code in this article is not very well written. If you split the definitions like so, it becomes much more readable (also, vector-map! is already defined in many schemes, so you don't even have to evaluate the top part):
Again, there are several common extensions (in various SRFIs) that would make this even cleaner. In the upcoming R7RS-large (the Red standard, which has these functions, has just been released), I would merely need to import one library, and vector-map! would be defined for me, as is already true in many implementations.TXR Lisp:
I should provide mappers that iterate over the places in a sequence. Good idea. Like non-const iterators in C++ or whatever.If `[v i]` is repeated a lot in the body of the each, we can currently approximate this now with placelet, an invention of mine:
That translation for the each-place fanatasy construct would work, but would be inefficient for lists; it has to use some type-specific iterator object under the hood to designate the place with constant-time access.Lisp is forever malleable and can overcome any ergonomic problem that anyone wants; you just have to articulate the requirements clearly: "I don't like writing X; why can't it be expressed as Y".
"Scheme is a functional programming language ..."
-- https://en.wikipedia.org/wiki/Scheme_(programming_language)
http://letoverlambda.com/index.cl/guest/chap5.html
https://www.quora.com/Should-Lisp-be-considered-a-functional...
https://en.wikipedia.org/wiki/Dylan_(programming_language)
Much more beautiful to read. You could almost turn syntax that looks like that into a scripting language with a good standard library. Would probably get widespread, commercial and FOSS adoption plus make Hacker News a lot. Just speculation on my part over ten years ago. Maybe give it a cute-looking, snake logo to symbolize making people like something they hate.
Nah, I'm sure lispers will miss this obvious strategy for success of their favorite language. :P
Also, many of us lispers like the regularity and simplicity of syntax that sexprs allow (no syntax, no precedence).
OTOH, a more direct sexpr mapping might work, a la wisp.
Seriously, if your main object to lisp is the syntax, wisp may be something you want to try.
Re WISP. Looks better but still prefix. The prefix notation is the problem as it's designed to be easy for computers & compiler writers, not humans reading it.
As for the lack of infix in WISP, IIRC WISP supports use with SRFI-105 (a part of another project to introduce a different syntax to Scheme, SRFI-110, aka readable), which provides exactly this.
Where's the data to support this? Has anyone done a randomized double-blind study on new programming students using smalltalk vs groups using Scheme, JS, or Java? Why is someones biased opinion enough to justify this claim? We need to hold ourselves to a higher standard than to accept unsupported arguments (meaning they havent been tested empirically) [1].
[1] https://www.youtube.com/watch?v=uEFrE6cgVNY
I don't like the smug some STers glow when they talk about REALOO but except that it really has some exceptional qualities (self consistency, humane interface, small size of the basic system).
Scheme: Show me the code comparison. How is FP vs OOP relevant, even if true?
JavaScript: How is the comparison to Lisp relevant, especially after the preceding? Author just chose some appealing praise of JavaScript to tear down.
Java: This reduces to an argument you should consider SmallTalk at all for systems programming.
Lately I (once again) started paying attention to programming and started looking around. I went from one e-book and MOOC to another with much of the python hype (previously in my - failed - attempt, I tried Perl, PhP etc, when they were in vogue). Well I have eventually concluded, that the problem with programming is not necessarily me, but it is the lack of proper padagogy itself. There are programmers galore out there trying to teach via YouTube and MOOCs, but most are code monkeys who know what they're doing but I wouldn't call them "teachers".
So my search eventually led me to Scheme/Racket where I see some signs and hope of proper learning (I'm not going to be able to afford myself to take a college level CS). I looked into Small Talk as well but as of now I don't see a proper MOOC on it. I have started Racket course (BSL) on EdX. After spending much time and energy chasing Python basics and going nowhere, i feel I can possibly and eventually learn programming the way it is meant to be.
The actual course is over, but all the course material is still available. It's an excellent resource.