> I've removed thisfn from Clojure.
I support removing thisfn for the reasons you give, but I am very much
against interfering with the clean semantics of let. Sure as hell,
someone somewhere is going to use let to bind a variable to the result
of a macro that introduces a top-level fn under the covers and get
surprised by the result.
> The original idea was to allow for recursive anonymous functions and
> avoid another let construct (letrec/labels) for recursive local
> functions.
>
> In dropping thisfn I've preserved the latter while losing the former,
> which was not used once in boot.clj or elsewhere, and is not possible
> in any other Lisp AFAIK (Y-combinator aside).
If you don't want letrec, you can go back to Lisp 1.5's label, with
the syntax (label name (lambda arglist . body)) or the Scheme
extension rec, with the syntax (rec name arglist . body). But
"knotted" name binding needs its own construct one way or another:
letrec/labels is just the most general method.
> I think this is a good solution, it leaves Clojure simple and removes
> a blemish.
By being too simple, it introduces another blemish. Things should be
as simple as possible, but no simpler, as Einstein said.
--
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures
> Now you can (optionally) put a symbol between fn and [ and that name
> will be in scope in the body of the fn definition, where it will refer
> to the fn itself.
+1
> Interestingly, when changing those parts of Clojure that let a
> recursive fn I always chose 'this' for the fn name, not the let name.
> It seemed clearer, and isolated the let-bound name to the let, so if
> it needed to be renamed I wouldn't have to touch the fn body.
That sounds like sensible advice that should go in the manual; it's
like the tendency of Scheme programmers to use "loop" as the name of a
named let.
> I've also removed the injection of the let name into the fn
> expression. Even if I revisit that in the future, I won't take away
> the anonymous fn naming syntax.
I apologize for not getting back to you with specific examples; I've
been too swamped to think them up. I was just speaking out of general
experience with "special cases", especially in Lispish languages where
it's not always obvious that you are invoking a special case because
it's concealed behind a macro.
If anyone's curious, it's easy to implement named let with this
addition, I find it clearer than ((fn this [arg-names] ...)
arg-inits):
(defmacro nlet [name args & body]
(let [arg-names (take-nth 2 args)
arg-inits (and args (take-nth 2 (rest args)))]
`((fn ~name [~@arg-names] ~@body) ~@arg-inits)))
You just have to be careful of the lack of TCO. Is there a way to
recur from inside multiple function boundaries?
Henk