{"id":27439630,"url":"https://github.com/subsetpark/smasher","last_synced_at":"2025-04-14T21:59:52.783Z","repository":{"id":23566067,"uuid":"26933783","full_name":"subsetpark/smasher","owner":"subsetpark","description":"Typed Message Passing for Python","archived":false,"fork":false,"pushed_at":"2014-12-10T04:17:23.000Z","size":356,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-06T13:49:55.319Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","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/subsetpark.png","metadata":{"files":{"readme":"README.md","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}},"created_at":"2014-11-20T21:56:20.000Z","updated_at":"2014-12-10T04:17:23.000Z","dependencies_parsed_at":"2022-08-22T01:50:45.665Z","dependency_job_id":null,"html_url":"https://github.com/subsetpark/smasher","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fsmasher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fsmasher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fsmasher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fsmasher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/subsetpark","download_url":"https://codeload.github.com/subsetpark/smasher/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248968751,"owners_count":21191158,"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":"2025-04-14T21:59:52.382Z","updated_at":"2025-04-14T21:59:52.775Z","avatar_url":"https://github.com/subsetpark.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"smasher\n=======\n\n## Typed Exception-Based Message Passing for Python\n\nAt some point in the recent past, I found myself enjoying the process of \ncreating my own exceptions for specific business logic needs at my Python \nday job. So, naturally, I thought: *what if you could use exceptions for\nall control flow in Python?*\n\n`smasher` applications have two main components: `Actor` objects that communicate with each other by way of raised exceptions, called `Atoms`, and the global `Atoms` namespace.\n\nLooking at an example, we see:\n\n```py\nclass SimpleGame(Actor):\n    atoms = ['Correct', 'Wrong', 'Win', 'KeepGoing', 'Done']\n```\n\n`Actor` classes declare their own atoms, which are instantiated as subclasses of the `Atom` exception class. Actors catch atoms using the `dispatch` decorator:\n\n```py\n@dispatch({('Wrong', 'ValueError', 'Again'): 'take_a_guess',\n           'Correct': 'correct',\n           'KeepGoing': 'play_a_game',\n           'Guess': ('evaluate', int)})\ndef take_a_guess(self):\n    self.server.get_guess()\n```\n\nHere we see that the main locus for control flow is the `take_a_guess` method. If any of the `Wrong`, `ValueError`, or `Again` exceptions are raised, we recurse; the `Correct` and `KeepGoing` atoms are routed to the appropriate methods; finally, we see that the `Guess` atom is expected to contain a single element, an int, which will be passed to the `evaluate` method. Atoms can also be dispatched to raw lambdas or even other atoms, though in practice it will usually suffice simply to catch the original signal further up.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubsetpark%2Fsmasher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsubsetpark%2Fsmasher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubsetpark%2Fsmasher/lists"}