{"id":13760341,"url":"https://github.com/jdevuyst/fletching-macros","last_synced_at":"2025-08-21T02:05:13.787Z","repository":{"id":62432671,"uuid":"28740149","full_name":"jdevuyst/fletching-macros","owner":"jdevuyst","description":"Clojure macros that complement the clojure.core threading (arrow) macros","archived":false,"fork":false,"pushed_at":"2020-04-19T13:26:40.000Z","size":12,"stargazers_count":34,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-17T00:48:37.793Z","etag":null,"topics":["clojure","clojure-library","clojure-macros","macros"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdevuyst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-03T09:43:35.000Z","updated_at":"2024-05-31T07:57:19.000Z","dependencies_parsed_at":"2022-11-01T21:15:29.704Z","dependency_job_id":null,"html_url":"https://github.com/jdevuyst/fletching-macros","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jdevuyst/fletching-macros","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdevuyst%2Ffletching-macros","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdevuyst%2Ffletching-macros/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdevuyst%2Ffletching-macros/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdevuyst%2Ffletching-macros/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdevuyst","download_url":"https://codeload.github.com/jdevuyst/fletching-macros/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdevuyst%2Ffletching-macros/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271260198,"owners_count":24728526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-20T02:00:09.606Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","clojure-library","clojure-macros","macros"],"created_at":"2024-08-03T13:01:08.238Z","updated_at":"2025-08-21T02:05:13.748Z","avatar_url":"https://github.com/jdevuyst.png","language":"Clojure","funding_links":[],"categories":["Clojure"],"sub_categories":[],"readme":"# Fletching macros\n\nA collection of Clojure macros that complement the `clojure.core` threading macros `-\u003e` and `-\u003e\u003e`.\n\n## Setup\n\nTo start, create a [Leiningen](http://leiningen.org) project and add the following dependency to `project.clj`:\n\n![Clojars Project](https://clojars.org/fletching-macros/latest-version.svg)\n\nNext, load the macros as follows:\n\n```clojure\n(require '[fletching.macros :refer :all])\n```\n\n## `\u003e\u003e`\n\n\u003e The macro `\u003e\u003e` removes itself from the head of the enclosing S-expression, and then moves the second form in the remaining expression to the end of the expression.\n\nIntended to be used within `-\u003e` to switch to `-\u003e\u003e` conventions.\n\n```clojure\n(-\u003e [[1 2 3] [3 4 5]]\n    (nth 1)\n    (-\u003e\u003e (map -))\n    (nth 1))\n;=\u003e -4\n```\n\nThis can be rewritten as\n\n```clojure\n(-\u003e [[1 2 3] [3 4 5]]\n    (nth 1)\n    (\u003e\u003e map -)\n    (nth 1))\n;=\u003e -4\n```\n\n## `\u003c\u003c`\n\n\u003e The macro `\u003c\u003c` removes itself from the head of the enclosing S-expression, and then moves the last form in the expression to the second position.\n\nThis macro addresses the problem of nesting `-\u003e` within `-\u003e\u003e`.\n\nWorking around this composition problem using `clojure.core` macros was already possible, but not always very elegant. You might have been writing code like this:\n\n```clojure\n(-\u003e (-\u003e\u003e [-1 -2 -3 -4 -5]\n         (map -)\n         (filter even?))\n    last\n    range\n    rest\n    (-\u003e\u003e (reduce *)))\n;=\u003e 6\n```\n\nOr like this:\n\n```clojure\n(as-\u003e [-1 -2 -3 -4 -5] x\n      (map - x)\n      (filter even? x)\n      (-\u003e x last range rest)\n      (reduce * x))\n;=\u003e 6\n```\n\nNow you can write this:\n\n```clojure\n(-\u003e\u003e [-1 -2 -3 -4 -5]\n     (map -)\n     (filter even?)\n     (\u003c\u003c -\u003e last range rest)\n     (reduce *))\n;=\u003e 6\n```\n\nOf course, `\u003c\u003c` is also useful in one-off situations:\n\n```clojure\n(-\u003e\u003e [1 2 3 4 5]\n     (map -)\n     (\u003c\u003c nth 2)\n     (/ 6))\n;=\u003e -2\n```\n\n## `?\u003e`, `\u003c?`\n\n\u003e The macros `?\u003e` and `\u003c?` remove themselves from the head of the enclosing S-expression, and then remove the second (`?\u003e`) or last (`\u003c?`) form in the remaining expression and bind it to `?`.\n\nThese macros are useful when you're composing functions using `-\u003e` or `-\u003e\u003e` and you find yourself needing a little bit more flexibility for some of the threaded expressions.\n\n```clojure\n(-\u003e\u003e [1 2 3 4 5]\n     (take 3)\n     (reduce *)\n     (\u003c? str ? \" is \" (if (even? ?) \"even\" \"odd\"))\n     (\u003c? do [? ?]))\n;=\u003e [\"6 is even\" \"6 is even\"]\n```\n\n## `\u003e\u003c`\n\n\u003e The macro `\u003e\u003c` removes itself from the head of the enclosing S-expression.\n\nThis macro is useful when you want to thread functions (as opposed to function arguments):\n\n```clojure\n(-\u003e [+ - * /]\n    (nth 2)\n    (\u003e\u003c 3 4)\n    inc)\n;=\u003e 13\n```\n\nEquivalently,\n\n```clojure\n(-\u003e\u003e [+ - * /]\n     (drop 2)\n     first\n     (\u003c\u003c \u003e\u003c 3 4)\n     inc)\n;=\u003e 13\n```\n\n## `\u003cfn`, `\u003c\u0026fn`\n\n\u003e The macros `\u003cfn` and `\u003c\u0026fn` remove themselves from the head of the enclosing S-expression, and then insert a variable in the second position of the remaining expression. Finally, the expression is transformed into a 1-ary (`\u003cfn`) or variadic (`\u003c\u0026fn`) lambda, which binds the variable.\n\n`\u003cfn` and `\u003c\u0026fn` can be used for defining functions in a [point-free style](https://en.wikipedia.org/wiki/Point-free_programming):\n\n```clojure\n(def f (\u003cfn -\u003e\u003e (map -)\n                (filter even?)\n                (reduce *)))\n(f [2 4 5 6])\n;=\u003e -48\n```\n\n`\u003c\u0026fn` is like `\u003cfn` but takes a variable number of arguments, which it threads into the expression as a sequence.\n\n```clojure\n(def g (\u003c\u0026fn -\u003e\u003e (map -)\n                 (filter even?)\n                 (reduce *)))\n(g 2 4 5 6)\n;=\u003e -48\n```\n\n## License\n\nCopyright © 2015 Jonas De Vuyst\n\nDistributed under the Eclipse Public License either version 1.0 or (at your option) any later version.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdevuyst%2Ffletching-macros","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdevuyst%2Ffletching-macros","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdevuyst%2Ffletching-macros/lists"}