{"id":18860530,"url":"https://github.com/nteetor/tinsel","last_synced_at":"2026-03-11T00:03:59.063Z","repository":{"id":56937588,"uuid":"72219492","full_name":"nteetor/tinsel","owner":"nteetor","description":"Use Decorators to Transform Functions","archived":false,"fork":false,"pushed_at":"2017-09-18T13:32:27.000Z","size":129,"stargazers_count":21,"open_issues_count":11,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-09T22:26:13.061Z","etag":null,"topics":["decorators","function-decorator","r"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nteetor.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":"2016-10-28T15:30:33.000Z","updated_at":"2024-08-28T13:55:46.000Z","dependencies_parsed_at":"2022-08-21T07:20:39.856Z","dependency_job_id":null,"html_url":"https://github.com/nteetor/tinsel","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nteetor/tinsel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nteetor%2Ftinsel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nteetor%2Ftinsel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nteetor%2Ftinsel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nteetor%2Ftinsel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nteetor","download_url":"https://codeload.github.com/nteetor/tinsel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nteetor%2Ftinsel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30362732,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"ssl_error","status_checked_at":"2026-03-10T21:40:59.357Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["decorators","function-decorator","r"],"created_at":"2024-11-08T04:25:01.493Z","updated_at":"2026-03-11T00:03:59.006Z","avatar_url":"https://github.com/nteetor.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tinsel\n\nDecorating functions in R.\n\n![Travis-CI Build Status](https://travis-ci.org/nteetor/tinsel.svg?branch=master) [![codecov](https://codecov.io/gh/nteetor/tinsel/branch/master/graph/badge.svg)](https://codecov.io/gh/nteetor/tinsel) ![cran status](http://www.r-pkg.org/badges/version/tinsel)\n\n\nThe tinsel package adds function decorators to R using a special `#.` comment. \nDecorators are a means of transforming a function without needing to rewrite \nthe function. They allow for easy integration of new code onto existing code. These benefits\nare illustrated below with an example about object classes.\n\n### What are decorators all about?\n\nSay we develop a *Spaceship* class. In addition to our standard *Spaceship*\nclass, we also need a class for a spaceship with a hyperdrive. So we develop a \n*SpaceshipWithHyperdrive* class. Hoever, given all our spaceships we also need a\nmothership. So we develop a *MotherSpaceship*. But, what if the mothership also \nhas a hyperdrive? In this have to add two new classes, *MotherSpaceship* and \n*MotherSpaceshipWithHyperdrive*. While the situation is not unmanageable adding \na new class for each spaceship feature, or even for every couple of features, is\nless than ideal.\n\nInstead we can create a decorator for each new spaceship feature. Let's call \nthese decorators *HyperdriveSpaceshipDecorator* and *MotherSpaceshipDecorator*. \nThe *HyperdriveSpaceshipDecorator* takes the *Spaceship* class, with all the \n*Spaceship* methods, and adds hyperdrive-related methods. Thus, we are saved the\ntrouble of copying over the *Spaceship* methods to a new class as would have\nbeen necessary to create the *SpaceshipWithHyperdrive*, *MotherSpaceship*,\nand *MotherSpaceshipWithHyperdrive* classes.\n\n### R Decorators (and *your* decorators)\n\nLet's create a function `if_warning` which wraps a function `f` such that if `f(...)`\nwould generate a warning a default value is returned instead, otherwise `f(...)` is \nreturned.\n\n```R\nif_warning \u003c- function(f, default) {\n  function(...) {\n    tryCatch(\n      f(...),\n      warning = function(w) {\n        default\n      })\n  }\n}\n```\n\nNow let's transform the default `mean` function, so instead of generating a \nwarning the function returns `Inf`. Great!\n\n```R\nmean_inf \u003c- if_warning(mean, Inf)\n\n# give it a try!\nmean_inf(1:5)\nmean_inf(c(1, 'two', 3))\n```\n\nHere is where the special comment `#.` comes in. The above code can be \nrewritten as the following,\n\n```R\n#. if_warning(Inf)\nmean_inf \u003c- mean\n```\n\nThe special comment `#.` is used to denote a function decorator. In this \nexample, `#. if_warning` denotes `if_warning` as the decorator of the decoratee\n`mean`. `mean` is passed as the first argument to `if_warning` and `Inf`\nas the second argument. The result of transforming `mean` with `if_warning` is\nassigned to `mean_inf`.\n\nIn order to see the decorator annotation example in action, save the above code \nin a file, source the file using `source_decoratees`, and then call `mean_inf` \nonce more. (Gentle reminder, the output is expected to be the same)\n\n### Installing tinsel\n\ntinsel is now available on CRAN.\n\n```R\ninstall.packages('tinsel')\n```\n\nYou can install the latest version of tinsel using devtools (currently even with version 0.0.1 on CRAN).\n\n```R\n# install.packages('devtools')\ndevtools::install_github('nteetor/tinsel')\n```\n\nCheck out the `source_decoratees` function to get started. \n\n### RStudio Addin\n\nIf you are working in RStudio the tinsel package includes an addin for the core \nfunction `source_decoratees`. To bind the addin to a keyboard shortcut in\nRStudio navigate to **Tools** \u003e **Addins** \u003e **Browse Addins** \u003e **Keyboard \nShorcuts**. For more information about the keyboard shortcuts checkout the \nRStudio [support \npage](https://support.rstudio.com/hc/en-us/articles/206382178-Customizing-Keyboard-Shortcuts).\nIf you choose to setup a keyboard shortcut for the addin I recommend\n\u003ckbd\u003eAlt\u003c/kbd\u003e+\u003ckbd\u003eShift\u003c/kbd\u003e+\u003ckbd\u003eS\u003c/kbd\u003e since \n\u003ckbd\u003eCmd\u003c/kbd\u003e+\u003ckbd\u003eShift\u003c/kbd\u003e+\u003ckbd\u003eS\u003c/kbd\u003e (or \n\u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eShift\u003c/kbd\u003e+\u003ckbd\u003eS\u003c/kbd\u003e on Linux and Windows) is the source active file \nshortcut. The end result is you can quickly load your decorated functions like\nyou would source all functions from the active file.\n\n---\n\nCheers, Nate.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnteetor%2Ftinsel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnteetor%2Ftinsel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnteetor%2Ftinsel/lists"}