Why Racket? Why Lisp?
beautifulracket.com
beautifulracket.com
https://docs.racket-lang.org/quick/
Just being able to put an image in a comment explaining your algorithm into your code would be huge improvement over the traditional syntax colored ascii you get with most languages and editors. There are many times I've written an algorithm which is difficult to understand without the associated diagram I drew on the whiteboard or in an image editor. Racket lets you insert that image or photo directly into your source, and I think this is a significant improvement over putting a link to that image in a comment.
Racket also goes a step beyond that by letting images be values which can be assigned to variables or returned from functions. The link above shows this clearly. I'm sure there is some value in this as a teaching aid, and I think that's why they did it, but you can also return mathematical plots from your functions and so on. This feature is similar to the various interactive notebooks people use for Mathematica or Python, so it's not really specific to Racket, but it is interesting to play with.
Obviously there are downsides to putting images in your source. After you do that, your code is no longer ascii, and it won't be something you can edit with vi, emacs, or any non-Racket IDE. Also I doubt it will play nicely with git any time soon. However, it's a neat feature of Racket whereas many of the other benefits in the article apply to any Scheme (Chez, Gambit, Chicken, Guile, etc...) or lisp.
I wish there was some reasonable standard (like a better version of Rich Text) that was commonly adopted so other languages could put graphical pictures in the source code.
I have felt exactly the same for many years. It would need to be something that was totally open (to achieve wide adoption), and reasonably easy to support in IDE's for edit and preview. And git-friendly. Belly-flopping on an existing standard is probably the easiest way to make that happen.
One thought is to presume a block comment with a language-specific marker, and make the contents a restricted subset of Postscript. a) You get one or two open-source fonts. Deal with it. b) The rendering area is strictly limited, c) the operator subset is limited to something reasonable -- like just enough to do a monochrome version of 80% of the kind of graphics that PowerPoint-ish programs give you.
Of course, you would never want to write Postscript by hand (although it isn't hard) but an IDE should be able to support a graphical editor plug-in. Or in a pinch you could even use another tool that left the rest of the code alone, and just edited the graphical block comments.
Vector graphics would be adequate and could discourage huge binary dumps in the code, but you know someone would try to jam a photograph in there by inserting a square per pixel, and I can't really blame them. Postscript could work, but if you picked something explicitly line oriented it would cause less confusion in revision control.
Minimal Viable Picture :)
> Postscript could work, but if you picked something explicitly line oriented it would cause less confusion in revision control.
Agreed. But Postscript has a lot of existing unencumbered infrastructure code littering the net. With a new syntax, you need to overcome an activation energy problem. You would have to make sure that rendering and editing code existed that could be munged into a plug-in for everybody's favorite IDE. EMACS mode, anyone?
Also, maybe an independent tool that ran in a local web browser (not uploading code to random servers) would be a way to jump start things.
/* <img source="images/bubble_sort.png"/> */
If you have the plugin installed, the image is displayed immediately after that line.
Developed in 1982. Present on almost every UNIX-like system and integrated into the manpage generator.
Probably the main reason we've not seen things like this achieve wide adoption is the small but very influential subset of programmers who refuse to use anything that isn't a pure text terminal for development.
A terminal with graphics in it would be nice too. Maybe if Tek4014 (and the Tek emulation in xterm) had graphics and useful text simultaneously it would've been more popular than the modal approach. I've also heard of Sixel, but never seen it live.
BTW, Mermaid and such might be more suitable for embedding diagrams in comments―maybe even just one of the ascii art diagram languages (for which there are utils to convert to graphics).
i do this all the time.
Many FOSS devs don't have a full picture of Lisps, by constraining themselves to what Emacs+SLIME are able to, without experimenting commercial Common Lisp environments.
the main purpose of the Code comment area markup method is to live Preview directly in the Code Editor Preview panel without exporting or any preprocessing.
Just add a line comment character of the programming language before each line of Markdown.
In the comments of code, you can draw flowcharts, tasklist, display data visualizations, etc.
The method is to add extension instructions in any programming language comment area:
markdown manual eval code, live eval code, print result, display data visualization and other directives When previewing or converting a format, you only need to simply preprocess: delete line comment characters with regular expressions, example: sed 's/^;//' x.clj
Note:
line comment character of Clojure(Lisp) is ; line comment characters of the current file type can be obtained from the editor's API. when we edit the code, we can preview the effect in real time. Editing literary code has a live preview panel like most markdown editors.
[Markdown Literary programming that don't break the syntax of any programming language](https://github.com/linpengcheng/PurefunctionPipelineDataflow...)
Emacs handles images.
Also, what made you choose Haskell for your project? Can you share some of the reasoning?
Racket is much better to get something done and working quickly. Same comment for Common Lisp.
Haskell has great support for strongly types web services (servant) and lots of great libraries. Racket has a very rich ecosystem of libraries, custom languages (like Typed Racket). Both are great.
EDIT: It takes me longer to get to working code in Haskell but once written the code has higher value to me because it is so much faster/easier to refactor, change APIs, reuse in other projects, etc. I just did a major refactoring/code-tidying this morning, and it was very simple to do.
CL has mutable data structures(lists are mutable by default) and setf etc. Scheme/Clojure makes a much pleasant functional programming without side effects experience.
https://docs.racket-lang.org/reference/pairs.html?q=list?#%2...
Immutable cons cells eliminates all of this. If a cons cell is created with a list cdr, it will always be a list. If a cons cell is created with anything but a list as the cdr, it will never be a list. Very straight forward. You don't have to worry about linear time or worse propagations, and you don't need to anticipate what some other programmer down the line will consider "normal usage".
Compare this to a language like Ocaml, where I have worked at the exact same REPL, modifying the same environment, for months at a time.
This was such a standard thing to do in the Lisp and ML worlds that these languages traditionally include a save-lisp-and-die function which saves your entire runtime to disk so it can be reloaded later. (We used DMTCP in Ocaml for the same effect).
Not to moan too much. Haskell is still my favourite language. I just wish it had a decent REPL.
This paragraph seems like it would be equally true for almost any subject you filled in the blanks with.
As someone who had to learn a foreign (natural) language in school, I can see the benefit now, but there's no way I could explain it, and certainly not in an hour. It's a type of learning which causes a change in how you organize things you already know. How do you sell that?
(No, I don't believe "so you can talk to people in that language" is a realistic benefit. I don't think even my school thought that. The selection of languages offered is simply not useful. I've never met anyone this side of Stuttgart with which to use my German. Of the top 10 non-English languages spoken in my state, only 1 was offered as a class at my school. It almost looked like they went out of their way to find teachers in less common languages.)
(BTW, that's also the same answer as "If Lisp is so great why isn't anyone using it?" It works for any subject. If trig is so great, why aren't you using it? If music is so great, why did you stop playing after you graduated, and were no longer required?)
I'm not trying to downplay the importance. It's a real problem, for many fields. As a Lisp programmer, it's my nature to try to sell everyone on learning Lisp even if they won't use it, and also to over-generalize problems to nearly the point of absurdity.
How do you get someone to want to learn something when it may have no immediate and apparent practical value to them? Especially today when their whole "learning" slice is competing with Netflix and Facebook and all the rest. I guess the trendy answer right now is something in the neighborhood of "freemium gamification" and for reasons I can't explain that makes me sad.
That's potentially a good pitch all by itself.
> Of the top 10 non-English languages spoken in my state, only 1 was offered as a class at my school. It almost looked like they went out of their way to find teachers in less common languages.
This is a great example of language education being frozen in time for essentially cultural reasons. Pre-20th century, and probably up to about WW2, the common choices of foreign languages to study were determined on cultural grounds and largely for ""elite"" purposes. You'd learn German so you could read Goethe and Schiller, or the various scientific papers published there.
Wind forwards to the present day and the obvious choices for US language learners would have Spanish at the top of the list, but that would involve the complex politics of the relationship between the US, the rest of Latin America, and its immigrants. Much easier to carry on pretending that someone might want to read Goethe.
You have a macro system that isn't some lameass additional language with severe limitations like the C preprocessor or C++ templates. You have all the language available both at compile time and at run time. You can even use functions you already have (and tested) in both places.
This allows you to leave every single assumption you make during programming in one place. You don't have to splatter uncertainty about what the program is supposed to do into multiple places because you language isn't expressive enough, e.g. you cannot just redefine control structures to express an assumption. That is what leads to "changeable software", not just "readable software".
My writings on the subject: https://medium.com/@MartinCracauer/a-gentle-introduction-to-...
https://medium.com/@MartinCracauer/a-gentle-introduction-to-...
Example - using scientific units attached to literals in source code, but keep them at compile time and don't slow down runtime with unit checking: https://medium.com/@MartinCracauer/a-gentle-introduction-to-...
And speaking about early or late (static/dynamic) type checking. If you have compile-time computing you don't have to choose. How silly would it be to make a programming language that can only do one or the other. https://medium.com/@MartinCracauer/static-type-checking-in-t...
Finally, there is turnaround time during development: https://hackernoon.com/software-development-at-1-hz-5530bb58...
When do people say to themselves "screw this, I need a more flexible tool like Racket"? Is it when you get super deep in the macro magic? (I'm not reallt sure how the Clojure macro system compares to the Scheme one)
As far as macros go, I greatly prefer racket's syntax-parse to anything else I've tried.
Also personally something I wish more functional languages would have is a little bit of Racket's maximalism with its forms like: (for/list ([e (range 10)]) e) [1] and for/fold, including the nested ones and the like that make mapping over things and even filtering a dream!
[1] https://docs.racket-lang.org/reference/for.html#%28form._%28...
The code it outputs is almost always as fast as a hand-rolled named-let (just as with racket), and you can port it without much difficulty to other schemes. I support most of the sequence iterators (in-range, in-list etc) and support non-tco loops to create things like lazy streams.
For example, the seq abstraction and the fact that most sequences and functions are lazy by default is really nice. It also makes more use of polymorphism, so you can e.g. call map on a hash-map, a vector or a lazy seq. Also the fact that maps and keywords act like functions is extremely convenient. Similarly, let is actually let* and binding forms allow destructuring. Racket has all this, but you have to remember to use e.g. match.
Racket macros are a work of art and I'm only just exploring them. However, the surface area is very large. In Clojure once you know the language and some of the standard library you can write macros. In Racket it seems there's a whole other language you have to learn. It's clear though that they're extremely powerful, so I probably just need to invest more time in it.
All in all my ideal language would be Racket with some of the conveniences and choices of Clojure. Gerbil is another lisp that looks interesting; maybe I'd steal some stuff from there too. Of course, Racket is extremely well suited to building languages, so I could actually build this ideal language if I wanted (and had the time and skill required).
Clojure's performance is of course better, though.
[1] https://en.wikipedia.org/wiki/Language-oriented_programming
[2] https://github.com/euhmeuh/wasm-adventure/blob/master/src/wa...
So even if one language's power is enough for someone's programming ambitions, they might still want to go for an environment with more like-minded people that are more supportive of using (and in the perspective of some, abusing) that power.
Also, trying to figure out how to build (non-web) GUIs with Clojure and Swing wasn't a pleasant experience for me.
But Racket can be overly verbose sometimes.
I like that the author addresses the “what’s in it for me” head on as well. Makes it a bit more clear what some of the immediate benefits are.
For anyone who enjoys programming language dives, I recommend Racket fully. It's simple and powerful in various ways.
x + (if is_true(): 1 else: 2)
I think he just got he syntax wrong, it's supposed to be: x + (1 if is_true() else 2)
And basically can't follow the rest of the argument. I have yet to learn a Lisp. Honestly, what am I missing?To add a little more detail to a spare but correct (I think) comment:
Outside of Beautiful Racket, some other helpful reading I've found in the past that covers macros:
> Creating Languages in Racket (Matt Flatt, 2011, ACM Queue) [0]
The details here are tantalizing, but there's a lot that goes unsaid. Code is available for download and review. As a longer-form example of something fun to do, it's good, and I've enjoyed it.
> Automata using Macros [pdf] (Shriram Krishnamurthy, date unk., Educational Pearl) [1]
This is a worthwhile read at only 14 pages. Krishnamurthy writes with clarity, iterating through several solutions to writing a finite state automaton.
[0]: https://queue.acm.org/detail.cfm?id=2068896
[1]: http://cs.brown.edu/~sk/Publications/Papers/Published/sk-aut...
Before that, I thought of the macro system to be like the #define preprocessor in C, nothing more.
Thank you very much, for actually expanding it with great links!!
I recently asked how to write a tree shaker in #sbcl because I thought it’d be cool. All I got was a “why would you do that?” and “ok fine your time to waste” and no substantial answers. The Common Lisp community is small and curmudgeonly. Who needs this?
I should give racket a second shot though. I love Chez.
https://cjelupton.wordpress.com/2014/08/14/quantum-computing...
Also with Typescript being adopted by most major JS projects, I wouldn't say that dynamic typing "won."
See for example:
https://github.com/roswell/roswell/blob/master/lisp/dump-sbc...
> Common Lisp community
#sbcl is not THE Common Lisp community. Best not to generalize from an IRC channel to a very diverse group of people using a dozen different implementations.
Yeah this is all very serious business. Also, one of the most curmudgeonly responses you could have given.
> #sbcl is not THE Common Lisp community
This is not my sample size of one opinion. I’m just throwing one in the pot for the very widely held opinion of the Common Lisp community being curmudgeonly.
It's work and SBCL is maintained mostly by volunteers, who may have their own agenda. Sometimes there is funding from commercial projects. So far maintaining a treeshaker wasn't high on the agenda, even though the project runs for some years now.
If you shell out serious money for your 'very serious business' the commercial implementations Allegro CL and LispWorks provide maintained tree shakers and all kinds of fancy application delivery features.
> throwing one in the pot
not very motivating...
You might check out the link I've gave you above, instead.
(let ((fs '(+ - *)))
(mapcar (lambda (f)
(funcall f 1 2))
fs))
How do we know that the functions in FS can't be removed? They are just symbols in a list in the code.http://www.lispworks.com/documentation/lw71/DV/html/delivery...
I don't recall any curmudgeon behavior in-person, but a bit "critical" is often a useful role for an engineer to play, if they can back it up and discuss. A useful mode of engineering discussion involves people making assertions, thinking aloud, and being challenged, and together you improve the ideas and generate new ideas. Sometimes it's appropriate to suddenly look at each other and start jumping up and down and shouting, like you're in a movie, because you've just hit on a solution that has passed your preliminary tests of critical thinking. If you're jumping up and down all the time, I suppose that could turn into incestuous amplification.
The Scheme and Racket communities are also good. I've spent the most time in Racket, and have a few ideas about why the community is good:
* The original professor (Matthias Felleisen) and grad students were solid PL people who were interested in making CS education more accessible, which seems like a pursuit that would value nurturing and accessibility.[1] When some of the grad students also became professors working with Racket, they kept up accessibility, such as in the main forum (`racket-users` email list / Google Group). (`racket-users` seems to implicitly coordinate, with community members, including the professors, responding to most any question.)
* This will sound a bit cynical or funny, but I've seen it change other language communities before: one thing that helps the community be good is that there's no money in it. (Once there's money happening, you'll get more of less-desirable behavior from some individuals and groups: promotion of personal brands, posturing and jockeying for the opportunities, SEO games and huge amounts of Web search hit noise from that, marketing puffery rather than engineering straight-talk, non-sharing, sometimes commercial landgrab games with the platform itself, sunny-sociopath workplace cultures, etc. Not that a community can't be great even when there's money involved, but "really, there's no money in this -- it's only for the merits and community" seems to scare away a lot of behavior, and the people who are attracted anyway set a tone.)[2]
* Racket is one of those tools that many hackers really like to use, and people generally have good morale when using it.
[1] You also saw this with the SICP professors, who are some of the best-regarded.
[2] Not that I haven't tried to promote commercial use of Racket, despite fear of spoiling a good thing. One of my attempts, I tried to do it while shaking up some usual expectations/modes: https://www.neilvandyke.org/racket-money/
I've use macro systems quite often in more or less complicated ways: as a professional assembly language programmer, in school when studying Lisp DSLs, when using my favorite editor Emacs and its elisp, in systems I've built similar to Moores TRAC programming language, M4, my extensive use of TeX and LaTeX for decades, C++ STL, sendmail configurations, etc.
Over the years, I've lost my enthusiasm for powerful meta-programming facilities like Lisp macros. The underlying languages are Turing complete and don't strictly need meta-programming, and most modern languages aren't lacking in abstraction mechanisms available to programming without meta-linguistic alterations.
Like operator overloading, sophisticated macro systems change the semantics of program source code in ways that are not obvious. They allow new variants of the programming language to be created willy nilly placing demands on me the reader, maintainer, or user of a programming language package to fully understand the implementation of the meta-linguistic features. Powerful macro systems encourage a thick frosting of magic to be applied on the implementation of complex systems.
Some systems, like Lisp or Scheme or TeX, would be difficult to use without macro extensions, but it seems to me that identifying a good set of built-in abstractions for writing programs and building the language around them is a better approach. I am so grateful for the TicZ graphics package for LaTeX, it's all built out of TeX's crazy flexible macro system, but I'm even more grateful that I've never had to touch the source for it. Take a peek at: [1].
For example, without a powerful macro system, something like the nanopass framework [1] would not have been possible.
Sure, you could write an external code generator, but at that point you've just implemented a bad macro system.
The only language that kind of breaks away from this pattern of necessary imediate empowerment was CoffeeScript. It just exactly mirrors my way of thinking and was just an inch away from pseudo code I used for my notes since primary school. But then ES6 came and gave me enough CoffeeScript to almost be fine without it. Final nail was TypeScript that gave me stuff I wanted, smart, fast code completion and typechecking for places where I wanted types. Now if I could just have an editor that could display curly braces as indented blocks (python and coffee style) I'd be perfectly happy with state of browser coding.
I tried Go, Elm, Haskel, Scala but nothing stuck or even went beyond simple programs. Nim was interesting because allowed you to run code at compile time to transform code (like Racket macros). I might use it for console programs that need speed (although I'll probably just dust off C++).
Rust so far has the biggest potential because it allows you to have code running concurently without crazy bugs by forcing you to specifically track who owns what and for how long. That might be useful for me to make programs faster at some point since multicore is now firmly a thing.
I always wanted to use Racket in a bigger project to have a deeper understanding of macro/language creating. I always believe to achieve real 'domain driven design' is to create a layer of real business language which could interpret to a software system.
However, every time I want to do this I found Clojure is actually a much better choice. I guess to be fully practical is not #1 priority for Racket right now. But I really hope Racket can improve some of the following:
1. Encourage efficient data structures by default. I know lists are the soul of lisp but it's not good to use lists for everything. Clojure by default let you use highly optimized persistent data structures -- namely vectors and hash maps. These two data structures are highly practical, performant in most of the cases.
On the other hand, lists are more like write-heavy data structure, with really bad reading performance. This is like, a plain file system writes faster than databases, but most of the websites use a database because most of the business has much more reads than writes.
2. ClojureScript. JavaScript is a big thing until WASM fully arrives. Clojure has several really solid ClojureScript workflow, which makes me feel ClojureScript is really a first-class citizen.
3. IDE and debugging. I use Emacs + Geiser for editing, but Drracket for debugging. Drracket is really good, but still not great for editing hundreds of files. For Clojure, Cider and Cursive are IDEs makes me feel solid and complete.
4. Frameworks. I guess if the other 3 points are really good there would be many good frameworks come out every day.
> 1. Encourage efficient data structures by default. I know lists are the soul of lisp but it's not good to use lists for everything. Clojure by default let you use highly optimized persistent data structures -- namely vectors and hash maps. These two data structures are highly practical, performant in most of the cases.
Scheme has vectors, and Racket adds hash tables and structs:
https://docs.racket-lang.org/guide/vectors.html https://docs.racket-lang.org/guide/hash-tables.html https://docs.racket-lang.org/guide/define-struct.html
There's also some work on matrices and arrays (beyond Scheme vectors): https://docs.racket-lang.org/math/index.html
There are some older libraries where lists (or alists) are used, when today you'd probably use hashes or structs. We could consider this an educational opportunity: there are still times when knowing how to do old-school list-processing is exactly what you need, and it's pretty fundamental data structures (e.g., singly-linked lists, trees), so we could consider it practice. :)
BTW, one difference between modern Racket lists and Scheme's is that Racket's default pairs are immutable. This turns out to be useful for optimizations, as well as encourage a healthy amount of functional programming.
Regarding #2, good point. I raised the WASM issue a couple years ago, and my thinking then (and now) is to build it for the forthcoming Chez backend, while getting plugged into the WASM standards work in the meantime. There are various ways to do JS with Racket (a big HTML5 Offline app of mine does it by generating JS and HTML from Racket), but WASM seems most promising.
Regarding #3, if Geiser works for you, great. You might also take a look at Greg Hendershott's racket-mode for Emacs: https://github.com/greghendershott/racket-mode
I appreciate that DrRacket's student-emphasizing IDE is very different than most IDEs, and it's missing some things I'd like, for editing many modules at once. If you're up to adding some features you'd like, there's an extension mechanism, and you can also do git pull requests to the DrRacket source itself. https://docs.racket-lang.org/drracket/extending-drracket.htm... https://docs.racket-lang.org/framework/index.html
Regarding #4, there are Web frameworks, and the main Racket Web Server (which you don't have to use; you can also do things like SCGI or proxy another HTTP server implementation), and you can also whip up your own frameworks very rapidly in Racket unlike many languages. I'm hoping a couple startups use Racket to get to launch, and release the light frameworks that they make along the way.
Regarding reader extensions, Racket has those, as well as a ton of great syntax extension mechanisms: https://docs.racket-lang.org/guide/hash-reader.html
Racket has an AMAZING debug instrumentation & tracing library, which, unfortunately, most people don't know about:
First, there's Medic:
Source: https://github.com/lixiangqi/medic
Docs: https://docs.racket-lang.org/medic/index.html
Demos: https://www.youtube.com/playlist?list=PL_U7i0VKF_mh7Vh3o2Yyt...
Paper: https://www.cs.utah.edu/plt/publications/fpw15-lf.pdf
Li, Xiangqi; Flatt, Matthew - Medic: Metaprogramming and Trace-Oriented Debugging (2015)
Building on top of Medic, but unfortunately still not packaged (unlike Medic), Li & Flatt developed (the somewhat ill-named, due to that name overlapping with something from the cryptocurrency crowd) 'Ripple', which makes debugging Domain specific languages a lot slicker:
http://www.cs.utah.edu/plt/publications/sle17-lf.pdf
Li, Xiangqi; Flatt, Matthew - Debugging with domain-specific events via macros (2017)
There's a YouTube demo here:
https://www.youtube.com/playlist?list=PL_U7i0VKF_mjF_SMiPbz-...
The published version of the above paper sits behind an ACM paywall, however, the download of the 'artifact' is open/free…:
https://dx.doi.org/10.1145/3136014.3136019
…and currently unfortunately represents the only way one can acquire the Ripple source code - and the artifact consists of a 2.4GB VM! :| (I understand why, and I consider it good scientific praxis - but I'd still appreciate a public repository in addition.)
Direct link to the artifact, for the impatient:
https://dl.acm.org/ft_gateway.cfm?id=3136019&type=zip&path=%...
Note that the artifact actually contains two very slightly different versions of the Ripple source code, a diff of which I posted over here on Github:
https://github.com/vygr/ChrysaLisp/issues/5#issuecomment-424...
(it's a two line difference in main.rkt)
If you do any of the in Racket, I can most highly recommend giving Medic (and Ripple, if you need it.) a try!
These are not "optimized" with regard to their ordinary mutable counterparts.
> These two data structures are highly practical, performant in most of the cases.
Immutable hashes are highly impractical when you need regular mutable hashes, which is most of the time.
The only annoying thing, is how to reduce brackets ( and ) from distracting content from its layout.
Of course Python is not the answer (due to its strict identation on space/tabs)
If i could teach newscomer about programming, i would say: Programming = composition of functions.
I am not sure this argument is given.
Immediately, I see there is a mismatch between what I want to program -- an objective, an algorithm, a procedure, a series of side effects that is outside the axioms of the programming language can support -- a mismatch between these objectives and this confinement of everything being an expression. An expression is a value. So to program in a language where everything is an expression is to map our idea into a (list of) value. This may be natural for programs that is seeking a value, but often not so. Even for programs that is seeking a value, the bulk of the program is to control the process of finding this value. There is no easy way or even correct way to map a process and side effects into a value. Math is logic or equivalency. To establish equivalency is to discard the effect of path or side effects. Therefore, to map the desired process and side effects into value, we have to add back the implicit knowledge of how these values are actually transformed. In stead of directly stating the transformation of values -- an imperative programming style -- we express that with dependency and relying on the understanding how these dependency is being resolved. The latter is very hard.
Of course, in practice, we have to give up on the fine control of our program to some extent and relying on the compiler implementation giving us desired result (the path and its side effects), then we only need worry about the value. When it works, it works great; when it does not work, we need either lower our expectations or give up the language, or transfer the burden/blame to compilers.
The argument for everything being an expression is the composability(although I thought the reason was ease and flexibility of writing compilers for it). This is similar to the argument that: if every object is a lego piece, then building something is easy. Well, it depends. First we need accept that lego pieces are all what we have. Second, we have to contend that what lego pieces can build is good for our needs. There are amazing lego projects, but they are nowhere I would find easy.
(if (rocket-engine-running?)
(start-rocket)
(start-engine))In your example, after you started the engine, don't you still need `start-rocket`? The bug sneaks in due to discrepancy that while the syntax is all about values, the semantics is all about flows.
Waiting for Racket-on-Chez effort to come with more optimizations and multi-core access
Chez-scheme has a pthread-style interface to OS threads, which has it's own set of problems with respect to concurrency(knowing which operators are thread safe). Not sure how racket would expose this.
He implies python doesn't have an "if" expression. It does.
He specifically claims this is invalid in python implying that "if" expressions don't exist in python:
x + (if is_true(): 1 else: 2)
The following is written in python and is correct syntax: x + (1 if is_true() else 2)
Although it's not "pythonic" to use python functionally, Python is a multi-paradigm language and has the facilities to be used as a very powerful functional language. It's not just a "functional" library. Functional is built into python syntax. The following is correct python syntax that will pass a type checker process as well. #List comprehensions using map and filter:
x: List[int] = [i+2 for i in range(100) if i%2 == 0]
#anonymous functions:
x: Callable[[int], int] = lambda a: a + 2
With mypy, type annotations or any other external type checker, python approaches the power and correctness of typed functional programming languages like haskell or Ocaml, though it is missing many features.In Python, an if conditional is a statement, and can only be used in certain positions.
This is categorically wrong. In python the if conditional exists in statement form and expression form. The if-expression also basically exists in every other imperative language out there, usually in this form:
x + (is_true() ? 1 : 2)
I know he's not trying to criticize python. Just want to correct his mistake and emphasize that python has intrinsic design features that can make it very very functional.I also offer some proof as to why python is a bad choice for his examples because python is actually a highly functional language. It's like trying to use haskell to prove racket is more expressive. It's a bad choice.
Sometimes I don't understand people. I literally posted just factual errors, no opinions on his article and then people misinterpret everything I said as opinion and proceed to tell me I misinterpreted things, then vote me down. Seriously.
...
“But wait! Python has a ternary conditional expression!” It doesn’t change the essential point, but OK—you can indeed write this:
42 + (100 if 1 < 0 else 200)
But now suppose we want to use a conditional in place of the operator, not the right-hand value. In a Lisp, because everything is an expression—including the operator itself—this is easy:
((if (< 1 0) + * ) 42 100)
But if you try the same thing in Python, it will raise a syntax error:
42 (+ if 1 < 0 else * ) 100
...