From 99d049ac48cebd44769f7efab6d8fe89dd1afd41 Mon Sep 17 00:00:00 2001 From: ikappaki Date: Mon, 23 Dec 2024 21:45:14 +0000 Subject: [PATCH 1/2] follow up patch to fn :decorators support, minor doc and test update --- docs/pyinterop.rst | 13 +++++++------ src/basilisp/core.lpy | 4 ++++ tests/basilisp/test_core_macros.lpy | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/pyinterop.rst b/docs/pyinterop.rst index b511a67a..29d8ef18 100644 --- a/docs/pyinterop.rst +++ b/docs/pyinterop.rst @@ -267,6 +267,12 @@ Type hints may be applied to :lpy:form:`def` names, function arguments and retur Python Decorators ----------------- +.. note:: + + Users wishing to apply decorators to functions are not limited to using ``:decorators`` metadata. + This feature is provided primarily to simplify porting Python code to Basilisp. + 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. + Python decorators are functions that modify the behavior of other functions or methods. 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. @@ -299,7 +305,7 @@ These decorators are applied from right to left, similar to how Python decorator ((fn ^{:decorators [add-5-decorator]} seven [] 7)) ;; => 12 - ;;; Decorators with arguments, and order of application + ;;; Decorators with arguments, and order of application (right to left) ;; ;; example decorator (defn mult-x-decorator @@ -325,11 +331,6 @@ These decorators are applied from right to left, similar to how Python decorator (asyncio/run (six)) ;; => 13 -.. note:: - - Users wishing to apply decorators to functions are not limited to using ``:decorators`` metadata. - The ``:decorators`` feature is provided primarily to simplify porting Python code to Basilisp. - 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. .. _arithmetic_division: Arithmetic Division diff --git a/src/basilisp/core.lpy b/src/basilisp/core.lpy index 9a636840..e89ad129 100644 --- a/src/basilisp/core.lpy +++ b/src/basilisp/core.lpy @@ -6004,6 +6004,10 @@ decorators and the ``comp`` function, decorators are applied to the generated function from right to left. + Note: The `name` metadata (i.e., `(fn ^{...} ...)`) takes precedence + over the `form` metadata (i.e., `^{...} (fn ...)`) when both specify + the same key. + Function argument vectors support sequential and associative :ref:`destructuring` . See :lpy:form:`fn` for more details." diff --git a/tests/basilisp/test_core_macros.lpy b/tests/basilisp/test_core_macros.lpy index 884c75eb..a80ad352 100644 --- a/tests/basilisp/test_core_macros.lpy +++ b/tests/basilisp/test_core_macros.lpy @@ -8,24 +8,30 @@ (testing "decorators" (testing "in form meta" (let [add-5% #(fn [] (+ (%) 5)) - f1 ^{:decorators [add-5%]} (fn [] 7)] + f1 ^{:decorators [add-5%]} (fn [] 7)] (is (= 12 (f1))))) (testing "in fn name meta" (let [add-5% #(fn [] (+ (%) 5)) - f2 (fn ^{:decorators [add-5%]} f2 [] 13)] + f2 (fn ^{:decorators [add-5%]} f2 [] 13)] (is (= 18 (f2))))) + (testing "in both form and name meta" + (let [add-2% #(fn [] (+ (%) 2)) + add-7% #(fn [] (+ (%) 7)) + f3 ^{:decorators [add-2%]} (fn ^{:decorators [add-7%]} f3 [] 20)] + (is (= 27 (f3))))) + (testing "with single arg" (let [add-x% (fn [x] #(fn [] (+ (%) x))) - f3 (fn ^{:decorators [(add-x% 10)]} f3 [] 7)] - (is (= 17 (f3))))) + f4 (fn ^{:decorators [(add-x% 10)]} f4 [] 7)] + (is (= 17 (f4))))) (testing "order" - (let [add-5% #(fn [] (+ (%) 5)) + (let [add-5% #(fn [] (+ (%) 5)) mult-x% (fn [x] #(fn [] (* (%) x))) - fvar (defn f4 {:decorators [add-5% (mult-x% -1)]} [] 9)] - (is (= -4 (f4))))))) + f5 ^{:decorators [add-5% (mult-x% -1)]} (fn [] 9)] + (is (= -4 (f5))))))) (deftest defn-test (testing "single arity defn" From 94698cad344e73b705608036c634601b793af5ab Mon Sep 17 00:00:00 2001 From: ikappaki <34983288+ikappaki@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:15:17 +0000 Subject: [PATCH 2/2] Update src/basilisp/core.lpy Co-authored-by: Chris Rink --- src/basilisp/core.lpy | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/basilisp/core.lpy b/src/basilisp/core.lpy index e89ad129..303880db 100644 --- a/src/basilisp/core.lpy +++ b/src/basilisp/core.lpy @@ -6004,9 +6004,11 @@ decorators and the ``comp`` function, decorators are applied to the generated function from right to left. - Note: The `name` metadata (i.e., `(fn ^{...} ...)`) takes precedence - over the `form` metadata (i.e., `^{...} (fn ...)`) when both specify - the same key. + .. note:: + + The ``name`` metadata (i.e., ``(fn ^{...} ...)``) takes + precedence over the ``form`` metadata (i.e., ``^{...} (fn ...)``) + when both specify the same key. Function argument vectors support sequential and associative :ref:`destructuring` .