Skip to content

Commit

Permalink
Make assoc into a function instead of a special form
Browse files Browse the repository at this point in the history
  • Loading branch information
Kodiologist committed Jul 28, 2017
1 parent bd1689e commit 4e68963
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 71 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Changes from 0.13.0
as necessary, so you can write ``(eval `(+ 1 ~n))`` instead of
``(eval `(+ 1 ~(HyInteger n)))``
* Literal `Inf`s and `NaN`s must now be capitalized like that
* `assoc` is now a function instead of a special form
* `get` is available as a function

[ Bug Fixes ]
Expand Down
33 changes: 0 additions & 33 deletions docs/language/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -281,39 +281,6 @@ the assert, and is the string that will be raised with the
; AssertionError: one should equal two
assoc
-----

``assoc`` is used to associate a key with a value in a dictionary or to set an
index of a list to a value. It takes at least three parameters: the *data
structure* to be modified, a *key* or *index*, and a *value*. If more than
three parameters are used, it will associate in pairs.

Examples of usage:

.. code-block:: clj
=>(do
... (setv collection {})
... (assoc collection "Dog" "Bark")
... (print collection))
{u'Dog': u'Bark'}
=>(do
... (setv collection {})
... (assoc collection "Dog" "Bark" "Cat" "Meow")
... (print collection))
{u'Cat': u'Meow', u'Dog': u'Bark'}
=>(do
... (setv collection [1 2 3 4])
... (assoc collection 2 None)
... (print collection))
[1, 2, None, 4]
.. note:: ``assoc`` modifies the datastructure in place and returns ``None``.


break
-----

Expand Down
35 changes: 35 additions & 0 deletions docs/language/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,41 @@ Hy Core
Core Functions
==============

.. _assoc-fn:

assoc
-----

``assoc`` is used to associate a key with a value in a dictionary or to set an
index of a list to a value. It takes at least three parameters: the *data
structure* to be modified, a *key* or *index*, and a *value*. If more than
three parameters are used, it will associate in pairs.

Examples of usage:

.. code-block:: clj
=>(do
... (setv collection {})
... (assoc collection "Dog" "Bark")
... (print collection))
{u'Dog': u'Bark'}
=>(do
... (setv collection {})
... (assoc collection "Dog" "Bark" "Cat" "Meow")
... (print collection))
{u'Cat': u'Meow', u'Dog': u'Bark'}
=>(do
... (setv collection [1 2 3 4])
... (assoc collection 2 None)
... (print collection))
[1, 2, None, 4]
.. note:: ``assoc`` modifies the datastructure in place and returns ``None``.


.. _butlast-fn:

butlast
Expand Down
24 changes: 0 additions & 24 deletions hy/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1386,30 +1386,6 @@ def compile_cut_expression(self, expr):
step=step.expr),
ctx=ast.Load())

@builds("assoc")
@checkargs(min=3, even=False)
def compile_assoc_expression(self, expr):
expr.pop(0) # assoc
# (assoc foo bar baz) => foo[bar] = baz
target = self.compile(expr.pop(0))
ret = target
i = iter(expr)
for (key, val) in ((self.compile(x), self.compile(y))
for (x, y) in zip(i, i)):

ret += key + val + ast.Assign(
lineno=expr.start_line,
col_offset=expr.start_column,
targets=[
ast.Subscript(
lineno=expr.start_line,
col_offset=expr.start_column,
value=target.force_expr,
slice=ast.Index(value=key.force_expr),
ctx=ast.Store())],
value=val.force_expr)
return ret

@builds("with_decorator")
@checkargs(min=1)
def compile_decorate_expression(self, expr):
Expand Down
8 changes: 7 additions & 1 deletion hy/core/language.hy
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
(import [hy.compiler [HyASTCompiler spoof-positions]])
(import [hy.importer [hy-eval :as eval]])

(defn assoc [coll &rest kvs]
(if (odd? (len kvs))
(raise (TypeError "`assoc` takes an odd number of arguments")))
(for* [[k v] (partition kvs)]
(setv (get coll k) v)))

(defn butlast [coll]
"Returns coll except of last element."
(drop-last 1 coll))
Expand Down Expand Up @@ -457,7 +463,7 @@
(or a b)))

(def *exports*
'[*map accumulate butlast calling-module-name chain coll? combinations
'[*map accumulate assoc butlast calling-module-name chain coll? combinations
comp complement compress cons cons? constantly count cycle dec distinct
disassemble drop drop-last drop-while empty? eval even? every? first filter
flatten float? fraction gensym group-by identity inc input instance?
Expand Down
13 changes: 0 additions & 13 deletions tests/compilers/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,19 +301,6 @@ def test_ast_good_drop():
can_compile("(drop 1 [2 3])")


def test_ast_good_assoc():
"Make sure AST can compile valid assoc"
can_compile("(assoc x y z)")


def test_ast_bad_assoc():
"Make sure AST can't compile invalid assoc"
cant_compile("(assoc)")
cant_compile("(assoc 1)")
cant_compile("(assoc 1 2)")
cant_compile("(assoc 1 2 3 4)")


def test_ast_bad_with():
"Make sure AST can't compile invalid with"
cant_compile("(with*)")
Expand Down
15 changes: 15 additions & 0 deletions tests/native_tests/language.hy
Original file line number Diff line number Diff line change
Expand Up @@ -628,12 +628,27 @@
(assoc vals "two" "three")
(assert (= (get vals "two") "three")))


(defn test-multiassoc []
"NATIVE: test assoc multiple values"
(setv vals {"one" "two"})
(assoc vals "two" "three" "four" "five")
(assert (and (= (get vals "two") "three") (= (get vals "four") "five") (= (get vals "one") "two"))))


(defn test-assoc-eval-lvalue-once []
"`assoc` only evaluates its lvalue once"
; https://github.com/hylang/hy/issues/1068
(setv counter [])
(setv d {})
(defn f []
(.append counter 1)
d)
(assoc (f) "a" 1 "b" 2 "c" 3)
(assert (= d {"a" 1 "b" 2 "c" 3}))
(assert (= counter [1])))


(defn test-pass []
"NATIVE: Test pass worksish"
(if True (do) (do))
Expand Down

0 comments on commit 4e68963

Please sign in to comment.