5 ms·
Isn't loop essentially a macro (probably special op) that a lot of people hate, specifically because it is a sprawling dsl? Because lisp has an expressive macro
by aaron-lebo 9y ago
Isn't loop essentially a macro (probably special op) that a lot of people hate, specifically because it is a sprawling dsl? Because lisp has an expressive macro system, it can lead people to that. The existence of macros requires an at least above average dev community, because it's one thing when a decently-designed but controversial dsl like loop is default to the language, it's another when every project can roll out their own poorly considered and implemented dsls using macros when simpler abstractions would have sufficed.
Most lisp docs will tell you to use macros only when necessary, because as great as they are, they have inherent issues that aren't fixed just by having a good macro system.
This is bad use of macros, or an ugly macro system.
No true scotsman?
- lispm 9y agoThe LOOP macro has actually seen a lot of work in designing and implementating it, including a syntax spec. Some people don't hate it because it is a DSL, but because it is a bit different from the regular Lisp macro, in that it requires more parsing and its clauses are not grouped by parentheses/s-expressions. Plus: understanding the relationship of the clauses is not really that simple, since there is some implicit grouping and dependencies. This is what a LOOP macro looks like in code: (loop for i from 0 below n for v across vec when (evenp n) collect (* i v)) This is what a typical Lisp programmer would prefer: (loop ((for i :from 0 :below n) (for v :across vec)) (when (evenp n) (collect (* i v)))) The clauses would be grouped in a list and each clause would be a list. The body would then use the usual Lisp syntax and the WHEN and COLLECT features would look similar to normal Lisp macros. The LOOP macro is historically coming from Interlisp (70s), where it was a part of a certain language design trend called 'conversational programming'. The idea was to have some more natural language like programming constructs, combined with tools like spell checkers and automatic syntax repair (Do What I Mean, DWIM). From there this idea and the FOR macro was influencing the LOOP macro for Maclisp. The LOOP macro grew over time in capabilities and was then transferred to later Lisp dialects, like Common Lisp. There are actually Lisp macros which are even more complicated to implement and even more powerful, but which create less resistance, since they are a bit better integrated in the usual Lisp language syntax. An example is the ITERATE macro: https://common-lisp.net/project/iterate/ https://common-lisp.net/project/iterate/ Thus it is not the complexity or the functionality of the macro itself, but a particular style of macro and its implementation. I personally also prefer something like ITERATE, but LOOP works fine for me, too. The advantage of something like ITERATE or even LOOP is that they are mostly on the developer level, and not fully the implementor level. A developer or group of developers can develop such a complex macro and can integrate it seamlessly into the language, making the language more powerful and allows us to reuse much of the knowledge/infrastrucure about/of the language. Implementing and designing something like ITERATE and LOOP requires above the usual dev capabilities. Generally macros require some of that, since it makes it necessary that the dev can use or program on the syntactic meta-level. It's there where language constructs are reused, implemented and integrated. Lisp docs will tell you to use macros only when necessary? They tell you to WRITE macros only when necessary. Since many Lisp dialects have a lot macros, you have to use them anyway. Most of the top-level definition constructs are already macros. If we use DEFUN to define a function, we already use macros. In my experience actual Common Lisp uses a lot of macros. I also tend to write a fair number of macros. But generally good macro programming style is slightly underdocumented, especially when we think of various qualities: robustness, good syntax, usefulness, readability, avoiding the obvious macro bugs, ... On Lisp from Paul Graham is useful, as a few other sources, ... Read On Lisp here: http://www.paulgraham.com/onlisp.html http://www.paulgraham.com/onlisp.html Macros are very useful and I use them a lot, but at the same time one needs to put a bit more care/discipline into them and some help of the development environment is useful...
- Shorel 9y agoI wonder if in a parallel world we would have a library system similar to the one used in Node.js with npm, and many installable libraries would consist of a single macro.
- flavio81 9y ago>Most lisp docs will tell you to use macros only when necessary One also declares variables when necessary, and one also creates arrays when necessary, etc. But imagine a programming language that doesn't support arrays. It would be a nightmare if you need to do certain scientific computations. So in the same way, yes, not having a (proper, Lisp-like) macro system surely hurts a lot, once you realize how it makes certain problems become really easy. And, by the way, one should write macros when necessary. In Lisp, we're using macros most of the time! >Isn't loop essentially a macro (probably special op) that a lot of people hate? And other Lisp programmers like the LOOP macro, since it can allow for very readable and concise code to do something simple that should stay simple to read. Examples: (loop for x from 1 for y = (* x 10) while (< y 100) do (print (* x 5)) collect y) Result: 5 10 15 20 25 30 35 40 45 (10 20 30 40 50 60 70 80 90) Example 2: (loop for x in '(a b c d e) for y in '(1 2 3 4 5) collect (list x y) ) Result: ((A 1) (B 2) (C 3) (D 4) (E 5)) Source of examples: http://cl-cookbook.sourceforge.net/loop.html http://cl-cookbook.sourceforge.net/loop.html
- gowld 9y agothat loop code looks hideous. For the first: There's an implicit x->x+1 hiding in there? Why 'for y' if y is derived from x and not incremented on its own? For the second: It looks like a nested (cross product) loop, but it's actually a zip (dot product) loop?
- kazinator 9y agoIt certainly does not look like it is one way or the other; it is something you have to know. If you don't know anything about loop, but have a belief that it is doing a Cartesian product, or a belief that it is not doing one, your belief has no rational basis either way. You can infer which one is right from the output. loop doesn't do cross-producting; if you know that, there is no mistaking it. All the clauses specify iteration elements for one single loop. "for x from 1" means starting at 1, in increments of 1. "for y = expr" means that expr is evaluated on each iteration, and y takes on that value. y could be incremented on its own, but then that example wouldn't show the "for var = expr" syntax, how one variable can depend on a combination of others.