Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Clojure Design
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
Colour
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Undo
Redo
Keyboard Shortcuts Help
<h2>Rationale</h2> <p>We need an interface to type information that:</p> <ul> <li>encapsulates Java reflection</li> <li>returns Clojure data not Java's reflection objects </li> <li>supports ASM in addition to reflection <ul> <li>ASM offering type info without loading classes</li> </ul> </li> <li>supports ClojureCLR</li> </ul> <p>Users will be compilers and tools, as well as REPL users through an interactive wrapper interface.</p> <p><strong>Design Decisions</strong></p> <ul> <li>using Clojure symbols to represent class and method names <ul> <li>pro: matches Clojure's use of symbols, easy literal rep</li> <li>con: requires [] to <> conversion (but this conversion is already in place elsewhere in Clojure!)</li> <li>also considered keywords and a new datatype. <ul> <li>rejected keywords as they have the same cons as symbols, and feel less idiomatic</li> <li>rejected new datatype as too much pain for not enough gain. Literal rep is a huge advantage</li> </ul> </li> </ul> </li> <li>get the data out as quickly as possible <ul> <li>APIs convert reflection/asm APIs into Clojure data before doing anything else</li> <li>gives you the entire Clojure data API to manipulate</li> <li>simplest to implement</li> <li>will be less performant for the case where you only want a tiny bit of info, but I don't have a use case needed that perf</li> </ul> </li> <li>create my own table of java access bitflags (flag-descriptors), instead of using constants from reflection or ASM <ul> <li>at first glance the existing constants might seem fundamental, but the spec actually dominates</li> <li>the existing constants don't capture all the information (different flags apply to different types)</li> <li>existing flags can't change, and if new ones emerge the code would have to change even if I was using the existing constants</li> </ul> </li> <li>use defrecords for constructor, field, method <ul> <li>wanted types for polymorphic dispatch for printing</li> <li>the print dispatch is not general, I still want map-ish printing through pprint (note Rich questions this below)</li> </ul> </li> <li>keep fields/methods/records in a set <ul> <li>they are logically a set (no order imposed by spec)</li> <li>they have a lot in common (flags, name, etc.)</li> <li>considered three separate sets for fields/methods/constructors, but given that no choice is ideal for all API consumers decided to keep it simple. Classes have <strong>members</strong> of different types.</li> </ul> </li> <li>two levels of reflection: class, or class-plus-ancestors <ul> <li>does not correspond to Java reflection's distinction of declared here vs. visible-from-here</li> <li>I have always believed Java had this wrong: visible from here is a derived fact. Class or class+ancestors reflects the reality of the data, while visible-from-here is driven by a single use case</li> <li>that said, the compiler will want visible-from-here, so when the compiler starts using this API we will need to derive it</li> </ul> </li> <li>reflection is parameterized by Reflector protocol <ul> <li>there will be one or more implementations per platform</li> <li>reflection is scoped to Reflector's notion of how to find classes <ul> <li>toyed with making this implicit in some way, scarily complex for no benefit</li> </ul> </li> <li>considered dynamic scope for default reflector <ul> <li>bad idea: just creates more stateful magic</li> <li>defaulting to platform reflecting by arity provides ease-of-use without the complexity of dynamic scope</li> </ul> </li> </ul> </li> </ul> <p><strong>Issues</strong></p> <p>Note, this list is primarily RH's notes on <a href="https://www.assembla.com/spaces/clojure/tickets/453?batch=&tickets_report_id=u17045&ticket_id=453&commit=Go+%C2%BB">Stu's patch</a>. <span style="color: rgb(51,153,102);">Stu's initial replies inline</span></p> <ul> <li>hrm, the predicate language in describe <span style="color: rgb(51,153,102);">thinking about this</span>** always and/every? <ul> <li> <ul> <li>single pred would allow arbitrary logic</li> </ul> </li> <li>Explore query-by-example, i.e. user provides partial data in same shape as returned</li> </ul> </li> <li>reflect-impl bad name for fn <ul> <li>prefer things like do-reflect, still a verb</li> <li><span style="color: rgb(51,153,102);">I hate overloading "do" because it already means "force". Come to think about it, it's too bad doall isn't force-all. :-)</span></li> <li><span style="color: rgb(51,153,102);">understand the problems with -impl, don't have a better word yet</span></li> </ul> </li> <li>typeref->name - typename <span style="color: rgb(51,153,102);">ok</span></li> <li>typeref->sym - typesym <span style="color: rgb(51,153,102);">ok</span>** typeref->* implies things of type typeref, we don't want to reify protocol like that <ul> <li>ditto - typepath</li> </ul> </li> <li>are we exposing the descriptor, internal-name confusion by having these helpers public, with no better docs than we complain about? <ul> <li><span style="color: rgb(51,153,102);">the easiest way to explain these is be enumerating a few examples (which the tests do)</span></li> <li><span style="color: rgb(51,153,102);">this is a place where I want the tests inline (which doesn't work with our CI harness) or a well-known convention of looking to the tests for examples (like Ioke does)</span></li> <li><span style="color: rgb(51,153,102);">if I am forced to repeat myself in tests and documentation I will just make these private to avoid having to answer the bigger questions. :-)</span></li> </ul> </li> <li>defrecord Constructor/Method/Field <ul> <li>make sure distinguishing these by type adds value <span style="color: rgb(51,153,102);">only value is in reflection-specific pprint. Still undecided, let's discuss.</span></li> <li>much pain today in writing generic reflection code due to unequal treatment of members <ul> <li>i.e. ctors are glorified static methods</li> </ul> </li> <li>I'd prefer a first cut with maps and see where that is inadequate <ul> <li>perhaps already done, notes?</li> </ul> </li> </ul> </li> <li>defrecord JavaReflector/AsmReflector <span style="color: rgb(51,153,102);">ok</span>** unlike Contrstructor/Method/Field, these are plainly not information but are programming constructs and should be deftypes</li> <li>describe's built in pprint <ul> <li>can we not get pprint to print the data structures nicely? <span style="color: rgb(51,153,102);">I don't want to (see my design notes above). What I really thought I wanted was context-specific pprint.</span></li> <li>giving the user a bunch of printout they can't lift and use as data isn't that great <ul> <li>may be more useful to enhance pprint</li> <li><span style="color: rgb(51,153,102);">the thing that I don't like about existing pprint in this scenario is the verbosity of enumerating keys that are obvious from context. I don't have a solution.</span></li> </ul> </li> </ul> </li> </ul>
Attachments
Labels
Location
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced