Of all the Lisps I've toyed with (mostly Clojure and Racket) I think I enjoy Racket the most. I wish more languages (I know some already do: Python, Processing, and others) would at least include a minimal text editor that can build and debug code - coded in the same language. Matter of fact, I've wished this were the case for Rust (and maybe D? - I guess there's a minimalist emacs for D but that's not as approachable as say Dr. Racket for newcomers), it would give them a chance to build a bare bones UI stack for Rust that is officially maintained.
On the other hand, my experience with Racket has been fantastic, I have not done too many significant projects, but when I toy around with it, it doesn't get in my way. I just don't have a good project for it as of yet. If I want to do web I'm already accustomed to using other web stacks so I don't see the appeal there, one thing that always surprises me is the GUI stack for Racket though, it just feels straight forward. It feels like we still haven't figured out the whole GUI thing, Electron is so popular because you can get a GUI done fairly quickly since everyone understands the front-end code so well out of the box.
I was also fairly impressed by Clojure. You install the package manager (Lein) and you have all you need to do any Clojure work, iirc it will go as far as installing Clojure for you. The repl approach to GUI design with Clojure was also quite interesting for me. I think Clojure and Kotlin are the only two things about the JVM that impress me these days, but that's just my opinion.
> you will end up needing something that is only available for the most popular 5-6 languages
The thing that is the Special Sauce for Racket is it's macro system. You can build your own language for specific things easily or you can extend Racket with a library also much easier then the other 5-6 languages.
I also think the documentation is all in one place. The library Scribble makes it simple for everyone to document your macro/library simply and uniformly. I really have high hopes for Racket over the next 5 years.
I tried to use Scheme years ago, and I found that no matter how good a language is, writing something to interface with some ugly API or something like that, or debugging an existing one that hasn't been used thoroughly, is a lot of work. Not sure where Racket itself stands these days, since the last time I used it it was called PLT Scheme.
> The thing that is the Special Sauce for Racket is it's macro system. You can build your own language for specific things easily or you can extend Racket with a library also much easier then the other 5-6 languages.
How are macros going to give me a better solution that the one which exists, is tested and have been used by others for some time? Besides, macros are a meme. What difference are macros going to make when wrapping a api? Can you show me an existing lisp/clojure wrapper which is more expressive than python/ruby?
The example you give doesn't have boilerplate so macro can't do more.
Macro can help for two things:
- reduce boilerplate
- add new function to your language (often specific and limited in context of use [racket's macro a suposedly composable]). Example: racket match, clojure.async.
I know what macros are and what macros can do. The parent poster made a comment that somehow macros can help overcome non-existence of wrappers in Racket. We both agree that macros won't help in this case, and my personal opinion is macros are a meme. They help some in very limited circumstances yet they are touted as a productivity multiplier. A pattern match over if-else doesn't really buy much. It's nicer, sure, but not by much.
The specific problem of wrapper around HTTP API have been resolved with WSDL (https://www.w3.org/TR/wsdl) assumming the use of WSDL the only thing a macro could do is equivalent of what an external program that generate a python file implementing the WSDL could do. I have written a php parser with the racket LLAR macro and it doesn't add more than an external tool like bison.
Reducing boilerplater could make your code less buggy (bugs you catch with your eyes) and could make the meaning of the code more clear.
Racket match is realy nice but it will shine if:
- You use a lot of immutable datasctructures.
- Explore shallow tree like data structures.
> and my personal opinion is macros are a meme
As far i has understand macro is already in use as Annotations for java.
In php, programmers developped complex frameworks that generate code (Symfony for instance) before running the user's code even if it isn't a macro per-se it share the same goal.
And i could have mention c++ template, so i don't think macro are a meme they already exists and there is a demand for it.
> assumming the use of WSDL the only thing a macro could do is equivalent of what an external program that generate a python file implementing the WSDL could do.
I am not assuming the use of WSDL and macros still don't do much.
> Reducing boilerplate could make your code less buggy (bugs you catch with your eyes) and could make the meaning of the code more clear.
Macros aren't required for reducing boilerplate and don't necessarily reduce boilerplate compared to a non-macro solution in an expressive language.
I read almost all of racket's documentation cover to cover and learnt Clojure about 5 years ago. There are a lot of good things to say about them but as far as expressiveness go, but I didn't found them anymore expressive than Ruby or Python.
> Racket match is realy nice but it will shine if:
> - You use a lot of immutable datasctructures.
> - Explore shallow tree like data structures.
The things you pointed out are non-macro things. I like match, especially when it's well integrated in the lang. viz f#. I just don't like the difference that being able to cook up your match using macros makes a huge difference when it comes to programming productivity.
> i don't think macro are a meme
You misunderstand my point. Code generation with or without macros is useful. That's not a meme. "Macros are a secret sauce" is a meme.
> Macros aren't required for reducing boilerplate and don't necessarily reduce boilerplate compared to a non-macro solution in an expressive language.
So i suspect you are thinking of ruby metaprogramming, in that case you have good and bad. With macro you can expand your code and have static tool reason about your code (IDE à la Éclipse). In the other hand in metra prog. you have all the info availlable at runtime and it is more easy to implement.
> I just don't like the difference that being able to cook up your match using macros makes a huge difference when it comes to programming productivity.
> It is probably an overstatement, if they have been useless for you (and me) doesn't mean they are.
You are conflating "useless" with "secret sauce". I didn't claim they are useless. I said macros are a meme and are useful in very limited circumstances.
I have developed a very nice Lisp dialect from the ground up, in which macros do all these things:
* completely implement the system of "syntactic places": the ability to mutate variables, mutable slots of various kinds on various objects, and user-defined such things. The only API underneath consist of ad hoc functions to update specific kinds of places.
* implement the syntax of the object system: structure defining via defstruct, instantiating objects with new and so on: over top of an API consisting of functions to manipulate the object system.
* various control structures.
* the op macro for currying / partial application.
* the FFI language for defining foreign types, and its operators like typedef, sizeof and offsetof.
* the awk macro: a fully-loaded, "Lispified" version of the Awk language.
* generator-like programming interface (featuring yield with bi-directional communication of values) implemented over top of delimited continuation primitives.
Many more. Macros provide a catalyst for language research. New syntax can be added to existing syntax without any conflict, and without having to muck around with a parser. The new syntax doesn't even have to be loaded into memory if it's not being used.
"Macros don't do much; I don't need need to write macros" ignores all the macros that have been already provided and the benefit they bring. You can't be using existing macros left and right while claiming that they are not all that necessary.
You may feel that way when using a language that has no macros. But the syntax of such a language is effectively a macro expander. A Yacc rule (or what have you) which matches some symbols on the left and produces a piece of AST in its action body is effectively a macro. Someone else wrote that syntax and you benefit from it, just like you benefit from existing macros in a Lisp. But that syntax hinders development of that language; it is ultimately detrimental to that language. Because new versions of the language struggle with the integration of new syntax, they create backward-compatibility wrinkles.
With macros, if I have some piece of code that uses syntax available only in the latest and greatest version of the language (not what I'm using in production), I may be able to just write the macro to simulate the feature well enough to get the code working. Code relying on hard-coded new syntax has to be rewritten not to exhibit a syntax error with the older language.
The ability to define macros can really help work around bugs in existing macros. If hard-coded syntax is broken, all you can do is code around it with different syntax. If a macro is broken, you can write a macro just like it (only with a different name) or perhaps even redefine it. The code doesn't have to change at all. Eventually when upstream fixes the bug, the workaround is removed and that is that.
Since macros are ordinary identifiers, they can be namespaced. Just because you introduce a new control construct called wonk doesn't mean that wonk is now a reserved token in a syntax, which breaks everyone who used wonk as a variable name. Syntax-in-a-package (rather than in a global parser) is awesome!
If Python had macros, Python 2 to 3 migration would be a non-issue. It wouldn't be a topic of discussion that non-Python-programmers know about.
> Someone else wrote that syntax and you benefit from it, just like you benefit from existing macros in a Lisp.
Are you following the discussion? The whole discussion arose from somehow macros make up for non-existence of libraries in Racket. Someone else wrote all those libraries for popular languages and I benefit from those existing libraries. Macros do fuck all if I have to wrap them myself. And even if I have to, most of the times it will be way simpler to wrap it in Python/Ruby.
You wrote a novella on your hypothetical macro use cases. I wrote I know what macros are. I don't know why you are throwing that at me.
> If Python had macros, Python 2 to 3 migration would be a non-issue. It wouldn't be a topic of discussion that non-Python-programmers know about.
This is what I mean when I say macros are a meme.
No, it won't have helped, at all. The changes in python 3 break the existing python 2 code.
> For example, this no longer works: k = d.keys(); k.sort(). Use k = sorted(d) instead (this works in Python 2.5 too and is just as efficient).
> The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering
> builtin.sorted() and list.sort() no longer accept the cmp argument providing a comparison function.
> The biggest difference with the 2.x situation is that any attempt to mix text and data in Python 3.0 raises TypeError, whereas if you were to mix Unicode and 8-bit strings in Python 2.x, it would work if the 8-bit string happened to contain only 7-bit (ASCII) bytes, but you would get UnicodeDecodeError if it contained non-ASCII values.
> No, it won't have helped, at all. The changes in python 3 break the existing python 2 code.
In a Lisp setting, the 2 code could be supported in an environment where it is not broken, in the same image in which 2 code is running. It could be redirected to use library symbols from a 2 package. E.g. if the hypothetical floop syntax changed there could be a ver2:floop and ver3:floop.
If necessary, the entire 2 implementation could be separately provided via this backward compatibility mechanism. Yet, 2 and 3 code could be freely mixed even in the same function. E.g. an instance of ver2:floop could nest inside ver3:floop.
> if the hypothetical floop syntax changed there could be a ver2:floop and ver3:floop.
dict.keys() returned a list earlier, now it returns a "view". dict already had keys() and iterkeys(). Is that what you were referring to by your ver2:floop and ver3:floop? They changed keys() to act essentially like iterkeys() and removed iterkeys() because per them, this is the correct behavior.
Most changes in python 3 won't be helped by macros. Macros would have helped if they were adding say pattern match. But even then, it doesn't really matter much. If python itself is adding pattern match, they can write it in C, or python, or write a macro(if python had it) - it would have been all the same to me.
I am not saying macros aren't useful. I am saying macros are useful in limited circumstances and existence of macros won't have done anything for python 2 to 3 migration.
You are just deflecting now. You made the claim that somehow macros would have made the python 2 to 3 migration easy. You are yet to demonstrate which of the migration issues would have been solved by macros.
dict.keys() returning something different from what it used to isn't a syntactic change; it's a change in function behavior. Since macros handle syntax, they aren't applicable to a function semantics change.
What we might do here is to use two different keys symbols in different packages. We can have a ver2:keys and ver3:keys and control which of these dict.keys() uses in some scope. But that's not macros.
The point is that with macros, we can do the same thing with the syntax of the language; it's a library feature that we can subject to versioning. Old syntax can be supported side by side with new syntax. So then since we have a way to have old syntax and old API semantics, which is pretty much everything, we can have a nice migration path.
> dict.keys() returning something different from what it used to isn't a syntactic change; it's a change in function behavior. Since macros handle syntax, they aren't applicable to a function semantics change.
Now you are telling me something I told you in the first place.
> What we might do here is to use two different keys symbols in different packages. We can have a ver2:keys and ver3:keys and control which of these dict.keys() uses in some scope. But that's not macros.
Right. So like I said, macros won't have helped, at all.
> Old syntax can be supported side by side with new syntax.
Creating a Frankenstein's monster was never the goal. And besides, they already had tools for code which can run both on 2 and 3.
I don't think the point was necessarily that you can always do better with lisp (with or without macros). A best case solution, regardless of language, can't be improved by definition.
The point is that you can adapt lisp to an equivalent best case solution. And if you like to program with lisp, that's a win. If you don't like lisp, then it doesn't matter.
> has a chance of being the Python of functional(ish) languages
I love lisps, but I don't think racket comes anywhere near the accessibility level of python. I'm not convinced a functional language (in the style that current functional languages take) can in general. Imperative python is extremely easy to grok.
John Carmack on his 10 year old son's first program.
> I’m still taking a little heat from my wife for using an obscure language instead of something mainstream that is broadly used in industry, but I have nothing but good things to say about using Racket and DrRacket for a beginning programmer, and highly recommend it. https://groups.google.com/forum/#!topic/racket-users/yjRuIxy...
I would say that typing your Python code is easier, but the rest is much easier in Racket.
1) easier to debug
2) easier to deploy
3) easier to design
4) easier to think through due to the concise manner of building programs
I have plenty of friends who use Python and they can write a 100 line program without a problem. After it is over 1000 it just falls apart. In a functional(ish) language it allows for a MUCH easier way to follow Do Not Repeat Yourself.
Well you can deploy the executable file to a server if it has the Racket runtime just like Python, Ruby etc. But there is a tool called `raco distribute` that will bundle the executable and the runtime into a folder that you can then distribute to anyone.
Well if my experience with py2exe is anything to go by raco distribute actually works 100% of the time so that's a pretty enormous improvement. Though I must admit my experience with py2exe is not particularly extensive.
It's a mixture of: standard library (see how quickly Go was adopted, especially when making a web project was an out of the box experience), documentation, and tooling is definitely crucial.
If I can download a language and have all these things out of the box (which Racket provides) then I probably will have less friction than someone programming in C or C++ (with 0 experience in either those or Racket mind you) who have to figure out what compiler to get, what editor / IDE to use, how to configure their IDE / editor, what magic terminal incantations to do all while I'm building websites and GUI's on Racket in a matter of minutes (from examples of course, but now I can play with those). All because Racket has: documentation, tooling and a good out of the box stack.
A language with large standard library and tooling is awesome. But Racket still falls short on api wrappers for tools(message queues, zero mq, templates...) and services(payment gateways, google cloud or azure apis...). It's a chicken and egg problem. Unless a significant number of people start using it in production, Racket isn't going to have extensive libraries and unless it has the libraries to hit the ground running, a significant number of people won't try it.
Why would you need a text editor to come with the language when you could have Vim and the rest of the command line. The problem newcomers have with programming is that educators think they're too stupid to use the command line and in the process they shield them from important details about the build process by obfuscating them under the veil of an IDE.
It depends on the language and intent. With Python it has a simple GUI shell that lets you edit, run, and use the REPL (similar to Dr Racket). It's easy to use and doesn't actually shield you because there isn't any complicated build process anyway. If anything it shields you from:
Really glad to see this book. I have shipped webapps in racket two or three times (once in typed/racket, because I was feeling especially crazy). It really was the most fun I had programming in a long time. But some of the problems I was tackling I felt like I was treading new ground - it wasn't clear if a ProxyPass to nginx was the best thing or not, it wasn't clear if this was the correct way to implement sessions or not, et cetera. I'm glad to see an authoritative book for the racket community on these topics.
To take lisp based web development to another level, what if we had a "browser" environment that embedded racket and executed sandboxed code instead of JavaScript/html? (Goes back to dreaming)
We had a taste of them in the past, Xerox PARC created Ethernet and their workstations (Interlisp-D, Smalltalk, Mesa/Cedar) offered some support for interactive objects across network.
Which is why Alan Kay is not a big fan of the Web as such,
"The Internet was done so well that most people think of it as a natural resource like the Pacific Ocean, rather than something that was man-made. When was the last time a technology with a scale like that was so error-free? The Web, in comparison, is a joke. The Web was done by amateurs."
Racket is interesting, but what turns me off about the language is that they decided they needed OO for some things and they... implemented a single dispatch based system. Why would you limit yourself this way if you don't need to? Single dispatch systems force you into all kinds of "power deficiency patterns" (e.g. all double-dispatch patterns) that just wouldn't be necassary if you do multiple dispatch a la CLOS. You don't have to re-implement all of CLOS if you don't want but at least use something like generic functions instead of the inferior (and ugly in Racket) single dispatch style.
The web server doesn't really use the object-oriented features. OO is mostly used in the Racket standard library for the GUI, where it models existing single-inheritance GUI libraries.
> Racket is interesting, but what turns me off about the language is that they decided they needed OO for some things and they... implemented a single dispatch based system.
yeah, frustratingly they have a great core language and then tack on optional OO, generics or static typing systems that are about 80%-90% baked. then those systems see just enough use they can't be ignored, but not so much that someone steps up to finish the last bit of baking.
It has a niche audience. I'd be surprised if it sold 1,000 copies at any price. But if I were interested in the subject, $50 is not a lot of money if I thought it would get me on the ground running. I paid for Discover Meteor, for example.
Meh, how about the variance in purchasing power and cost of living among all the places that use just one currency? You'll find differences even greater than $8.
Prices are arbitrary. Locking USD = EUR makes you superficially feel like you're getting ripped off but it's still arbitrary. You're also paying the same as someone making $100k/year more or less than you.
On the other hand, my experience with Racket has been fantastic, I have not done too many significant projects, but when I toy around with it, it doesn't get in my way. I just don't have a good project for it as of yet. If I want to do web I'm already accustomed to using other web stacks so I don't see the appeal there, one thing that always surprises me is the GUI stack for Racket though, it just feels straight forward. It feels like we still haven't figured out the whole GUI thing, Electron is so popular because you can get a GUI done fairly quickly since everyone understands the front-end code so well out of the box.
I was also fairly impressed by Clojure. You install the package manager (Lein) and you have all you need to do any Clojure work, iirc it will go as far as installing Clojure for you. The repl approach to GUI design with Clojure was also quite interesting for me. I think Clojure and Kotlin are the only two things about the JVM that impress me these days, but that's just my opinion.