{"id":15394252,"url":"https://github.com/xyproto/rangetype","last_synced_at":"2026-04-27T21:31:58.484Z","repository":{"id":57520030,"uuid":"112206803","full_name":"xyproto/rangetype","owner":"xyproto","description":":1234: Mini-language/DSL for defining and dealing with ranges of numbers","archived":false,"fork":false,"pushed_at":"2018-09-17T16:09:20.000Z","size":720,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-27T23:43:57.129Z","etag":null,"topics":["ada","dsl","foreach","go","mini-language","ranges"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xyproto.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":"2017-11-27T14:32:19.000Z","updated_at":"2018-09-17T16:09:21.000Z","dependencies_parsed_at":"2022-09-05T12:01:32.508Z","dependency_job_id":null,"html_url":"https://github.com/xyproto/rangetype","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xyproto/rangetype","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyproto%2Frangetype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyproto%2Frangetype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyproto%2Frangetype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyproto%2Frangetype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xyproto","download_url":"https://codeload.github.com/xyproto/rangetype/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyproto%2Frangetype/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32356598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T20:07:02.737Z","status":"ssl_error","status_checked_at":"2026-04-27T20:07:00.910Z","response_time":128,"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":["ada","dsl","foreach","go","mini-language","ranges"],"created_at":"2024-10-01T15:22:48.518Z","updated_at":"2026-04-27T21:31:58.467Z","avatar_url":"https://github.com/xyproto.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rangetype\n\n[![Build Status](https://travis-ci.org/xyproto/rangetype.svg?branch=master)](https://travis-ci.org/xyproto/rangetype) [![GoDoc](https://godoc.org/github.com/xyproto/rangetype?status.svg)](http://godoc.org/github.com/xyproto/rangetype) [![License](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/xyproto/rangetype/master/LICENSE) [![Report Card](https://img.shields.io/badge/go_report-A+-brightgreen.svg?style=flat)](http://goreportcard.com/report/xyproto/rangetype)\n\nA mini-language for defining numeric types by defining ranges.\n\nThe idea is to provide a DSL for defining and validating numeric types for implementations of programming languages.\n\nIt can also be used for iterating over ranges, generating lists of numbers or slicing a given slice (like slices in Python).\n\n## ForEach\n\nLooping over a range can be done by providing a function that takes a `float64`:\n\n```go\nr.New(\"1..10\").ForEach(func(x float64) {\n\tfmt.Println(int(x))\n})\n```\n\n## Join\n\nCollecting integers to a comma separated string can be done with `Join`:\n\n```go\nr.New(\"1..10\").Join(\", \", 0)\n```\n\nOr for floats, with 2 digits after the period, separated by semicolons:\n\n```go\nr.New(\"1..3 step 0.5\").Join(\";\", 2)\n```\n\n## Syntax\n\nExpressions can optionally start with:\n\n* `[` for including the first value in the range, or\n* `(` for excluding the first value in the range\n\nAnd can end with:\n\n* `]` for including the last value in the range, or\n* `)` for excluding the last value in the range\n\nNumbers can be suffixed by:\n\n* `~` for subtracting 1 from the preceding number. Any number of `~` is possible.\n\nThe ranges can be Python-style:\n\n`[0:10]`\n\nPython-style with a step:\n\n`[1:20:-1]`\n\nRuby-style:\n\n`1..10`\n\nRuby-style with a step:\n\n`1..10 step 2`\n\nMath-style:\n\n`[1,5)`\n\nMath-style with a step:\n\n`[1,5) step 2`\n\nMath-style with negative steps:\n\n`(5,1] step -0.1`\n\nHere's an expression for specifying the range for a 16-bit unsigned integer:\n\n`0..65535`\n\nThis can also be defined by dropping the initial `0` and using `~` for `-1`:\n\n`..65536~`\n\nThis can be made clearer (when defining many numbers of many bit-sizes) by using `2**16` instead of `65536`:\n\n`..2**16~`\n\nThis can be used for validating if a given number fits a 16-bit unsigned type:\n\n```go\nIntType := r.New(\"..2**16~\")     // from 0 up to and including 65536-1\nIntType.Valid(42)              // true\n```\n\n## Examples\n\nAn int with a range from 1 to 3 that includes both 1, 2 and 3:\n\n`1,3`\n\nA float with a range from 1 to 3 that includes 1.0, 1.1 etc up to 3.0:\n\n`1,3 step 0.1`\n\nInclusivity is specified with square brackets:\n\n`[1,3]`\n\nExclusivity is specified with parenthesis:\n\n`(1,3)`\n\nRanges inspired by Ruby also work:\n\n`1..3`\n\nThese are inclusive, unless parenthesis are used.\n\nRuby-style range which will exclude `1` and `3` and only keep `2`:\n\n`(1..3)`\n\nPython style ranges are also supported, where the start value is inclusive and the end value is exclusive:\n\n`1:3`\n\nAdding square brackets makes the range inclusive:\n\n`[1:3]`\n\nBrackets and parenthesis does not have to be balanced. This works too:\n\n`1:3]`\n\nAdding an iteration step is also possible:\n\n`1..5 step 2`\n\nThis is a range with the numbers `1`, `3` and `5`.\n\nThe Python-style syntax also supports steps:\n\n`[3:1:-1]`\n\nThis is `3`, `2`, `1`.\n\nSteps does not have to be integers:\n\n`[3:1:-0.1]`\n\nThis steps from 3 (inclusive) down to 1 (inclusive) in step sizes of 0.1.\n\n\n## More Examples\n\n### Defining a SmallInt type and checking if a given number is valid\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tr \"github.com/xyproto/rangetype\"\n)\n\nfunc main() {\n\t// Define a new type that can hold numbers from 0 up to and including 99\n\tSmallInt := r.New(\"0..99\")\n\n\t// Another way to define a number type from 0 up to and excluding 100\n\t//SmallInt := r.New(\"[0,100)\")\n\n\t// Another way to define a number type from 0 up to and excluding 100\n\t//SmallInt := r.New(\"..10**2~\")\n\n\t// Is 42 a valid SmallInt?\n\tfmt.Println(\"0 is a valid SmallInt value:\", SmallInt.Valid(0))\n\tfmt.Println(\"2 is a valid SmallInt value:\", SmallInt.Valid(2))\n\tfmt.Println(\"-1 is a valid SmallInt value:\", SmallInt.Valid(-1))\n\tfmt.Println(\"99 is a valid SmallInt value:\", SmallInt.Valid(99))\n\tfmt.Println(\"100 is a valid SmallInt value:\", SmallInt.Valid(100))\n\n\t// How many integers are there room for?\n\tfmt.Printf(\"SmallInt can hold %d different numbers.\\n\", SmallInt.Len())\n\tfmt.Printf(\"Storage required for SmallInt: a %d-bit int\\n\", SmallInt.Bits())\n\n\t// All possible SmallInt values, comma separated:\n\tfmt.Println(\"All possible values for SmallInt:\\n\" + SmallInt.Join(\",\", 0))\n}\n```\n\n## Example 2\n\n### Slicing slices and looping with the ForEach method\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tr \"github.com/xyproto/rangetype\"\n)\n\nfunc main() {\n\t// Outputs 1 to 10, with 0 digits after \".\"\n\tfmt.Println(r.New(\"1..10\").Join(\", \", 0))\n\n\t// Outputs 2 and 4\n\tfor _, x := range r.Slice([]float64{1.0, 2.0, 3.0, 4.0}, \"1..3 step 2\") {\n\t\tfmt.Print(x, \" \")\n\t}\n\tfmt.Println()\n\n\t// Also outputs 2 and 4\n\tr.New(\"(0:6:2)\").ForEach(func(x float64) {\n\t\tfmt.Print(x, \" \")\n\t})\n\tfmt.Println()\n}\n```\n\nThere are more examples in the `range_test.go` file.\n\n## Features and Limitations\n\n* Can handle very large ranges without storing the actual numbers in the ranges, but iterating over large ranges may be slow.\n* Only `**` and `~` are supported for manipulating numbers in the range expressions.\n* It's not a general language, it's only a DSL for expressing ranges of integers or floating point numbers, with an optional step size.\n\n## Error Handling\n\n* `New2` and `Slice2` will return both a value and an error (if the expression failed to evaluate) and are the recommended functions to use.\n* `New` and `Slice` are fine to use for expressions that are already known to evaluate, but may panic if there are errors in the given expression.\n\n## General Info\n\n* License: MIT\n* Version: 0.1\n* Author: Alexander F Rødseth \u0026lt;xyproto@archlinux.org\u0026gt;\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxyproto%2Frangetype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxyproto%2Frangetype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxyproto%2Frangetype/lists"}