Expressions can sometimes contain itertools.islice objects, which we can
only walk if we force them into a list. To do this, the walk function
has to be taught that collections that are not instances of list should
be forced into a list.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Python 3.5's PEP 448 ("Additional Unpacking Generalizations") allows the
iterable- and dictionary- unpacking operators to be used more than once;
the implementation (see https://hg.python.org/cpython/rev/a65f685ba8c0)
gets rid of the optional `starargs` and `kwargs` arguments to `ast.Call`
and `ast.ClassDef`, instead using `ast.Starred` and `ast.keyword`
objects inside of the normal `args` and `keywords` lists,
respectively. This commit allows Hy's `apply` to work correctly with
this revised AST when running under Python 3.5.
As reported in issue #748, there was a bug in which passing a lambda
as the value of a :keyword argument would fail—
$ hy --spy
hy 0.10.1 using CPython(default) 3.4.0 on Linux
=> (sorted (range 10) :key (fn [x] (- x)))
from hy.core.language import range
sorted(range(10), key=_hy_anon_fn_1)
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name '_hy_anon_fn_1' is not defined
The function call would appear in the generated AST without being
preceded by the appropriate function definition corresponding to the
anonymous function argument value in the Hy source, causing either a
NameError (as in the example above), or erroneous reuse of whatever
function was already pointed to by the `_hy_anon_fn_` name referenced
in the list of keywords passed to `ast.Call`.
This commit aims to fix the problem by handling it in same way that
the expression/statement gap is bridged many other places in the
compiler, by adding the compiled value of the keyword argument to the
Result object being built during `_compile_collect`, with the
understanding that any Python statements implied by the argument value
will be appropriately preserved therein.
Python 3.5 will have a new commercial-at infix operator with the magic
methods __matmul__, __rmatmul__, and __imatmul__, unused as yet in the
standard library, but intended to represent matrix multiplication in
numerical code; see PEP 465 (https://www.python.org/dev/peps/pep-0465/)
for details. This commit (developed against Python 3.5 alpha 3) brings
support for this operator to Hy when running under Python 3.5 (or,
hypothetically as yet, greater). For Hy under Python <= 3.4, attempting
to use `@` in function-call position currently results in a NameError;
this commit does not change that behavior.
This is intended to resolve#668.
This code is heavily, *heavily* based off of Guillermo Vaya
(willyfrog)'s work... instead of defining its own keyword arg though, it
uses the "standard" :kwarg type, which is the main difference from
willyfrog's original branch.
Included tests and some documentation in the tutorial.
Also documented "apply" separately as an example of reproducing
*args and **kwargs.
When (fn) or (defn) does not get an arglist as first/second parameter,
emit a more descriptive error message, rather than an ugly traceback.
Fixes#716.
Reported-by: Joakim Tall
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Our MetaImporter was being inserted at the end of sys.meta_path.
For Python prior to 3.3, this was fine since sys.meta_path
was empty by default. As of the completion of PEP 302 in Py3.3 and
later, there are several importers registered by default. One of
these was trying (and failing) to import simple Hy modules,
resulting in a failure to import anything inside __init__.hy.
This change simply inserts the Hy-specific importer at the front
of the list.
This was noted in issue #620 (great catch @algernon)
A tribute to Portal 2, this function will return an infinite list of the
contents of the AUTHORS file on GitHub master (assuming requests is
installed). Except, the macro does this, the function never gets called,
it is purely there for tribute reasons.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Python has the keyword.iskeyword method we can leverage for Python
keywords, but we also need to address Hy builtins like 'get' or
'slice'.
And to make behavior compatible with Python 2 or 3, we also make
a special case to prevent assignment to False, True or None as
well as the Hy versions: false, true, null, and nil.
For non-Hy modules, we also check to make sure the symbol is not
part of the compiler. This allows shadow.hy to override "+" but
prevents general use from re-defn-ing 'get' or 'do'.
As noted in #600, Python 3 allows a return inside a generator
method, that raises a StopIteration and passes the return value
inside the 'value' attr of the exception.
To allow this behaviour we simple set 'contains_yield' while compiling
'yield', thus allowing a return statement, but only for Python 3. Then
when compiling the try-except, we check for contains_yield to decide
whether there will be a return.
This allows code like:
(defn gen []
(yield 3)
"goodbye")
to compile in both Py2 and Py3. The return value is simply ignored in
Python 2.
hy2py in Python 2 gives:
def g():
yield 3L
u'goodbye'
while hy2py in Python 3 gives:
def g():
yield 3
return 'goodbye'
Turns out return in yield started in Python 3.3
This new core module allows us to shadow the builtin Python operators so
they may be passed to sequence functions that expect functions:
=> (map / [1 2 3 4 5])
[1.0, 0.5, 0.3333333333333333, 0.25]
Currently, defmacro/g! doesn't respond well when it comes across a
HyObject that doesn't respond to the instance method startswith (e.g.
HyInteger, HyFloat, etc.). This updates defmacro/g! to be a little
safer when searching for the gensyms it needs to create.
This also breaks out the PY3 only tests into their own file. We need to do this because raise from is a syntax error in PY2, so we can't rely on the previous hack of catching a HyCompileError - it would compile fine through Hy and then be a syntax error in Python.
As a result:
* functions such as `nth` should work correctly on iterators;
* `nth` will raise `IndexError` (in a fashion consistent with `get`)
when the index is out of bounds;
* `take`, etc. will raise `ValueError` instead of returning
an ambiguous value if the index is negative;
* `map`, `zip`, `range`, `input`, `filter` work the same way (Py3k one)
on both Python 2 and 3 (see #523 and #331).
Also small DRYing in try handling.
Previously, writing a bare (try (foo)) would invoke Pokemon
exception catching (gotta catch 'em all) instead of the correct
behavior, which is to raise the exception if no handler is provided.
Note that this is a cute feature of Hy, as a `try` with no `except`
is a syntax error. We avoid the syntax error here because we don't
use Python's compiler, which is the only thing that can throw
Syntax Errors. :D
Fixes#555.
The yield-from that existed previously wasn't actually implementing the
full complexity of "yield from":
http://legacy.python.org/dev/peps/pep-0380/#formal-semantics
... this includes passing along errors, and many other things.
Also removes the yield-from backport macro, since it does not seem
possible at present to conditionally build macros.
Thus, there is no longer yield-from on pre-python-3.3 systems.
Includes updated docs and tests to reflect all this.
One would expect the form:
> (defmacro a (&rest b) b)
> (a 1 2)
To return a tuple object but we have no Hy model so it returns a HyList.
Not sure if this is the right thing to do.
This function will recursively perform all possible macroexpansions in
the supplied form. Unfortunately, it also traverses into quasiquoted
parts, where it shouldn't, but it is a useful estimation of macro
expansion anyway.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The hy.contrib.walk module provides a few functions to walk the Hy AST,
and potentially transform it along the way. The main entry point
is (walk), which takes two functions and a form as arguments, and
applies the first (inner) function to each element of the form, building
up a data structure of the same type as the original. Then applies outer
(the second function) to the result.
Two convenience functions are provided: (postwalk) and (prewalk), which
do a depth-first, post/pre-order traversal of the form.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
* hy/core/language.hy: Adding a simple `identity` function that returns
the argument supplied to it
* docs/language/core.rst: Updated docs with identity function
Sometimes it is better to start with the false condition, sometimes that
makes the code clearer. For that, the (if-not) macro, which simply
reverses the order of the condition blocks, can be of great use.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
In the same vein as defmacro-alias, this implements defn-alias /
defun-alias, which does essentially the same thing as defmacro-alias,
but for functions.
Signed-off-by: Gergely Nagy <algernon@balabit.hu>
* hy/core/language.hy:
-Added a simple coll? function that checks whether the given argument
is an iterable and not a string,
- Also replaced the check in `flatten` by coll?
* tests/native_tests/core.hy: Tests updated for checking coll?
This cleans up a number of doc warnings, including a bad
underline for zero?
While there, added a nil? function to match up with the
new nil is None.
Also un-hid myself from coreteam.
When calling get with more than two arguments, treat the rest as indexes
into the expression from the former. That is, (get foo "bar" "baz")
would translate to foo["bar"]["baz"], and so on.
This fixes#362.
Requested-by: Sean B. Palmer <sean@miscoranda.com>
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
* hy/contrib/anaphoric.hy: The following anaphoric macros have been
added
`ap-reject` : Opposite of ap-filter, yields the elements when a `pred`
evaluates to false
`ap-dotimes` : Execute body forms (possibly for side-effects) n times
with `it` bound from 0 to n-1
`ap-first` : return the first element that passes predicate
`ap-last` : return the last element that passes predicate
`ap-reduce`: anaphoric form of reduce that allows `acc` and `it` to
create a function that is applied over the list
* docs/contrib/anaphoric.rst: updated docs to reflect these changes
* tests/__init__.py: updated to explicitly include tests for anaphoric
macros
Apply didn't work on method calls (i.e. `(apply .foo [bar]) broke).
This slipped through because there were no tests of this behavior. I noticed
it while trying to merge the `meth` fixes.
Added first iteration of reader macros
Refactored defmacro and defreader
Added test inn hy/tests/lex/test_lex.py
Added new test in hy/tests/native/tests
Added new test in hy/tests/macros.
changed the error given in the dispatch macro and added some handling for missing symbol and invalid characters
Adding to the manual gensym for macros are 2 new
macros, but very literal from the CL in
letoverlambda.
The first is the (with-gensyms ...) macro that
can generate a small set of syms for a macro. Works
something like:
(defmacro adder2 [A B]
(with-gensyms [a b]
`(let [[~a ~A] [~b ~B]]
(+ ~a ~b))))
and ~a and ~b will be replaced with (gensym "a") and
(gensym "b") respectively.
Then the final macro is a new defmacro that will automatically
replace symbols prefaced with "g!" with a new gensym based on the
rest of the symbol. So in this final version of 'nif':
(defmacro/g! nif4 (expr pos zero neg)
`(let [[~g!result ~expr]]
(cond [(pos? ~g!result) ~pos]
[(zero? ~g!result) ~zero]
[(neg? ~g!result) ~neg])))
all uses of ~g!result will be replaced with (gensym "result").
Simple implementation of gensym in Hy.
Returns a new HySymbol.
Usable in macros like:
(defmacro nif [expr pos zero neg]
(let [[g (gensym)]]
`(let [[~g ~expr]]
(cond [(pos? ~g) ~pos]
[(zero? ~g) ~zero]
[(neg? ~g) ~neg]))))
This addresses all the general comments about (gensym), and doesn't
try to implement "auto-gensym" yet. But clearly the macro approach
instead of the pre-processor approach (as described in the
letoverlambda (http://letoverlambda.com/index.cl/guest/chap3.html#sec_5)
is the way to go
Like other lisps, operators `+` and `*` return their identity values
when called with no arguments. Also with a single operand they return
the operand.
This fixes#372
The fancypants Hy award goes to Nick for coming up with the quoted
symbol hack for exports. This broke with foo?, since the export string
needs to be is_foo, but using a quoted string will pick up the change
due to it being a Symbol.
Mad clown love for that, @olasd.
A couple of more macros:
hy> (--each-while [1 2 3 4 5] (< it 3) (print it))
1
2
3
hy>
```--each-while``` continues to evaluate the body form while the
predicate form is true for each element in the list.
```--map-when``` uses a predicate form to determine when to apply the
map form upon the element in the list:
hy> (list (--map-when (even? it) (* it 3) [1 2 3 4]))
[1, 6, 3, 12]
Anaphoric macros reduce the need to specify a lambda by binding a
special name in a form passed as a parameter to the macro. This allows
you to write more concise code:
(= (list (--filter (even? it) [1 2 3 4])) [2 4])
This patch just adds a few basic ones. Other forms that can be
converted to anaphoric versions include reduce, remove, enumerate,
etc.