<div dir="ltr">Wow! &nbsp;I should have asked that a long time ago.<div><br></div><div>Actually, I&#39;m glad your response was as in-depth as it was. &nbsp;It gave me time to really think about the things that have been stumbling blocks, whether externally (the size and scope of ObjC &amp; Cocoa), or internally (adapting my brain to ObjC&#39;s syntax).</div>
<div><br></div><div>After working through the currency converter (first in ObjC, then CCL), I could see how the things were working, but it wasn&#39;t what I would call &quot;independent knowledge&quot; (i.e., I couldn&#39;t have taken what I knew and written something from scratch). &nbsp;Realizing this, I cast about for a small project to tinker with (as you suggested), and remembered a book that I had bought years ago (<span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px; "><a href="http://www.amazon.com/dp/0387202293">http://www.amazon.com/dp/0387202293</a>) that had drawing exercises at the end of each chapter written in Basic. &nbsp;(Hmm. &nbsp;Basic, ObjC, Lisp. &nbsp;There&#39;s a joke in there somewhere, but, at the moment, it escapes me.)</span></div>
<div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;"><br></span></div><div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;">From what I&#39;ve gathered, NSBezierPath will be my friend for accomplishing the drawing.</span></div>
<div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;"><br></span></div><div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;">Given Matthew&#39;s suggestion, it sounds like working through the Hillegass book first, and translating the exercises from the aforementioned book to ObjC might be the most optimal approach.</span></div>
<div><br></div><div>Thank you for the thoughtful response,</div><div>Chris.<br></div><div><br></div><div><div class="gmail_quote">On Thu, Aug 28, 2008 at 5:18 AM, Gary Byers <span dir="ltr">&lt;<a href="mailto:gb@clozure.com">gb@clozure.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="Ih2E3d"><br>
<br>
On Wed, 27 Aug 2008, Chris Van Dusen wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Agreed. &nbsp;I saw AppKiDo mentioned in the online documentation, and have been<br>
using it pretty heavily since.<br>
One thing I&#39;ve been curious about (and may produce on my own, if none<br>
exists) is a cheat sheet for the various ways of interacting with<br>
Objective-C. &nbsp;Until I get used to it, when to use the appropriate reader<br>
macro is a source of frustration.<br>
<br>
All of that said, does anyone have suggestions/recommendations as to how<br>
best to learn to commingle CCL &amp; Objective-C? &nbsp;I&#39;m fairly comfortable with<br>
Lisp in general. &nbsp;Would it be worth my while to devote my time to learning<br>
Objective-C, Cocoa, etc. to the point that I&#39;m conversant in those things,<br>
then come back at it from the CCL perspective?<br>
<br>
Thanks,<br>
Chris.<br>
<br>
</blockquote>
<br></div>
When learning CL, there were probably some fairly major concepts<br>
that needed to be absorbed, including:<br>
<br>
 &nbsp;- macros<br>
 &nbsp;- syntax (or the near total absence of it)<br>
 &nbsp;- the general notion that everything&#39;s a function that returns<br>
 &nbsp; &nbsp;some number of values, and that most primitive operations<br>
 &nbsp; &nbsp;(arithmetic, array/string access) are expressed as function calls<br>
 &nbsp;- closures and higher-order functions<br>
 &nbsp;- special variables and dynamic binding<br>
 &nbsp;- lambda-lists and variadic functions<br>
 &nbsp;- garbage collection (which might or might not be a new concept)<br>
 &nbsp;- CLOS<br>
 &nbsp;- the reader, packages ..<br>
 &nbsp;- the fact that there&#39;s a fairly rich library of standard functions<br>
 &nbsp; &nbsp;for dealing with common data structures<br>
 &nbsp;- ...<br>
<br>
At some point - when enough of these things make enough sense - one<br>
gets comfortable enough with enough of these concepts to be able to<br>
program productively in CL. &nbsp;Learning to program in CL probably has<br>
more to do with becoming comfortable with a relatively small set of<br>
core concepts (like those above) than it does with memorizing<br>
reference material describing all of the library functions. &nbsp;(If you<br>
quizzed me right now, I probably couldn&#39;t correctly enumerate all of<br>
the possible standard values that the :IF-EXISTS argument to OPEN can<br>
take; since we all know what keyword arguments are and how they<br>
can be used, we can look up those details in CLHS when we need<br>
to and expect that reference material to make sense. &nbsp;Well, usually.)<br>
<br>
For ObjC and Cocoa, the number of core concepts that we need to<br>
learn in order to start to make sense of things is (mostly) pretty<br>
small; if we want to be able to read ObjC code/examples, there<br>
are some additional syntactic details. &nbsp;For ObjC, these concepts<br>
include (some of this is a little circular):<br>
<br>
&nbsp;- certain data structures are &quot;classes&quot;; they serve a role<br>
 &nbsp; very similar to that served by classes in CLOS and other<br>
 &nbsp; object systems. &nbsp;It&#39;s possible to add new classes to a<br>
 &nbsp; running ObjC program (just as it is in CLOS), though ObjC<br>
 &nbsp; is less flexible than CLOS/MOP is about redefining/removing<br>
 &nbsp; classes procedurally. &nbsp;ObjC classes are uniquely named (by<br>
 &nbsp; a string); many of the predefined classes in Cocoa (which<br>
 &nbsp; was derived from NeXT&#39;s NeXTStep framework) have names<br>
 &nbsp; that start with the prefix &quot;NS&quot;.<br>
<br>
 &nbsp; ObjC classes are allocated in foreign memory (often as<br>
 &nbsp; part of a shared library&#39;s initialized data.) &nbsp;A class<br>
 &nbsp; decribes the layout of its instances&#39; instance variables<br>
 &nbsp; (&quot;slots&quot; in CLOS) and describes methods which are specialized<br>
 &nbsp; on its instances.<br>
<br>
 &nbsp; Redefining ObjC classes at runtime probably doesn&#39;t work<br>
 &nbsp; very well. &nbsp;In CCL&#39;s ObjC bridge, accidentally mousing<br>
 &nbsp; on an unchanged class definition is probably harmless.<br>
 &nbsp; Adding/removing slots won&#39;t affect existing instances<br>
 &nbsp; in general, and I don&#39;t know/remember what Bad Things<br>
 &nbsp; might happen if the class hierarchy was changed.<br>
<br>
&nbsp;- classes can be instantiated (just as in CLOS and most other<br>
 &nbsp; object systems); this involves allocating a (somewhat opaque)<br>
 &nbsp; block of foreign memory. &nbsp;If one knows that a block of<br>
 &nbsp; foreign memory contains an ObjC instance, it is possible<br>
 &nbsp; (and cheap) to determine the class of that instance at<br>
 &nbsp; runtime.<br>
<br>
&nbsp;- unlike the case in CLOS - where classes are usually instances<br>
 &nbsp; of the metaclass STANDARD-CLASS - ObjC classes of unique<br>
 &nbsp; metaclasses. &nbsp;(Among other things, this scheme allows methods<br>
 &nbsp; on classes to be specialized and customized.) &nbsp;An ObjC class<br>
 &nbsp; is therefore an instance of its metaclass (which is itself<br>
 &nbsp; an instance of a special root metaclass), and it&#39;s possible<br>
 &nbsp; to consider any ObjC class, metaclass, or instance as being<br>
 &nbsp; an &quot;ObjC object&quot;. &nbsp;All three kinds of ObjC object are implemented<br>
 &nbsp; as &quot;blocks of foreign memory&quot;; the blocks occupied by classes<br>
 &nbsp; and metaclasses are &quot;permanent&quot; (for the lifetime of the<br>
 &nbsp; application), while those occupied by ObjC instances can be<br>
 &nbsp; freed (and possibly reallocated) when it appears that they<br>
 &nbsp; can no longer be referenced. &nbsp;Apple is moving toward the<br>
 &nbsp; use of real garbage collection to determine when instances<br>
 &nbsp; can be reliably and automatically freed; traditionally, a<br>
 &nbsp; reference-counting scheme has been used.<br>
<br>
 &nbsp; A foreign type corresponding to &quot;pointer to ObjC object&quot;<br>
 &nbsp; is predefined in ObjC; this type is named &quot;id&quot; (or :id from<br>
 &nbsp; CCL).<br>
<br>
&nbsp;- some strings (usually in mixed case and often containing<br>
 &nbsp; embedded and/or trailing colons) name ObjC &quot;messages&quot;. &nbsp;An<br>
 &nbsp; ObjC message isn&#39;t quite a first-class object, but it can be<br>
 &nbsp; thought of as being similar to a kind of generic function<br>
 &nbsp; which is specialized on the class of its first argument<br>
 &nbsp; (which must be an ObjC object) and which may contain<br>
 &nbsp; additional arguments. &nbsp;Those additional arguments may<br>
 &nbsp; be ObjC objects or low-level C pointers or numbers.<br>
 &nbsp; A string which names a message is sometimes called a<br>
 &nbsp; &quot;selector&quot; (in some other ObjC implementations, a &quot;selector&quot;<br>
 &nbsp; is distinct from the string which identifies it, but that&#39;s<br>
 &nbsp; a separate issue.)<br>
<br>
 &nbsp; The number of colons in a message name typically indicates<br>
 &nbsp; the number of arguments (other than the first, special<br>
 &nbsp; argument) that methods defined on the message should accept.<br>
<br>
&nbsp;- It&#39;s possible (and useful) to define methods on any message<br>
 &nbsp; and any ObjC class or metaclass. &nbsp;A large number of methods<br>
 &nbsp; (on a large number of classes ...) are predefined in Cocoa<br>
 &nbsp; and other ObjC libraries; methdods can also be added at<br>
 &nbsp; runtime. &nbsp;In order for ObjC code to be able to pass arguments<br>
 &nbsp; (other than the first specialized argument of type &quot;id&quot;)<br>
 &nbsp; to and return results from an ObjC method, the (foreign)<br>
 &nbsp; types of those arguments and return value must be specified.<br>
 &nbsp; If a method shadows another method defined in a superclass<br>
 &nbsp; (or is shadowed by a method defined in a subclass), the<br>
 &nbsp; types of those arguments and return value must agree.<br>
 &nbsp; (It&#39;s legal for methods defined on disjoint classes to<br>
 &nbsp; have different type signatures; this happens occasionally<br>
 &nbsp; in practice.)<br>
<br>
 &nbsp; All methods defined on an ObjC message must take the same<br>
 &nbsp; number of arguments, but (as noted above) the types of<br>
 &nbsp; their non-specialized arguments may differe in some cases.<br>
<br>
 &nbsp; It is possible to redefine an ObjC method at runtime; it<br>
 &nbsp; generally works reliably to change the implementation (body)<br>
 &nbsp; of the method, but may not work as well (or at all) to<br>
<br>
<br>
&nbsp;- From within the body of an ObjC method M, it&#39;s possible to<br>
 &nbsp; invoke whatever method would have been applicable had M<br>
 &nbsp; not been defined. &nbsp;(Conceptually, this is similar to<br>
 &nbsp; CALL-NEXT-METHOD in CLOS.)<br>
<br>
&nbsp;- In ObjC (as in SmallTalk), invoking a generic function on<br>
 &nbsp; a specialized argument (&quot;the receiver&quot;) and some other<br>
 &nbsp; arguments is called &quot;sending a message&quot;, and it&#39;s written<br>
 &nbsp; in a sort of infix syntax:<br>
<br>
[reciever messageName] &nbsp; if the message accepts no other arguments<br>
[receiver messageNameFirstArg: first-arg-value nextArg: next-arg-value]<br>
otherwise.<br>
<br>
 &nbsp; In the first case, the actual message name is &quot;messageName&quot;; in the<br>
 &nbsp; second &nbsp;case, it&#39;s &quot;messageNameFirstArg:nextArg:&quot;<br>
<br>
&nbsp;- Methods can be defined on classes (and therefore applicable to<br>
 &nbsp; their instances) or on metaclasses (and therefore applicable to<br>
 &nbsp; class methods). &nbsp;When a class method is defined or described, it&#39;s<br>
 &nbsp; usually prefixed with a &quot;+&quot; character; an instance method is<br>
 &nbsp; usually prefixed with a &quot;-&quot;.<br>
<br>
That&#39;s a fair amount of stuff that really should be written down<br>
someplace and in greater detail. &nbsp;A short version is that ObjC offers<br>
an object system with dynamically typed objects and at least some<br>
amount of/some kinds of runtime extensibility, and a sort of<br>
restricted form of (something like) CLOS method dispatch that&#39;s based<br>
on the (runtime) class of the first/only specialized argument, and<br>
that ObjC methods typically deal with some combination of run-time<br>
typed Objc objects and statically-typed primitive C things (numbers,<br>
pointers, structures.)<br>
<br>
I suspect (I don&#39;t know for sure) that the thing that&#39;d help most<br>
people the most in getting up to speed with using Cocoa in CCL is<br>
comfort and familiarity with CCL&#39;s FFI. &nbsp;If that&#39;s true (and to the<br>
extent that it is), it&#39;s somewhat unfortunate; when he first started<br>
working on it, Randall Beer said that ideally he&#39;d like the bridge to<br>
expose as much of Cocoa as possible while hiding as much of ObjC as<br>
possible. &nbsp;It&#39;s gotten closer to that goal over the years, but I<br>
suspect that a lot of things that people have trouble with could<br>
be blamed on the fact that ObjC (and some of the arcana of dealing<br>
with it) still isn&#39;t hidden well enough. &nbsp;(If this is true, it&#39;s<br>
probably the &quot;C&quot; part that&#39;s problematic; the &quot;Obj&quot; part seems<br>
to fit a lot better into CL/CCL.) &nbsp;Looking back at it, I think<br>
that the bridge actually -does- do a good job of hiding a lot<br>
of the problematic C stuff (though admittedly not all of it),<br>
but a lot of it is ultimately nothing more than a few layers<br>
of syntactic sugar around the FFI, and I imagine that it&#39;s<br>
still hard to use unless one has some sense of what&#39;s going<br>
on underneath.<br>
<br>
For learning Cocoa itself ... well, it&#39;s a large class library (much<br>
larger than the standard CL library) that provides default behavior<br>
for a lot of things that an application needs to do (implemented as<br>
instances of predefined classes and predefined methods on those<br>
classes), and the general idea is that by subclassing some of those<br>
classes and overriding some of those methods you turn this generic<br>
application into something that offers custom behavior. &nbsp;It&#39;s<br>
generally hard to absorb all of the functionality that&#39;s available<br>
in a library by reading the reference manual from cover to cover<br>
(it might help to skim reference material to get a sense of<br>
what&#39;s available and to read a few passages that seem interesting.)<br>
It&#39;s often helpful - especially when starting out - to have a<br>
specific goal in mind, and then try to learn what you need to<br>
learn in order to achieve that. &nbsp;After you repeat that process<br>
a few times, it likely starts to get easier, and (as is often<br>
the case) the first foray into something new is the hardest.<br>
<br>
Suppose that we had a specific goal of writing an image-viewing<br>
program, like a watered-down version of Apple&#39;s Preview.app)<br>
(We could make the example more interesting, but let&#39;s not ...)<br>
If we&#39;ve never done this before in Cocoa, there are clearly<br>
a bunch of specific questions we&#39;d need answered, including:<br>
<br>
&nbsp;- what predefined support is there for loading files containing<br>
 &nbsp; well-known image types (jpg, tiff, gif, png, ...) and displaying<br>
 &nbsp; them ? &nbsp;If we wanted to construct an image from an unsupported<br>
 &nbsp; file type or procedurally, what&#39;s involved in doing that ?<br>
<br>
&nbsp;- how exactly do you display a window and get an image to appear<br>
 &nbsp; in it ? &nbsp;How do you control what happens when the window is<br>
 &nbsp; resized (e.g., does the image scale ? &nbsp;do you want it to ?)<br>
<br>
&nbsp;- how do you provide a user interface that allows images to<br>
 &nbsp; be loaded (and other behavior that a more interesting<br>
 &nbsp; application would want) ?<br>
<br>
Apple does provide very good overview documentation (in the<br>
form of &quot;guides&quot;.) &nbsp;At the moment, the Cocoa guides are<br>
available at:<br>
<br>
&lt;<a href="http://developer.apple.com/documentation/Cocoa/index.html" target="_blank">http://developer.apple.com/documentation/Cocoa/index.html</a>&gt;<br>
<br>
and looking at the &quot;Graphics and Imaging&quot; section there we find links<br>
to guides describing &quot;Image Views&quot; (sounds promising) and a &quot;View<br>
Programming Guide&quot;. &nbsp;The image view guide is a little terse (it<br>
basically just says that NSImageViews are NSViews that display<br>
NSImages, whatever they are. &nbsp;The &quot;View Programming Guide&quot; is a lot<br>
more to digest, and if we follow a link to NSImage we&#39;d have even more<br>
to digest. &nbsp;If we follow the link from the Image View guide to the<br>
NSImageView reference, we see that NSImageViews can be set to allow<br>
cut copy and paste of images as well as drag-and-drop. &nbsp;That&#39;s maybe<br>
not ultimately what we want (if we want to load images from files),<br>
but it may be an easier way to get started.<br>
<br>
Let&#39;s make a window, put an NSImageView in it, set some options<br>
that enable drag-and-drop and cut-and-paste to work with the<br>
image view, center and display the window, and return the NSImageView<br>
object:<br>
<br>
(defun make-image-view-window ()<br>
 &nbsp;&quot;Make a window whose content view is an empty NSImageView. &nbsp;Allow<br>
the user to drag images to that view, and support transfer of images<br>
to/from the view via the clipboard. &nbsp;Return the NSImageView.&quot;<br>
 &nbsp;(ccl::with-autorelease-pool<br>
 &nbsp; (let* ((rect (ns:make-ns-rect 0 0 300 300))<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(w (make-instance &#39;ns:ns-window<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:with-content-rect rect<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:style-mask (logior #$NSTitledWindowMask<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#$NSClosableWindowMask<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#$NSMiniaturizableWindowMask<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#$NSResizableWindowMask)<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:backing #$NSBackingStoreBuffered<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:defer t))<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(image-view (make-instance &#39;ns:ns-image-view)))<br>
 &nbsp; &nbsp; ;; Set the window&#39;s title to a constant NSString (#@&quot;...&quot;).<br>
 &nbsp; &nbsp; (#/setTitle: w #@&quot;Drag or paste an image here!&quot;)<br>
 &nbsp; &nbsp; ;; Make the image view respond to drag-and-drop<br>
 &nbsp; &nbsp; (#/setEditable: image-view t)<br>
 &nbsp; &nbsp; ;; and make it support the clipboard<br>
 &nbsp; &nbsp; (#/setAllowsCutCopyPaste: image-view t)<br>
 &nbsp; &nbsp; ;; Make the image view be the window&#39;s &quot;content view&quot;.<br>
 &nbsp; &nbsp; (#/setContentView: w (#/autorelease image-view))<br>
 &nbsp; &nbsp; ;; Center and display the window.<br>
 &nbsp; &nbsp; (#/center w)<br>
 &nbsp; &nbsp; (#/orderFront: w nil)<br>
 &nbsp; &nbsp; image-view)))<br>
<br>
If we call this function, an empty 300x300 window should appear on<br>
the screen and an NSImageView object should be returned.<br>
<br>
? (make-image-view-window)<br>
#&lt;NS-IMAGE-VIEW &lt;NSImageView: 0x1279bf50&gt; (#x1279BF50)&gt;<br>
? (defvar *v* *) ; so we can refer to the NS-IMAGE-VIEW later.<br>
*V*<br>
<br>
If we then switch to a web browser or other image-viewing application<br>
and copy an image to the clipboard, we can switch back to the IDE and<br>
paste that image into the image view.<br>
<br>
I happened to copy a fairly small image:<br>
<br>
? (#/image *v*)<br>
#&lt;NS-IMAGE NSImage 0x12795df0 Size={120, 80} Reps=(<br>
 &nbsp; &nbsp;NSBitmapImageRep 0x1279cf30 Size={120, 80} ColorSpace=NSCalibratedRGBColorSpace BPS=8 BPP=32 Pixels=120x80 Alpha=YES Planar=NO Format=2 CGImage=0x1279e340<br>
) (#x12795DF0)&gt;<br>
<br>
When I resized the window, the image stayed at 120x80 and happened to<br>
stay centered in the window. &nbsp;It may be more impressive to let the image<br>
scale itself to fit the view bounds:<br>
<br>
? (#/setImageScaling: *v* #$NSScaleToFit)<br>
NIL<br>
<br>
Getting images from the clipboard is all well and good, but the original<br>
goal was to display images that were loaded from files. &nbsp; If only<br>
NSImage had an &quot;initWithContentsOfFile:&quot; method, this would be trivially<br>
easy in most cases.<br>
<br>
Oh, wait: it does (as revealed by a little bit of poking around in the<br>
NSImage reference doc.) &nbsp;ObjC messages whose names start with<br>
&quot;init&quot; are treated specially by the bridge: MAKE-INSTANCE with keyword<br>
args derived from the rest of the message name will (among other<br>
things) send that initialization message to a newly-allocated instance<br>
of the class. So:<br>
<br>
(let* ((image (make-instance &#39;ns:ns-image :with-contents-of-file #@&quot;/Library/Desktop Pictures/Nature/Aurora.jpg&quot;)))<br>
 &nbsp;(unless (%null-ptr-p image) ; unless the image couldn&#39;t be initialized<br>
 &nbsp; &nbsp;(#/setImage: *v* (#/autorelease image))))<br>
<br>
We know from an earlier message in this thread (if not otherwise)<br>
how to use NSOpenPanel to select a file, so we&#39;re maybe around 75%<br>
of the way towards the goal of developing a simple image-viewing<br>
program. &nbsp;That&#39;s probably enough for an off-topic reply, but it&#39;s<br>
worth noting that so far it&#39;s been about 20 lines of code and that<br>
NSImage and NSImageView and the rest of Cocoa are doing all of the<br>
heavy lifting.<br>
<br>
I&#39;m sorry that this reply is so long and not entirely responsive. To<br>
try to summarize:<br>
<br>
&nbsp;- I think that the best way to learn Cocoa (or anything similar)<br>
 &nbsp; is probably from the bottom up and from the inside out, and that<br>
 &nbsp; it helps to have a concrete, narrowly focused goal and to try<br>
 &nbsp; to learn just what you need to learn in order to achieve that.<br>
 &nbsp; After repeating that process a few times, more stuff tends to<br>
 &nbsp; resonate and make sense.<br>
<br>
 &nbsp; It&#39;s certainly not practical to go in the other directions,<br>
 &nbsp; as in &quot;here are several hundred classes and a few thousand<br>
 &nbsp; methods, go learn them.&quot;<br>
<br>
&nbsp;- From your comments and others, I think that it&#39;s fair to say<br>
 &nbsp; that the goal of hiding ObjC (the C part of it, especially)<br>
 &nbsp; hasn&#39;t been fully reached. &nbsp; It&#39;s still sometimes necessary<br>
 &nbsp; to allocate foreign objects and pass pointers to them by<br>
 &nbsp; reference, and that sort of thing is disconsonant with what&#39;s<br>
 &nbsp; otherwise a very high-level and powerful framework (Cocoa.)<br>
 &nbsp; That stuff is also inherently hard and un-lispy.<br>
<br>
One of the problems that I personally have here is that while<br>
I can believe that there are aspects of CCL&#39;s FFI that are hard<br>
to use and/or understand, it&#39;s hard for me to guess exactly<br>
what those things are (since it all makes perfect sense to me<br>
for some reason.)<br>
</blockquote></div><br></div></div>