Re: there is a subtle problem doing: mySlot := obj getSlot(slotname)
"Mildred Ki'Lya" <[email protected]>
| Newsgroups | gmane.comp.lang.io |
|---|---|
| Message-ID | <CAHU8Kxi_MvYVWmhHV-eaqHQbKqkbW_iVO2hoyY1OEQaUKhqW_w@mail.gmail.com> |
On 8 November 2011 15:11, Jeremy Tregunna <[email protected]> wrote: > ** > > This is a common gotcha, and a source of many pains if you are writing >> library code. You can never be sure if a user is passing in an activatable >> object, so you have to account for that. >> > > Is it so much a problem in library code, can't we assume that we don't > accept method objects? > > > Well, you can assume that, but then you litter your code with checks which > still require a getSlot to verify the argument isn't a Block type. I.e., > you think just restricting the objects users can pass around and making > your implementation more complicated in doing so, requiring more time even > to execute. > I don't really see how a simpler assumption can still result in complicated code. Why would you need to do a check with getSlot()? Can't we use a proxy object that don't have the activation bit to use methods just like any normal object. Now that I think about it, can't we use a block as a proxy object? > > In Io, behaviour is a special kind of state, and that's a core > requirement. As such, methods/blocks are valid values. If you use the > method() convenience constructor, the activatable bit is set by default. If > you use the block() constructor, it's not set by default. That is to say: > > foo := method(1) > bar := block(1) > > list(foo, bar) > > Will return a list whose first value is 1, but whose second value is a > Block object. You must explicitly pass call() to the Block object in order > to invoke it. Generally, if you are accepting a function, you should pass > around blocks. That said, nothing negates users from passing methods. > Now, foo := block(method(1)) bar := block(1) list(foo, bar) you get a list with two blocks, the first wrapping the method. Functionally, it's similar to: foo := method(1) bar := block(1) list(getSlot("foo") setIsActivable(false), bar) But then, we can imagine a thinner layer around the method: protectActivableObject := method(obj, # probably won't work if(getSlot("obj") isActivable) then( proxy := Object clone proxy do( targetObject := getSlot("obj") forward := method( targetObject doMessage(call message) ) ) prox**y setIsActivatable(false) return(proxy) ) else( return(obj) ) ) And we can imagine that when called, a method wraps all arguments this way Or, if when we send a message, we know an object is activable, then we can wrap it manually at the call site directly. Mildred -- Mildred Ki'Lya http://mildred.fr