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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.