[Openmcl-devel] when is :<BOOL> == T?

Gary Byers gb at clozure.com
Sat Aug 6 17:01:49 UTC 2005

On Sat, 6 Aug 2005, alex crain wrote:

> I'm thinking that if :<BOOL> = { T, nil} then it should always be so and 
> #$YES and $#NO should be banned from the kingdom.
> Current, OBJC-MESSAGE-SEND and friends do not translate #<BOOL>, but SEND and 
> %SEND do.
> ? (defvar w (make-instance 'ns:ns-window))
> #<NS-WINDOW <NSWindow: 0x3ac750> (#x3AC750)>
> ? (send w 'can-hide)
> T
> ? (ccl::objc-message-send w "canHide")
> #<A Mac Pointer #x1>
> ?

? (ccl::objc-message-send w "canHide" :<BOOL>)  would at least return
1 (= #$YES), and that serves to demonstrate that SEND is somewhat
higher level than OBJC-MESSAGE-SEND.

Carried still further, the #_ reader macro is usually a little
higher-level than CCL:EXTERNAL-CALL, which is syntactic sugar on top
of CCL:FF-CALL, which in turn is slightly higher-level than

> I'm not sure that I see that value of translating :<BOOL> into a lisp type. 
> All the other objects in the ObjC interface are ObjC
> types so it's not intuitive (to me, anyway).

I'm generally a little leery of DWIMming too much, but I became
convinced that mapping back and forth between :<BOOL> and BOOLEAN was
the right thing at the level of SEND; it's an unambiguous and
reversible mapping and it's fairly cheap (could certainly deal with
constants better, but it doesn't cons).  The fact that ObjC uses what
are ultimately numbers to represent truth values is a gory
implementation that seems better hidden, and saving a little typing
when writing

   (if (send w 'can-hide) ...)

instead of

   (if (not (eql #$NO (send w 'can-hide))) ...)

- and a little cognitive effort when reading that - seems worthwhile.

I -do- think that some other possible coercions would be DWIMming too
much or too far; I don't think that it'd be right for a SEND of a
message that returned an NSString to return a lisp string, because
there are radically different sets of operations that are applicable
on those disjoint classes.  There aren't too many operations that can
be performed on booleans (testing for truth/falsehood, negation),
and I think that it's a lot more convenient to use the lisp versions
of those operations than the C/ObjC ones:

;;; Send doesn't do boolean coercion
(defmethod toggle-visibility ((w some-NSWindow-subclass))
   (send w :set-visible (logxor (send w 'visible) 1)))

;;; Send doesn't do boolean coercion
(defmethod toggle-visibility ((w some-NSWindow-subclass))
   (send w :set-visible (- 1 (send w 'visible))))

;;;  Send doesn't do boolean coercion
(defmethod toggle-visibility ((w some-NSWindow-subclass))
   (send w :set-visible (! (send w 'visible))))

;;; It's time to invent the C negation operator
(defun ! (arg)
   (if (zerop arg) 1 0))

;;; Send does boolean coercion
(defmethod toggle-visibility ((w some-NSWindow-subclass))
   (send w :set-visible (not (send w 'visible))))

> If we must translate, then SLOT-VALUE, WITH-SLOTS, etc should all work

I already agreed with this yesterday :)

> You could make the case that OBJC-SEND-MESSAGE is a low level primitive and 
> thus should not do translation whereas
> SEND and %SEND are high level and should .... but to be honest that looks a 
> lot like early C++ to me and I wasn't a fan
> of that either.

I don't expect too many people to use OBJC-MESSAGE-SEND, or to use it
very often.

I don't know if early C++ high level primitives were defined in terms
of early C++ low level primitives; that strikes me as being a perfectly
reasonable implementation strategy (certainly a lot easier than doing
it the other way around), and I don't know enough about the history of
C++ to understand why exposing more than one level of functionality was
bad.  (I -do- know enough about C++ to be able to anticipate that any
reference to C++ must be describing something bad.)

In Common Lisp, it's possible to write iterative loops with TAGBODY
and GO (though it's pretty painful to do so); LOOP also exists, as do
DO/DOTIMES/DOLIST/etc.  TAGBODY's about as low-level and primitive as
CL gets; to avoid being compared to C++, should it be made
higher-level ?

I don't believe that having or exposing multiple layers of
functionality is a bad thing.

> It would make sense that it would be legal to send #$YES in place of T unless 
> we get rid of #$YES all together.

It generally is possible to pass #$YES instead of T (and #$NO instead of NIL)
in outgoing message arguments, and (AFAIK) it always has been.

SEND always maps :<BOOL> return values to T or NIL.  If you want to get
at the ObjC return value before SEND does this mapping, you have to use
something lower-level.

> We cold maybe modify the #$ dispatch macro so that #$YES and #$NO are mapped 
> to T and nil respectively,
> which would make everything uniform (at least at the symbolic level).

I think that I'd have to have a very different model of things than I do
in order to be able to understand the rationale for doing what you propose.

> :alex
> On Aug 5, 2005, at 6:03 PM, Gary Byers wrote:
>> On Fri, 5 Aug 2005, Randall Beer wrote:
>>> As far as I recall, :<BOOL>s always expect T/NIL, unless this has changed 
>>> in the new SEND stuff that Gary has been doing.  I *think* that any 
>>> untyped argument in a DEFINE-OBJC-METHOD defaults to :ID, which is 
>>> probably not what you want.
>>> Randy
>> The only recent related change that I'm aware of is that there's a
>> real :<BOOL> foreign type in the pre-0.14.4 lisp; the interface
>> translator treats :<BOOL> as being a primitive, built-in type, and the
>> bridge gets method type signatures from the interface database instead
>> of by querying the ObjC runtime.  (The way that the runtime encodes
>> types, it wasn't possible to reliably distinguish between :<BOOL> and
>> :signed-char, but it worked fairly well to assume that :signed-char
>> meant :<BOOL> except in certain known/declared exceptional cases.)
>> One case in which :<BOOL> and BOOLEAN aren't automatically mapped
>> back and forth is SLOT-VALUE; the value of a slot of foreign-type
>> :<BOOL> is #$YES or #NO, not t/nil.  This probably doesn't come up
>> that often (there's at least one case of it in the demo IDE), but
>> it might be simpler if everything in the bridge consistently mapped
>> between :<BOOL> and BOOLEAN without this special case.
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list