{"id":14068256,"url":"https://github.com/moodymudskipper/typed","last_synced_at":"2025-04-07T06:06:14.937Z","repository":{"id":53519218,"uuid":"304487343","full_name":"moodymudskipper/typed","owner":"moodymudskipper","description":"Support Types for Variables, Arguments, and Return Values","archived":false,"fork":false,"pushed_at":"2024-01-24T01:32:48.000Z","size":356,"stargazers_count":155,"open_issues_count":15,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-24T20:03:28.480Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moodymudskipper.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-16T01:25:14.000Z","updated_at":"2024-06-10T08:49:22.866Z","dependencies_parsed_at":"2023-12-02T11:22:34.117Z","dependency_job_id":"afc21fd0-79d5-4327-bad0-37aaaee237a9","html_url":"https://github.com/moodymudskipper/typed","commit_stats":{"total_commits":127,"total_committers":7,"mean_commits":"18.142857142857142","dds":"0.20472440944881887","last_synced_commit":"76183d3a285fa963e6d9a4ba4826c97ffb66dea5"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodymudskipper%2Ftyped","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodymudskipper%2Ftyped/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodymudskipper%2Ftyped/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodymudskipper%2Ftyped/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moodymudskipper","download_url":"https://codeload.github.com/moodymudskipper/typed/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601447,"owners_count":20964864,"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","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":[],"created_at":"2024-08-13T07:06:03.276Z","updated_at":"2025-04-07T06:06:14.908Z","avatar_url":"https://github.com/moodymudskipper.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- badges: start --\u003e\n[![Travis build status](https://travis-ci.com/moodymudskipper/typed.svg?branch=iteration2)](https://travis-ci.com/moodymudskipper/typed)\n[![Codecov test coverage](https://codecov.io/gh/moodymudskipper/typed/branch/master/graph/badge.svg)](https://codecov.io/gh/moodymudskipper/typed?branch=master)\n\u003c!-- badges: end --\u003e\n\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  error = TRUE,\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n# typed \u003cimg src='man/figures/logo.png' align=\"right\" height=\"139\" /\u003e\n\n*{typed}* implements a type system for R, it has 3 main features:\n\n* set variable types in a script or the body of a function, so they can't be\n  assigned illegal values\n* set argument types in a function definition\n* set return type of a function\n\nThe user can define their own types, or leverage assertions from\nother packages.\n\nUnder the hood variable types use active bindings, so once a variable is restricted\nby an assertion, it cannot be modified in a way that would\nnot satisfy it.\n\n## Installation\n\nInstall CRAN version with:\n\n``` r\ninstall.packages(\"typed\")\n```\n\nor development version with :\n\n``` r\nremotes::install_github(\"moodymudskipper/typed\")\n```\n\nAnd attach with : \n\n```{r}\n# masking warning about overriding `?`\nlibrary(typed, warn.conflicts = FALSE) \n```\n\n## Set variable type\n\n### Question mark notation and `declare`\n\nHere are examples on how we would set types \n\n```{r}\nCharacter() ? x # restrict x to \"character\" type\nx \u003c- \"a\"\nx\n\nInteger(3) ? y \u003c- 1:3 # restrict y to \"integer\" type of length 3\ny\n```\n\nWe cannot assign values of the wrong type to `x` and `y` anymore.\n\n```{r}\nx \u003c- 2\n\ny \u003c- 4:5\n```\n\nBut the right type will work.\n\n```{r}\nx \u003c- c(\"b\", \"c\")\n\ny \u003c- c(1L, 10L, 100L)\n```\n\n`declare` is a strict equivalent, slightly more efficient, which looks like `base::assign`.\n\n```{r}\ndeclare(\"x\", Character())\nx \u003c- \"a\"\nx\n\ndeclare(\"y\", Integer(3), 1:3)\ny\n```\n\n### Assertion factories and assertions\n\n`Integer` and `Character` are function factories (functions that return functions),\nthus `Integer(3)` and `Character()` are functions.\n\nThe latter functions operate checks on a value and in case of success \nreturn this value, generally unmodified. For instance :\n\n```{r}\nInteger(3)(1:2)\n\nCharacter()(3)\n```\n\nWe call `Integer(3)` and `Character()` assertions, and we call\n`Integer` and `Character` assertion factories (or just types, with then we must\nbe careful not to confuse them with atomic types returned by the `typeof` function).\n\nThe package contains many assertion factories (see `?assertion_factories`), \nthe main ones are: \n\n* `Any` (No default restriction)\n* `Logical`\n* `Integer`\n* `Double`\n* `Character`\n* `List`\n* `Environment`\n* `Factor`\n* `Matrix`\n* `Data.frame`\n* `Date`\n* `Time` (POSIXct)\n\n### Advanced type restriction using arguments\n\nAs we've seen with `Integer(3)`, passing arguments to a\nassertion factory restricts the type.\n\nFor instance `Integer` has arguments `length` `null_ok` and\n`...`. We already used `length`, `null_ok` is convenient to allow a default `NULL`\nvalue in addition to the `\"integer\"` type.\n\nThe arguments can differ between assertion factories, for instance `Data.frame`\nhas `nrow`, `ncol`, `each`, `null_ok` and `...`\n\n```{r}\nData.frame() ? x \u003c- iris\nData.frame(ncol = 2) ? x \u003c- iris\nData.frame(each = Double()) ? x \u003c- iris\n```\n\nIn the dots we can use arguments named as functions and with the value of\nthe expected result.\n\n```{r}\n# Integer has no anyNA arg but we can still use it because a function named\n# this way exists\nInteger(anyNA = FALSE) ? x \u003c- c(1L, 2L, NA)\n```\n\nUseful arguments might be for instance, `anyDuplicated = 0L`, `names = NULL`, \n`attributes = NULL`... Any available function can be used.\n\nThat makes assertion factories very flexible! If it is still not flexible enough,\nwe can provide arguments arguments named `...` to functional factories to add\na custom restriction, this is usually better done by defining a wrapper.\n\n```{r}\nCharacter(1, ... = \"`value` is not a fruit!\" ~ . %in% c(\"apple\", \"pear\", \"cherry\")) ? \n  x \u003c- \"potatoe\"\n```\n\nThis is often better done by defining a wrapper as shown below.\n\n### Constants\n\nTo define a constant, we just surround the variable by parentheses (think of \nthem as a protection)\n\n```{r}\nDouble() ? (x) \u003c- 1\nx \u003c- 2\n\n# defining a type is optional\n? (y) \u003c- 1\ny \u003c- 2\n```\n\n### Set a function's argument type\n\nWe can set argument types this way : \n\n\n```{r}\nadd \u003c- ? function (x= ? Double(), y= 1 ? Double()) {\n  x + y\n}\n```\n\nNote that we started the definition with a `?`, and that we gave a default to\n`y`, but not `x`. Note also the `=` sign next to `x`, necessary even when we\nhave no default value. If you forget it you'll have an error \"unexpected `?` in ...\".\n\nThis created the following function, by adding checks at the top of the\nbody\n\n```{r}\nadd\n```\n\nLet's test it by providing a right and wrong type.\n\n```{r}\nadd(2, 3)\nadd(2, 3L)\n```\n\nIf we want to restrict `x` and `y`  to the type \"integer\" in the rest of\nthe body, so they cannot be overwritten by character for instance,we can use\nthe `?+` notation :\n\n```{r}\nadd \u003c- ? function (x= ?+ Double(), y= 1 ?+ Double()) {\n  x + y\n}\n\nadd\n```\n\nWe see that it is translated into a `check_arg` call containing a `.bind = TRUE`\nargument.\n\n## Set a function's return type\n\nTo set a return type we use `?` before the function definition as in the previous section, \nbut we type an assertion on the left hand side.\n\n```{r}\nadd_or_subtract \u003c- Double() ? function (x, y, subtract = FALSE) {\n  if(subtract) return(x - y)\n  x + y\n}\nadd_or_subtract\n```\n\nWe see that the returned values have been wrapped inside `check_output` calls.\n\n# Use type in a package and define your own types\n\nSee `vignette(\"typed-in-packaged\", \"typed\")` or the Article section if you're\nbrowsing the pkgdown website.\n\n## Acknowledgements\n\nThis is inspired in good part by Jim Hester and Gabor Csardi's work and many\ngreat efforts on static typing, assertions, or annotations in R, in particular: \n\n* Gabor Csardy's [*argufy*](https://github.com/gaborcsardi/argufy)\n* Richie Cotton's [*assertive*](https://bitbucket.org/richierocks/assertive/)\n* Tony Fishettti's [*assertr*](https://github.com/tonyfischetti/assertr)\n* Hadley Wickham's [*assertthat*](https://github.com/hadley/assertthat)\n* Michel Lang's [*checkmate*](https://github.com/mllg/checkmate)\n* Joe Thorley's [*checkr*](https://github.com/poissonconsulting/checkr)\n* Joe Thorley's [*chk*](https://github.com/poissonconsulting/chk/)\n* Aviral Goel's [*contractr*](https://github.com/aviralg/contractr)\n* Stefan Bache's [*ensurer*](https://github.com/smbache/ensurer)\n* Brian Lee Yung Rowe's [*lambda.r*](https://github.com/zatonovo/lambda.r)\n* Kun Ren's [*rtype*](https://github.com/renkun-ken/rtype)\n* Duncan Temple Lang's [*TypeInfo*](https://bioconductor.org/packages/TypeInfo/)\n* Jim Hester's [*types*](https://github.com/jimhester/types)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoodymudskipper%2Ftyped","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoodymudskipper%2Ftyped","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoodymudskipper%2Ftyped/lists"}