Skip to content

Commit 5ef8525

Browse files
follow up patch to fn :decorators support, minor doc and test update (#1193)
Hi, can you please consider the follow up patch for anonymous fn decorators support (#1189). - Moved the note in python interop decorators doc at the top, as it contains important policy information. - Updated the `fn` docstring to document the form/name metadata precedence rules established in #1189, where `name` metadata takes precedence over `form`. - Added new test to verify precedence rule. - Corrected a test that was mistakenly using `defn` instead of `fn`. I don't think this requires a changelog entry but I can add if necessary. Thanks --------- Co-authored-by: ikappaki <[email protected]> Co-authored-by: Chris Rink <[email protected]>
1 parent 5525a69 commit 5ef8525

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

docs/pyinterop.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ Type hints may be applied to :lpy:form:`def` names, function arguments and retur
267267
Python Decorators
268268
-----------------
269269

270+
.. note::
271+
272+
Users wishing to apply decorators to functions are not limited to using ``:decorators`` metadata.
273+
This feature is provided primarily to simplify porting Python code to Basilisp.
274+
In Python, decorators are syntactic sugar for functions which return functions, but given the rich library of tools provided for composing functions and the ease of defining anonymous functions in Basilisp, the use of ``:decorators`` is not typically necessary in standard Basilisp code.
275+
270276
Python decorators are functions that modify the behavior of other functions or methods.
271277
They are applied to a function by prefixing it with the ``@decorator_name`` syntax. A decorator takes a function as input, performs some action, and returns a new function that typically extends or alters the original function's behavior.
272278

@@ -299,7 +305,7 @@ These decorators are applied from right to left, similar to how Python decorator
299305
((fn ^{:decorators [add-5-decorator]} seven [] 7))
300306
;; => 12
301307
302-
;;; Decorators with arguments, and order of application
308+
;;; Decorators with arguments, and order of application (right to left)
303309
;;
304310
;; example decorator
305311
(defn mult-x-decorator
@@ -325,11 +331,6 @@ These decorators are applied from right to left, similar to how Python decorator
325331
(asyncio/run (six))
326332
;; => 13
327333
328-
.. note::
329-
330-
Users wishing to apply decorators to functions are not limited to using ``:decorators`` metadata.
331-
The ``:decorators`` feature is provided primarily to simplify porting Python code to Basilisp.
332-
In Python, decorators are syntactic sugar for functions which return functions, but given the rich library of tools provided for composing functions and the ease of defining anonymous functions in Basilisp, the use of ``:decorators`` is not typically necessary in standard Basilisp code.
333334
.. _arithmetic_division:
334335

335336
Arithmetic Division

src/basilisp/core.lpy

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6004,6 +6004,12 @@
60046004
decorators and the ``comp`` function, decorators are applied to the
60056005
generated function from right to left.
60066006

6007+
.. note::
6008+
6009+
The ``name`` metadata (i.e., ``(fn ^{...} <name> ...)``) takes
6010+
precedence over the ``form`` metadata (i.e., ``^{...} (fn <name?> ...)``)
6011+
when both specify the same key.
6012+
60076013
Function argument vectors support sequential and associative :ref:`destructuring` .
60086014

60096015
See :lpy:form:`fn` for more details."

tests/basilisp/test_core_macros.lpy

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,30 @@
88
(testing "decorators"
99
(testing "in form meta"
1010
(let [add-5% #(fn [] (+ (%) 5))
11-
f1 ^{:decorators [add-5%]} (fn [] 7)]
11+
f1 ^{:decorators [add-5%]} (fn [] 7)]
1212
(is (= 12 (f1)))))
1313

1414
(testing "in fn name meta"
1515
(let [add-5% #(fn [] (+ (%) 5))
16-
f2 (fn ^{:decorators [add-5%]} f2 [] 13)]
16+
f2 (fn ^{:decorators [add-5%]} f2 [] 13)]
1717
(is (= 18 (f2)))))
1818

19+
(testing "in both form and name meta"
20+
(let [add-2% #(fn [] (+ (%) 2))
21+
add-7% #(fn [] (+ (%) 7))
22+
f3 ^{:decorators [add-2%]} (fn ^{:decorators [add-7%]} f3 [] 20)]
23+
(is (= 27 (f3)))))
24+
1925
(testing "with single arg"
2026
(let [add-x% (fn [x] #(fn [] (+ (%) x)))
21-
f3 (fn ^{:decorators [(add-x% 10)]} f3 [] 7)]
22-
(is (= 17 (f3)))))
27+
f4 (fn ^{:decorators [(add-x% 10)]} f4 [] 7)]
28+
(is (= 17 (f4)))))
2329

2430
(testing "order"
25-
(let [add-5% #(fn [] (+ (%) 5))
31+
(let [add-5% #(fn [] (+ (%) 5))
2632
mult-x% (fn [x] #(fn [] (* (%) x)))
27-
fvar (defn f4 {:decorators [add-5% (mult-x% -1)]} [] 9)]
28-
(is (= -4 (f4)))))))
33+
f5 ^{:decorators [add-5% (mult-x% -1)]} (fn [] 9)]
34+
(is (= -4 (f5)))))))
2935

3036
(deftest defn-test
3137
(testing "single arity defn"

0 commit comments

Comments
 (0)