gilch
For sum types we have enums, and for product types we have tuples (or namedtuples or dataclasses). Sugar could be done with decorators or metaclasses.
For Lisp macros, there's macropy and Hissp.
https://www.gnu.org/software/m4/
https://threeofwands.com/algebraic-data-types-in-python/
Try Hissp (https://github.com/gilch). Lisp programming and Python's ecosystem.
import code; code.interact(local=vars(foo))
where `foo` is the module object you want to set as current. This launches a subREPL in that module's namespace. (EOF kills the subREPL and returns to main.)Python has a debugger in the standard library that can also do post-mortem inspections.
You can have both with Hissp. https://github.com/gilch/hissp
I made a small one that classified dinosaurs in school.
If you're already comfortable with Python, check out Hissp's tutorials (in the docs). It's a Lisp hosted on Python, so you can focus on the Lisp concepts without getting so bogged down by learning a new standard library at the same time.
Hissp just released version 0.4.0. It compiles Python tuples to Python expressions and has multiple readers with different characteristics, not all of which are based on S-expressions.
Android is basically Linux, which is great for development. You can install the Termux app (https://github.com/termux/termux-app) on Android phones, then you have a shell and a decent package manager. You can install compilers and interpreters and text editors. Python, Emacs, and so forth. (And shell is a scripting language in its own right.) The Play Store version of Termux is kind of crippled, so you'd want to sideload. It might be easiest to sideload the F-Droid store first and install from there. Recent versions of Android (12+) also aggressively kill processes to save battery life, which makes Termux much less usable. It takes some technical know-how to turn that off, but there are instructions linked in the Termux repo.
I'm less familiar with the iPhones, but they're a lot more locked down. I'd expect Android phones to be more common because they're cheaper, but sufficiently old iPhones are not that expensive either. There are some iOS IDE apps, but I don't think they're quite as complete as Termux can be.
Single-board computers like the Raspberry Pi are fairly cheap and can run Linux. I think even iPhone users can ssh into a server. Linux is multi-user, so students could share. Simple command-line apps don't require a very powerful computer by modern standards.
There are also a number of online IDEs that would only require a decent web browser. Some of them might be compatible with iPhone Safari. I'd consider JupyterLite, which is free and runs entirely in-browser. https://github.com/jupyterlite/jupyterlite
There are so many details one has to get right in one's head to program at all, that non-programming experience doesn't prepare one for. E.g. the assignment operator isn't symmetric like the equality boolean operator (in most languages). This is not how it works in math. The simpler the language you start with, the easier it is to model in one's head.
Having a simple language with a REPL is super useful for getting this straight--if you don't know what it does, you quickly test the assumptions. Go through lots of small examples. Have the students predict and write down what the output will be, then run it and have them explain why they were surprised. This should help you diagnose where their mental models are wrong. Tell them to assume the bugs live in the programmer's mental model, not in the compiler. Flip the classroom if you need more time for this. (I.e. pre-record the lectures, and have them watch them as the homework, and work on the exercises during class time.)
Explain the language's memory model. What lives on the stack or on the heap? How are arguments passed? What's a copy and what's a mutation? Diagram on the blackboard. Write assumptions down. Human working memory is extremely limited. The gifted students might have seven registers to work with, when they're concentrating. If they're learning the language itself, or talking to you at the same time, there isn't much left to program with. Those with more average IQ might not have anything left at all. Have them start with pseudocode, and iteratively break it down to the level that it can be mechanically translated into the language. Offload everything you can.
If you know how to do it in Python (or Hy, probably) the community chat can help show you how to translate it to Lissp.
The Lissp REPL also shows the Python compilation before evaluating it, so if you're already familiar with Python, that can help you get a handle on Hissp.
Lambdas can't have single statements either. The body is only an expression. So why are we saying "multiple" (a word to distinguish from "single") if you meant to multiply statements? The number of statements is zero.
Does a try/except fit on one line? That's a try statement. Does a class? Technically possible, but typically no. That's a class statement. It's not just the "class" word, or the first line. The class statement includes its body. Many Python statement types can't fit on one line, and many others don't have to. So why are we saying "lines" to mean statements when these are not remotely the same thing?
The statement/expression distinction is a holdover from FORTRAN. Statements are just expressions that don't return a value. (Yes, Smalltalk and Haskell can implement control structures with expressions just fine, thank you.) Many functional languages do away with the distinction altogether and just use expressions. You only really need lambdas in Python for the functional style, and in functional style, expressions are all you need!
A few approaches got lucky in the rapid inflationary period of the personal computer revolution (C), and the advent of the Web (Javascript), and became deeply entrenched in industry, while superior alternatives that had been known for decades missed the boat. Industry languages still haven't caught up to where Lisp, Prolog, Smalltalk, and APL were in the 1970's, but they are clearly (if slowly) trending in that direction.
APL and derivatives are still used extensively in finance, a highly competitive field, to say the least. That's where you find the jobs.
Your cultural prejudice is showing. There are good reasons APL is written the way it is, and this example is simply bringing those benefits to C by writing it in the dense APL style. There are other APL derivatives, like J[1] that are written in C the same way. These projects are well-maintained. They aren't collapsing under a load of technical debt. The style works. To them, it's clean code.
The query params were never in the lambda to begin with. Python function calls have strict (not lazy) semantics, i.e. "applicative order", i.e. both expressions passed as arguments to map() are evaluated before the map body gets them as parameters, thus the query params would only be evaluated once, even when inlined as they were originally.
Same with the lambda definition: it's evaluated only once. It's just the lambda body that gets reevaluated each loop, and only evaluated for the first time on the first loop.