{"id":20665701,"url":"https://github.com/gseitz/lensed","last_synced_at":"2025-07-14T07:38:42.027Z","repository":{"id":137509723,"uuid":"2055989","full_name":"gseitz/Lensed","owner":"gseitz","description":"in your case","archived":false,"fork":false,"pushed_at":"2012-04-10T19:03:51.000Z","size":139,"stargazers_count":62,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-04-19T19:08:28.689Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","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/gseitz.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":"2011-07-15T23:05:52.000Z","updated_at":"2022-06-27T20:33:23.000Z","dependencies_parsed_at":"2023-03-13T10:56:38.989Z","dependency_job_id":null,"html_url":"https://github.com/gseitz/Lensed","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gseitz/Lensed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gseitz%2FLensed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gseitz%2FLensed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gseitz%2FLensed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gseitz%2FLensed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gseitz","download_url":"https://codeload.github.com/gseitz/Lensed/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gseitz%2FLensed/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265257503,"owners_count":23735744,"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-11-16T19:33:23.240Z","updated_at":"2025-07-14T07:38:41.992Z","avatar_url":"https://github.com/gseitz.png","language":"Scala","readme":"Description\n-----------\nScala compiler plugin that generates `scalaz.Lens`es in companion objects for case class fields.\n\nDisclaimer\n----------\nThis compiler plugin is in a **VERY** early stage.\n\n**USE AT YOUR OWN RISK**\n\nFeatures\n--------\n**Completed:**\n\n + Add `def FIELD_NAME: scalaz.Lens[CLASS_NAME, FIELD_TYPE]` to the companion object for every case class field\n + Support `case class`es with type parameters\n + Implement Jason's idea for automagically composing lenses: http://groups.google.com/group/scalaz/msg/c89c41c3dbecb16c\n\n\n**Todo:**\n\n + Cache lenses in a `val` and add `asInstanceOf` casts to the `def`'s body.\n\nQuickstart\n----------\n\n    git clone https://github.com/gseitz/Lensed.git\n    cd Lensed\n    sbt \"project usage\" console\n\nThe last line compiles the projects in this order `annotation`, `plugin` (package), `testCaseClasses`, `usage` and presents you with a scala REPL ready for playing around:\n\n    import lensed.test.Persons._\n\nNow you can play around with some [predefined persons](examples/usage/src/main/scala/lensed/test/Persons.scala).\n\n\n\nRestrictions\n------------\nBecause of certain restrictions for compiler plugins (specifically, not being able to run between namer and typer phase),\nit is not possible to use the created lenses in the same compilation pass (read module, project, ...).\n\nThe obvious workaround is to put all `case class`es for which you want lenses to be generated into a separate project/submodule\nand have other projects depend on it. The compiler plugin only needs to be active for the project with the case classes.\n\nCaveats\n-------\nBecause IDEA uses its own parser for scala code, it doesn't know about the generated lenses and will mark the code with errors.\n\nExample\n-------\n\nProject A\n\n        case class Person(name: String, address: Address)\n        case class Address(city: String)\n\nThe following code will be generated:\n\n        object Person {\n          def name: Lens[Person, String] = Lens(_.name, (p, n) =\u003e p.copy(name = n))\n          def address: Lens[Person, Address] = Lens(_.address, (p, a) =\u003e p.copy(address = a))\n\n          class PersonW[A](l: Lens[A, Person]) {\n            def name: Lens[A, String] = l andThen Person.name\n            def address: Lens[A, Address] = l andThen Person.address\n          }\n\n          implicit def lens2personW[A](l: Lens[A, Person]): PersonW[A] = new PersonW(l)\n        }\n\n        object Address {\n          def city: Lens[Address, String] = Lens(_.city, (p, s) =\u003e p.copy(city = s))\n\n          class AddressW[A](l: Lens[A, Address]) {\n            def city: Lens[A, String] = l andThen Address.city\n          }\n\n          implicit def lens2addressW[A](l: Lens[A, Address]): AddressW[A] = new AddressW(l)\n        }\n\nUsage Project B\n\n        val yankee = Person(\"John\", Address(\"NYC\"))\n        val mounty = Person.address.city.set(yankee, \"Montreal\")\n        Person.address.city.get(mounty) // == \"Montreal\"\n        val cityLens: scalaz.Lens[Person, String] = Person.address.city\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgseitz%2Flensed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgseitz%2Flensed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgseitz%2Flensed/lists"}