├── .gitignore ├── project.clj ├── Readme.md ├── src └── cljos │ └── core.clj └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml 3 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject cljos "1.3.0-SNAPSHOT" 2 | :description "CljOS - A simple, dynamic, single-inheritance OOP system in Clojure" 3 | :url "http://github.com/divs1210/cljos" 4 | :dependencies [[org.clojure/clojure "1.6.0"]]) 5 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## Clojure Object System 2 | ------------------------ 3 | ### A simple, thread-safe, single-inheritance OOP system in Clojure 4 | Leiningen - `[cljos "1.3.0-SNAPSHOT"]` 5 | 6 | #### Why this heresy? 7 | Clojure is a brilliant functional language, and it would be best to use it as such, but when you just *have* to write OO code and don't want to give up other benefits that Clojure provides, CljOS might prove to be pretty useful. To read a more detailed write-up, go [here](http://pizzaforthought.blogspot.in/2014/12/cljos-objectifying-clojure.html). 8 | 9 | #### Usage 10 | Here's a Stack implemented in CljOS: 11 | 12 | ```clojure 13 | (defclass 14 | {:seq '(), :size 0} 15 | 16 | {:init (fn [this size] 17 | (this :set :size size)) 18 | 19 | :push (fn [this x] 20 | (if (< (this :seq count) (this :size)) 21 | (this :setf :seq conj x) 22 | (throw (Exception. "Stack full!")))) 23 | 24 | :pop (fn [this] 25 | (if (> (this :seq count) 0) 26 | (let [x (this :seq first)] 27 | (this :setf :seq pop) 28 | x) 29 | (throw (Exception. "Stack empty!"))))}) 30 | ``` 31 | 32 | which can be used in the following manner: 33 | ```clojure 34 | (def s (new+ 3)) 35 | (s :state) ;=> {:seq (), :size 3} 36 | (s :push 1) ;=> {:seq (1), :size 3} 37 | (s :push 2) ;=> {:seq (2 1), :size 3} 38 | (s :push 3) ;=> {:seq (3 2 1), :size 3} 39 | (s :pop) ;=> 3 40 | (s :state) ;=> {:seq (2 1), :size 3} 41 | ``` 42 | 43 | though it would be better to use the `doto+` macro: 44 | ```clojure 45 | (doto+ (new+ 3) 46 | (:push 1) 47 | (:push 2) 48 | (:push 3) 49 | :pop :state) ;=> {:seq (2 1), :size 3} 50 | ``` 51 | 52 | ##### Note 53 | * `:setf` stands for 'set with fn' and updates the given var. 54 | * `:state` can be used to get the object in the form of a Clojure data structure. No serialization required! 55 | * `:swap` works like `swap!`, and updates the `:state`. 56 | * `:type` gets the name of the class of the object. 57 | * `:super` can be used to access the super-class's methods, including `:init`. 58 | * All objects are automatically thread-safe! 59 | 60 | #### License 61 | (C) Divyansh Prakash. CljOS is released under the EPL 1.0 license. 62 | -------------------------------------------------------------------------------- /src/cljos/core.clj: -------------------------------------------------------------------------------- 1 | (ns cljos.core) 2 | 3 | ;-----The 'class' data structre------------------- 4 | (defn make-class 5 | [type extends vars methods] 6 | {:vars (or (into (extends :vars) vars) {}) 7 | :fns (or (into (extends :fns ) methods) {}) 8 | :type type 9 | :super extends}) 10 | 11 | (defmacro defclass 12 | "Every CljOS class should extend another. 13 | Extend if none other is applicable." 14 | [name extends vars methods] 15 | `(def ~name 16 | (~make-class (quote ~name) 17 | ~extends 18 | ~vars ~methods))) 19 | 20 | ;-----Bootstrapping the CljOS base class---------- 21 | (def 22 | {:vars {} 23 | :fns {:init (fn [_])} 24 | :type ' 25 | :super nil}) 26 | 27 | (defclass {} {}) 28 | 29 | ;-----Utility fn(s) and macro(s)------------------ 30 | (defn of-class? 31 | "Returns true if obj is a hash-map with all and only 32 | the keys required for it to qualify as an object of 33 | the given CljOS class." 34 | [obj class-name] 35 | (= (set (keys (class-name :vars))) 36 | (set (keys obj)))) 37 | 38 | (defmacro doto+ 39 | "Like \"doto\", but for CljOS objects. 40 | Returns the value of the last expression." 41 | [x & forms] 42 | (let [gx (gensym)] 43 | `(let [~gx ~x] 44 | ~@(map (fn [f] 45 | (if (seq? f) 46 | `(~gx ~(first f) ~@(next f)) 47 | `(~gx ~f))) 48 | forms)))) 49 | 50 | ;-----Object instantiation------------------------ 51 | (defn new+ 52 | "Instantiates a new CljOS object, which is a closure 53 | with access to a set of methods, and *mutable* state." 54 | [class-name & args] 55 | (let [state (atom (class-name :vars)) 56 | fns (class-name :fns) 57 | this (fn this* [method & argv] 58 | (case method 59 | ;special keywords 60 | :type (class-name :type) 61 | :state @state 62 | :super (let [[method & args] argv] 63 | (apply (-> class-name :super :fns method) 64 | this* args)) 65 | :set (let [[var val] argv] 66 | (if (contains? @state var) 67 | (swap! state assoc var val) 68 | (throw (Exception. (str var " undefined in class " (class-name :type) "."))))) 69 | :setf (let [[var f & args] argv] 70 | (this* :set var 71 | (apply f (@state var) args))) 72 | :swap (let [[f & args] argv 73 | new-val (apply f @state args)] 74 | (if (of-class? new-val class-name) 75 | (swap! state (fn [_] new-val)) 76 | (throw (Exception. (str new-val " is not a valid object of class " (class-name :type) "."))))) 77 | ;first check if it's a method 78 | ;if not, treat it as a property 79 | (if (contains? fns method) 80 | (apply (fns method) this* argv) 81 | (if (contains? @state method) 82 | (let [var (@state method) 83 | [f & args] argv] 84 | (if (nil? f) var 85 | (apply f var args))) 86 | (throw (Exception. (str method " undefined in class " (class-name :type) ".")))))))] 87 | ;call constructor, and return the object 88 | (apply (fns :init) this args) 89 | this)) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | --------------------------------------------------------------------------------