|
| 1 | + |
1 | 2 | * Design Notes
|
2 | 3 | ** Dynamic Typing
|
3 | 4 | Let's say we have a function like the invoke function (check out
|
4 |
| - clojure.lang.IFn) for function-like types, which takes a variable |
5 |
| - number of arguments whose types are not known at compile time. In |
6 |
| - Java, this looks like |
| 5 | + clojure.lang.IFn) for function-like types, that is meant to invoked on |
| 6 | + an certain number of arguments whose types are not known at compile time. |
| 7 | +#+BEGIN_SRC clojure |
| 8 | +;; Example of a 'function like type'; {}, an IFn that is not a function that can nontheless |
| 9 | +;; be invoked on arguments |
| 10 | +({:name "Cameron" |
| 11 | + :age 100} :name) => "Cameron" |
| 12 | +#+END_SRC |
7 | 13 |
|
| 14 | + In Java, this invoke function looks something like |
8 | 15 | #+BEGIN_SRC java
|
9 | 16 | public Object invoke(Object arg1,Object arg2 ...)
|
10 | 17 | #+END_SRC
|
|
16 | 23 | #+BEGIN_SRC rust
|
17 | 24 | fn invoke<'a>(arg1: &'a dyn Any, ..) -> &'a dyn Any
|
18 | 25 | #+END_SRC
|
19 |
| - |
20 |
| - (But, considering that really we want to be often returning a |
21 |
| - new value with invoke, and thus our 'reference', despite |
22 |
| - starting in the function, should be existing beyond the function |
23 |
| - itself, we'd more so probably need to return a proper pointer on |
24 |
| - the heap, perhaps a Box<dyn Any>. When I was experimenting with |
25 |
| - this approach, I ended up using a Rc<dyn Any>, which fit better |
26 |
| - with some other implementation details and was 'easier', but there |
27 |
| - was still a lot to explore there) |
28 |
| - |
29 | 26 | or
|
30 | 27 |
|
31 | 28 | 2. To have a wrapper ADT (enum) that knows all possible types ahead of time; ie, something like
|
|
41 | 38 | #+END_SRC
|
42 | 39 |
|
43 | 40 | For now, I have moved forward with #2, as there appear to be some
|
44 |
| - major issues one runs into with #1, although I am open to hearing |
45 |
| - from others wiser than I in Rust |
46 |
| -*** TODO Document problem with #1 |
47 |
| - |
| 41 | + major issues one runs into with #1, although, like with all decisions on |
| 42 | + this sheet, I am open to hearing from others wiser than I in Rust. |
| 43 | +*** TODO Document problem with #1 |
48 | 44 | ** Exceptions
|
49 | 45 | How best represent exceptions?
|
50 | 46 | *** Conditions
|
|
59 | 55 | There's a few things to think about here, for now let's just have
|
60 | 56 | erroneous situations flat out return a Condition type, and start
|
61 | 57 | adding more behavior when we get back to this.
|
62 |
| - |
63 | 58 | ** Keeping the codebase close
|
64 | 59 | Originally, at least ,the goal was to keep the Rust base as similar
|
65 | 60 | to the Java / C# codebase as possible for consistency, but now I am
|
|
72 | 67 | the IFn trait, which for now is keeping the IFn name. See notes at
|
73 | 68 | top of IFn for more info
|
74 | 69 |
|
| 70 | +*** 4/14/2020 Note |
| 71 | + One glitch in my thinking that didn't really compute when I wrote this |
| 72 | + is that the, say, Java version looks pretty straightforward underneath |
| 73 | + -- if you want a hashmap, for instance, its just implemented in Java -- |
| 74 | + but I am forgetting that, by virtue of the JVM, it is sort of |
| 75 | + automatically getting an efficient bytecode to evaluate to. Without |
| 76 | + that luxury, we likely do not want to just likewise implement things |
| 77 | + outright, we will likely also want to add an additional step where everything |
| 78 | + too perhaps compiles to a more efficient bytecode -- or we might |
| 79 | + implement some sort of JIT action. In the long run, I'd love for this |
| 80 | + to be like SBCL, although I imagine that might take a few decades |
75 | 81 | ** Explore more the idea of a clean rust FFI / interop, in the usual spirit of Clojure
|
76 | 82 | I get the impression that runtime reflection in Rust would be difficult if not downright
|
77 | 83 | impossible, so for now I would like to look into producing our interop functions at compile time
|
78 | 84 | (or rather, 'pre compile time'; parsing our rust files, producing the appropriate ClojureRS rust code bridging
|
79 | 85 | the two, and the compiling the entire project after)
|
80 | 86 |
|
81 |
| -** Clojure map comments |
82 |
| - For now, I decided to add some meta data to some of the Rust-Clojure functions as an actual map in the comment |
83 |
| - (ie, |
84 |
| -#+BEGIN_SRC rust |
85 |
| -/* |
86 |
| -{:clojure-fn "+"} |
87 |
| -*/ |
88 |
| -struct AddFn { |
89 |
| -} |
90 |
| -#+END_SRC |
91 |
| - I am not 100% I have a conscious reasoning yet, but I often like |
92 |
| - expressing data just as data, this is one of the draws of Clojure |
93 |
| - for me as it is. The map here is explicit, it is human readable, but |
94 |
| - also easily reflected read and manipulated by software. And it is |
95 |
| - expressed with the same, to-the-point language you can use to |
96 |
| - express any other information. |
| 87 | +*** 4/14/2020 Note |
| 88 | + At the very least, we are closer, as we have some intermediate Rust traits and types we can use to create |
| 89 | + Rust values that can live inside ClojureRS. Perhaps the next step might be some derive macros, |
| 90 | + and then generation itself might become a lot easier, as the bulk of it would be carried out |
| 91 | + from within Rust itself |
| 92 | +** TypeTag |
| 93 | + Put in separate file as Value or same? Let's keep it separate and see how its used as the program progresses |
| 94 | +** IFn Values |
| 95 | + If we notice, our Value enum, which just wraps all potential types (this is how we're implementing dynamic typing), has some 'types' that are not concretions but interfaces. And then it has some types that are more |
| 96 | + complicated yet, like Conditions (Conditions technically are a value with a type, but are they exactly |
| 97 | + returned in the same 'expression space', or aren't they sort of returned to this separate 'exception channel', |
| 98 | + and not to the environment where it was written but to a handler anywhere higher up awaiting it) |
| 99 | + |
| 100 | + Anyways, I just want to keep this in mind. Right now Value wraps *everything* in a flat sort of way, |
| 101 | + but they aren't all quite on the same 'level'. |
| 102 | + |
| 103 | +** Conditions |
| 104 | +Perhaps they could look like |
| 105 | +#+BEGIN_SRC clojure |
| 106 | +(defn div [x y] |
| 107 | + (restart-case |
| 108 | + (if (not= y 0) |
| 109 | + (/ x y) |
| 110 | + ;; Oh yeah this looks sexy |
| 111 | + (error :divide-by-zero {:message "Tried to divide by zero"})) |
| 112 | + (return-zero [] 0) |
| 113 | + (return-value [r] r) |
| 114 | + (div-new-vals [x y] (/ x y)) |
| 115 | + (div-new-denominator [v] (/ x v)))) |
| 116 | + |
| 117 | +(defn test-div-error |
| 118 | + (handler-bind |
| 119 | + :on-zero-denominator |
| 120 | + (fn [cond] |
| 121 | + (println (:message cond)) |
| 122 | + (invoke-restart :return-value 10)) |
97 | 123 |
|
98 |
| - Anyways, for now I am only listing the Var this function should |
99 |
| - correspond to, as all other information can be found on said Var, |
100 |
| - although if I later realize it helps to have this information on |
101 |
| - the Rust implementation of a function at a glance , I'm not against |
102 |
| - adding it there, even if its repeat information |
| 124 | + (div 5 0))) |
| 125 | +#+END_SRC |
0 commit comments