Open Quelklef opened 5 years ago
Sounds like a good idea to me. We were following Clojure here, but Common Lisp's interpretation makes more sense to me.
Actually, if we do that, perhaps we should use Common Lisp's names, incf
and decf
, so as not to trip up Clojure programmers.
Eh, incf
and decf
are fairly ugly names, IMO. I personally would like inc!
and dec!
but as far as I can tell, Hy doesn't use that convention.
Another option would be to not have mutative increment/decrement functions. (+= x 1)
and (-= x 1)
are not that bad to write, and while succ
and pred
are likely to be passed around a lot in functional code, saving many keystrokes over (fn [x] (+- x 1))
, I imagine that mutative increment/decrement functions will only be used as statements, not saving that much at all.
+1 to not changing the existing meaning of inc
/ dec
to be mutative. (as someone coming from Clojure and also very new to Hy)
Using incf
from Common Lisp doesn't make much sense because there's no equivalent concept in Hy of a "generalized place variable"...
Maybe incv
/ decv
in relation to setv
?
(defmacro incv [x]
`(+= ~x 1))
(setv xs [1 2 3])
(incv (get xs 2))
(print xs)
;; => [1, 2, 4]
there's no equivalent concept in Hy of a "generalized place variable"
But there is; it's the same concept of lvalue that Python uses. Just as you can put a variety of things to the left of =
in Python other than plain variables, you can do the same in Hy with setv
.
I'm betting that setv
was only called what it was because Python has the built-in set
function (@Kodiologist confirm?) so I'm not sure making -v
a motif would be great.
Personally I think it would be cool to do this as follows:
doto
transforms mutative forms into non-mutative forms. What if there was a counterpart, called, say, #!
?
(setv x 1)
#! (succ x) ; expands to (setv x (succ x))
(setv l [5 4 3 2 1])
#! (sorted l) ; expands to (setv l (sorted l))
This would be a more general solution, bridging the mutative<->non-mutative gap in the other direction, which would be awesome. However, it's a little weird/hard to read. Also, the examples I gave are very simple and it's not clear how it should generalize to multiple values or multiple forms (if desired).
I'm betting that
setv
was only called what it was because Python has the built-inset
function (@Kodiologist confirm?)
It looks like it (73695881a9b69bab9d10a356258e78cf0ec6afa3).
Yeah, it's not clear how #!
would detect the lvalue in general.
A solution would be to make it not a tag, so you'd have:
(mut a (succ))
(mut b (sorted))
(mut c (filter even?))
; Multiple forms?
(mut d (map succ) (filter even?))
where the supplied argument is the last argument.
Personally I actually like the -v
prefix as a sort of reminder that it follows Python's scoping rules, as opposed to the setq
in other Lisps.
@Quelklef wouldn't that just be a specialized form of threading macro?
(defmacro ->! [lval &rest forms]
`(setv ~lval
(-> ~lval ~@forms)))
;; eg.
(setv x 1)
(->! x
(str)
(repeat 5)
(zip (range 10))
(list))
(print x)
;; => [('1', 0), ('1', 1), ('1', 2), ('1', 3), ('1', 4)]
Yeah. But I've been pondering this kind of macro for a while and I think it may be useful enough to warrant its own thing.
I suppose it doesn't make sense to call (-!> x succ)
a "solution" to this discussion since it's more verbose than (+= x 1)
and really the power of mutative inc
/dec
is concision. Written-out increment
and decrement
functions are off the board as well.
My personal vote goes for:
inc
/dec
.+=
and -=
.succ
/pred
.This would also fit better with Python's "one way to do it" mantra.
My vote would be for inc
/dec
non-mutative like Clojure (status quo). I understand that immutability is not as pervasive in Hy as it is in Clojure, so failing that, we should fall back on the names 1+
/1-
like Common Lisp for non-mutative instead of succ
/pred
. Generally we should borrow from Python, Clojure, Common Lisp, in that order.
I get that Hy follows Clojure, but I would opine that Clojure's naming is a mistake. I presume that inc
and dec
stand for increment
and decrement
. To "increment" and to "decrement" are both fundamentally mutative operations, and having them pure seems misleading.
And by status quo more general than just Clojure, inc
and dec
should be succ
and pred
.
I'm not sure I should get a vote, but I can't help being opinionated here.
1) I know Hy is supposed to be a moving target at this stage, but breaking changes should be minimized. I'm sure there are excellent reasons for having dropped let
, for example, but the fallout is a good chunk of the small amount of Hy code there is around being broken.
2) Python is fairly confusing around what's in-place and what's a proper function (i.e. the behavior of sort
versus sorted
). With the full character set and so many traditions to choose from, Hy can do the big-tent thing by supporting a pure inc
, a mutating incf
(and an inc!
) and succ
as a synonym for numeric types. In my mind inc
and succ
are already slightly different concepts (cardinal vs ordinal numbers).
3) There are probably good reasons not to do (2) to the extreme (elegance, for one; it matters), but I'd argue the default policy in discussions like this should be "do the big-tent thing" (at the cost of proliferating synonyms) and then the argument for choosing One True Option be made. Most often this would lead to the One True Option anyway, but it'd simplify discussions and minimizing the risk of unnecessary breaking changes (even if at times these are going to be necessary anyway).
IMO,
inc
is poorly named. I had thought that(inc x)
is(+= x 1)
when it, in fact, is(+ x 1)
. "increment" seems to imply a mutative statement.I suggest that
(inc x)
be(+= x 1)
and(succ x)
be(+ x 1)
. Similarly,(dec x)
should be(-= x 1)
and(pred x)
be(- x 1)
.This would be in line with:
succ
andpred
mean what Hy'sinc
anddec
do.