Does it need to blend? Were Racket the only supported scripting language for Oculus I'm sure people would just learn Racket rather than skipping out on Oculus.
No need to learn Racket, it's easy to build any language on top of it. Having a single meta-language as a base allows diversity and choice for end users that is not possible with any of the inferior (non-meta) languages.
The code you pasted is used to illustrate the concepts of ports. You took it out of context. It's not an example of hello world like you're claiming. Also, the code on Wikipedia doesn't always match actual practice of programming in a language..
If you want to see more realistic examples go to RosettaCode, pick interesting task and look for Scheme, Racket and Clojure entries. You can then compare them to each other and to other languages you know.
The other thing is that your code in Scheme and Dart don't do the same thing at all, unless I underestimate Dart semantics very much. A translation of your Scheme code to JS, with as much semantics preserved as possible, would look something like:
(function (){ // let introduces new scope
var hello0 = function (){ // hello0 is a variable holding an anonymous function
return console.log("Hello world");
};
return hello0();
})();
That's quite a bit of work less in Scheme, isn't it? But for when you don't need these semantics you can do a translation the other way round (Dart->Lisps). In Racket your Dart example would look like:
To expand on this a little, here is a thing that you can't translate to most programming languages. By defining a simple, pattern-based macro we can get much closer to the Dart version:
I used to program in a LISP (the language predates Lisp) derivative called "Boot". (It booted a computer algebra system.) It added two rules to LISP: unparenthesized expressions bind "to the function call", using dynamic lookup to determine arity, and failing if the binding wasn't unambiguous; and, ';' to delimit expressions. It's been a decade since I used the language, but it would look something like this:
define (hello)
displayln "Hello, World!";
hello;
The boot 'compiler' only did name resolution and parenthesization, then it kicked everything back to an underlying LISP. (In this case, SBCL, which rocked!)
The second level language built on Boot was Spad, which used a slightly friendlier syntactic top-form:
e : t = x
With compact forms:
e := x
e = x
e : t
e
Which lets you uniformly parse packages, modules, domains, categories, functions, annotations, etc. etc. For instance, we had a Spad-lite syntax:
You can't effectively criticise a language without actually knowing it. That's why you're being downvoted.
The example you gave is using the lowest level primitives to printing with zero syntactic sugar. It's equivalent to writing the following in JavaScript (assuming functions called 'display' and 'newline':
> However, I dislike it from a practical point of view,
How can you be disliking it from a practical point of view if you don't use it in practice? Don't you think it would be different if you tried actually learning Scheme for a week? Do you think it would still be unreadable to you after that week? Why do you think so?
Also, take a look at APL or J if you want to see "unreadable" language.
> How can you be disliking it from a practical point of view if you don't use it in practice?
I had plenty of exposure to deeply nested things. This is pretty much like nested function calls. "foo(a, b)" and "(foo a b)" isn't all that different, is it?
I prefer to have different bits of syntax for different things because it looks less uniform. I like it when different things stick out in different ways.
> Also, take a look at APL or J if you want to see "unreadable" language.
Both of these aren't even in the top 50. Can you think of a somewhat popular (non-legacy) language?
Nested lists are similar to nested function calls. Did you skip the rest of the paragraph?
> the "things" are sticking out in a variety of ways
No, they don't. Syntax-wise, everything is the same.
"Scheme's very simple syntax is based on s-expressions, parenthesized lists in which a prefix operator is followed by its arguments. Scheme programs thus consist of sequences of nested lists."
There shall be nested lists. That's all, folks!
In other languages, you have syntax for importing stuff, syntax for declaring a variable, syntax for different loop constructs, syntax for branching, syntax for classes/methods/functions...
Each building block comes with its own syntax.
This isn't as elegant as having one universal construct for everything, but it's easier to use (once you got used to it), because the syntax itself carries a lot of the information.
(define (square x)
(* x x))
I rather write something like:
square(x) => x * x;
"bla(...)" is a bit of syntax for defining a function. "=>" is a bit of syntax for defining a lambda. "x * x" is a bit of syntax for using x's "star" operator.
> Again, I don't understand what you mean.
J and APL aren't popular languages. There are many unpopular languages with worse syntax. They are also both array programming languages which is a rather odd niche.
This is simply the case of getting used to something. The Lisp code reads like this: (define A B) -> define A to be B. You define (square x) to mean (* x x). It requires you to know only one syntax rule - that (f a b ...) means "apply f to arguments a, b, ...". The above code basically reads "define applying square to x to mean applying * to x and x".
> They are also both array programming languages which is a rather odd niche.
Array programming may seem like an odd niche if the only thing one knows is web development, but the moment you actually start doing some maths, they become incredibly useful. Another, much more popular (and crappier, which seems to be a common correlation, but that's a different story) array programming language is MATLAB. Also you've probably heard of R, loved in statistics and sciences, which is another array language.
> This is simply the case of getting used to something.
My point was that other languages provide more visual hooks. Lisp is just words and parens. Nothing sticks out. Everything is the same.
So, you can't learn this "visual vocabulary" because there simply isn't any. There is a thing at the beginning of each list and what follows are the parameters. That's it.
"(define x 5)", "(square x)", and "(+ x x)" are syntactically the same thing.
> Array programming may seem like an odd niche if the only thing one knows is web development
You make it sound like it's either web stuff or maths.
Array programming languages aren't used for scripting (e.g. games), are they?
How many of those visual hooks are provided by syntax highlighting? You have that in Lisp as well. Moreover, you don't need that many syntax hooks; you learn to recognize words, just like when reading a book, and also indentation structure.
> Array programming languages aren't used for scripting (e.g. games), are they?
They've been used at least once, if you count one demo and one game I wrote in MATLAB. Man, you wouldn't believe how convenient array languages are when you need to do, things like polygon mesh interpolation (morphing), not to mention actual array operations like multiplying matrices or vectors. MATLAB may be a crappy language, but the array operations? I wish I had them in C++/Java for games.
If you interpret "array programming language" as "language with support for arrays and matrices as first-class objects with nice operators, etc" then you get a lot more things coming into the mix beyond oddballs like apl.
> but it's easier to use (once you got used to it)
No, actually it's easier to both read and write and edit sexps once you get used to it. This whole thread is about this: you have no practical Lisp experience yet you claim Lisp is not practical. You couldn't be bothered to actually learn more of a language, but you want to tell us how the experience of using it looks like.
It doesn't work that way. You can only compare things meaningfully when you have comparable knowledge of both. You apparently don't. There are many people who do know both "normal" languages and Lisps and most of them seem to agree that in practice Lisps are as readable as other syntaxes. But you don't want to believe in it for some reason and you don't even want to see for yourself.
> square(x) => x * x;
Why don't you answer my earlier posts, where I show how to make similar syntax in Lisp?
> J and APL aren't popular languages.
But that is completely irrelevant. I'm talking about language features and practice/experience of programming with it, I don't care at all about "popularity".
> If you extend it with your own syntax, it becomes a different language.
...but that's exactly what programming Lisp looks like. Becoming a different language every time you need it to is business as usual in Lisp. Syntactic abstraction - ability to extend language syntax - is central to Lisp programming.
> If you extend it with your own syntax, it becomes a different language.
No. This is exactly what Lisp is for. If you're not transforming it into hundreds of small DSLs (with their own syntax and a wide variety of semantic properties), then you're not using it right, and missing on all of its expressive power. In such case, yes, you may get rightfully puzzled, what all the Lisp buzz is about if it's just all the same stuff, but with an ugly syntax.
"Scheme's very simple syntax is based on s-expressions, parenthesized lists in which a prefix operator is followed by its arguments. Scheme programs thus consist of sequences of nested lists."
That's as uniform as it gets. Everything is the same.
This is a thread about Racket, if you did not notice.
> Are you really arguing that implementing some other language is the way to go?
This is exactly what Lisps are about. You've got a nearly raw AST at the bottom (S-expressions) and then you build up a hierarchy of languages on top of it.
This applies globally; when it makes sense, differentiate between some lists by using brackets instead of parens. Some Lisps take this further by using other bracket types to signify certain things.
I would advise not to hop on Wikipedia and assume things about languages. Scheme is not very hard to get into and with variants where batteries included you can build useful stuff right out of the box.
Go to http://www.racket-lang.org/ if you want to see a good example of a pragmatic and useful Scheme variant that may just dispel some of your prejudices.
> Scheme and all the other Lisp variants look terrible to me
Baby duck syndrome?
> Having an excessively simple syntax doesn't mean that it's nice to use.
Having an excessively simple syntax ensures that you can add any amount of syntax on top of it, whatever you fancy. Do not like S-expressions? Fine. Code in any syntax you like.
> but this is much easier to understand, isn't it?
All Scheme variants are approximately as verbose as your second example, except you don't have to assume hello is global. Internal defines are part of the R4RS standard published in 1991.
> Or assuming hello is a global in your dart example
The way it's written implies that it's somewhere inside some block, because "main()" is always the entry point. I wrote it like that because I couldn't be bothered to figure out how this stuff works in Scheme.
> I wrote it like that because I couldn't be bothered to figure out how this stuff works in Scheme.
I think that sums everything up, really. This is how shallow the complaints about parens are. No one who actually bothers will make a point about what delimits expressions in a language.
To complain about parens is also doubly wrong, as they do bring something technical to the table.
What Carmack talks about when he says S-expressions are nice for reading in terms of network communication, for example, is that the messages can be read exactly like other expressions over the wire. This is true for any I/O; you can read the data just as if it was code, because the code is data. The same mechanism that reads the code you are executing is available to you to read full expressions through any medium, and use that data/code as you see fit.
I didn't complain about parenthesis. ASM's syntax is also extremely simple, but that doesn't make it easy to use, does it? If everything looks the same, it's hard to scan.
C-like languages provide more visual hooks than Lisp dialects.
I'm currently using Java and Javascript for work. Previously I used Scheme. I do find that scanning is important in Java and JavaScript because often you don't need to read a whole section, just a piece. Back when I worked with Scheme, if I didn't need to read a whole section, generally the part I needed to know was right at the beginning. I think all Lisp dialects work this way.
The worst example is immediate function application in JavaScript. You get to the end and all of a sudden the }(); tells you everything you've just read is a different context than you thought it was. In Scheme (and probably most Lisps) you'd recognize immediate function application at the beginning as soon as you saw ((.
I don't know how people get really good at JavaScript without learning Scheme first.
And the Clojure example makes me say "aaah the ambiguity!" The key/value pairs makes much more sense to me when they are delimited as such. It's a minor point, anyhow. Clojure is just fine. I just don't think that it is significantly less verbose than Scheme. Let's just keep hacking with Lisps and be happy. :)
It's dramatically less verbose when you are dealing with code that uses associative data structures, both because of having nicer literal syntax and because the data structures can be applied directly without needing to reach for things like hash-ref. (Which makes a boatload of sense, because immutable hash maps actually have more in common with mathematical functions than Scheme procedures do.) In addition, functional nested updates are very verbose in Scheme.
However, both of these problems can be solved in Racket by third-party libraries.
Less ambiguity, all of the clarity of what is what. I don't get why you use other delimiters for your Clojure code, but have this view that they can't be used in other Lisps/Schemes.
(You will also have to use `let*` in (most?) schemes because the binding for y has absolutely nothing to do with the binding for x and so cannot be used in the binding of y.)
>I don't get why you use other delimiters for your Clojure code
Do other delimiters mean the same thing as in Clojure tho ? I only know Clojure - in Clojure [] - vector- is a different data structure from () - linked list - which is different from {} - hash map. Is this similar to Racket or is it all just lists in Racket ?