4 ms·
I disagree that `aif` is semantically any narrower than `let-if`, or that `awhen` is narrower than `let-when`. I'd argue that they have very nearly the same se
by groovy2shoes 10y ago
I disagree that `aif` is semantically any narrower than `let-if`, or that `awhen` is narrower than `let-when`. I'd argue that they have very nearly the same semantics, or at least the same semantic structure, modulo alpha conversion. Furthermore, `it` is implicit, but that does not mean it gets to escape mental processing. It's an extra thing that must be learned and remembered, and a mental binding must be established whenever the form is read anyway.
I also feel confident that pg put the anaphoric macros into Arc primarily to reduce typing, given his introductory article about the design of Arc:
> It would not be far from the truth to say that a hacker about to write a program decides what language to use, at least subconsciously, based on the total number of characters he'll have to type. If this isn't precisely how hackers think, a language designer would do well to act as if it were.
However, I'd be silly to deny that less writing does not lead directly to less reading, and I'd be disingenuous not to also include a later passage:
> But the cost of a long name is not just the cost of typing it. There is also the cost of reading it, and the cost of the space it takes up on your screen.
(Somewhat tangentially, I agree that names in Lisp can sometimes get comically long, but I think there's a happy medium between 20+ character names and 3- character names.)
I personally find the more explicit variable names offered by `let-if` (and the more descriptive macro name itself) to aid in reading. I also disagree that `aif` has a "single, simple organizing principle to the form" whereas `let-if` does not. `let-if` is, as its name implies, a composition of `let` and `if` (just as `mapcar` is a composition of `map` and `car`, and `cadr` is a composition, etc.), and it is structured that way. In fact, even if `aif` &co. are individually fine, they add weight (albeit quite light) to the mental burden of the overall language simply by being extra, whereas `let-if`, as a composition of existing constructs, is not extra.
I'm willing to agree to disagree and chalk it up to preference. In fact, I'm starting to feel a little silly elaborating such a small thing :D I'm just hoping I managed to adequately explain my point of view, and that it at least seems like a sensical place to stand, even if you think it's a worse place to be standing.
And thank you for taking the time to elaborate on your thoughts. A friend of mine with whom I periodically debate religious topics is fond of saying "an unexamined faith is not worth having", and I think the same holds true for any belief, opinion, ideology, etc. At the very least, I had a chance to really think about this stuff in more depth :)
- kazinator 10y agoI also don't feel that aif has much value, and doesn't resemble the linguistic anaphora that it is inspired by. That's why I did a "one up" in my ifa design, to outdo the silly aif macro. In English, I can say, "if x exceeds 3, then print it". When I say that, it's obvious to everyone that by "it" I do not mean the Boolean value of "x exceeds 3". I mean x. So aif is nothing like the anaphoric "it" we encounter in English. I tried to make ifa at least superficially try to capture some of that: (ifa (> (whatever) 3) (print it)): prints value of (whatever). Also, suppose (whatever) is a place. We want to be able to say "If (whatever) exceeds 3, increment it": (ifa (> (whatever) 3) (inc it)). And we don't want (whatever) evaluated twice. The expression (aif whatever expr-containing-it) doesn't buy us much over (iflet (var whatever) expr-containing-var). Both communicate an organization of code around something returned from whatever, which can be nil (don't run the code) or some non-nil object (do run the code, refer to the thing as var). To me also, aif does look mostly like keystroke saving. My iflet/whenlet/whilet/condlet constructs bind multiple variables. The last one is tested: (iflet ((x whatever) (y another thing)) expr-evaled-if-y-true). This makes the macros helpful in more situations. (Next release will make the y optional if expr doesn't need it.) E.g.: (whenlet ((x (get-something arg)) (y (get-some-dependent-thing x other-arg (calculation))) ;; code run if y is true, with access to x too ) Or: (whilet ((next (get-next-object stream)) (maybe-foo (if next (get-foo-property next)))) ;; process only maybe-foo things from stream ) We should try towrite macros that have some half decent level of impact: bang for the parenthesis and symbol. Especially if they are intended for enduring public use.
- groovy2shoes 10y agoVery neat!