Re: [Pharo-dev] Strange primitive failure

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] Strange primitive failure

Eliot Miranda-2
Hi Ben,


On Fri, Nov 1, 2013 at 7:01 AM, Benjamin <[hidden email]> wrote:
Hello guys,

is it expected that

1 perform: #gcd: withArguments: {2} 
works

while

1 perform: #gcd: withArguments: {2} asOrderedCollection
fails ?

As Alexandre explained it's because the VM insists on an Array.  But there is a neat way to solve this.  e.g. if the method is defined as

Object>>perform: selector withArguments: argArray 
"Send the selector, aSymbol, to the receiver with arguments in argArray.
Fail if the number of arguments expected by the selector 
does not match the size of argArray.
Primitive. Optional. See Object documentation whatIsAPrimitive."

<primitive: 84>
^ self perform: selector withArguments: argArray inSuperclass: self class

 and

Object>>perform: selector withArguments: argArray inSuperclass: lookupClass
"NOTE:  This is just like perform:withArguments:, except that
the message lookup process begins, not with the receivers's class,
but with the supplied superclass instead.  It will fail if lookupClass
cannot be found among the receiver's superclasses.
Primitive. Essential. See Object documentation whatIsAPrimitive."

<primitive: 100>
(selector isSymbol)
ifFalse: [^ self error: 'selector argument must be a Symbol'].
(selector numArgs = argArray size)
ifFalse: [^ self error: 'incorrect number of arguments'].
(self class == lookupClass or: [self class inheritsFrom: lookupClass])
ifFalse: [^ self error: 'lookupClass is not in my inheritance chain'].
self primitiveFailed

then redefine perform:withArguments:inSuperclass: to read something like:

Object>>perform: selector withArguments: argArray inSuperclass: lookupClass
"NOTE:  This is just like perform:withArguments:, except that
the message lookup process begins, not with the receivers's class,
but with the supplied superclass instead.  It will fail if lookupClass
cannot be found among the receiver's superclasses.
Primitive. Essential. See Object documentation whatIsAPrimitive."

<primitive: 100>
(argArray isCollection and: [argArray isSequenceable and: [argArray class ~~ Array]]) ifTrue:
[^self perform: selector withArguments: argArray asArray inSuperclass: lookupClass].
selector isSymbol
ifFalse: [^ self error: 'selector argument must be a Symbol'].
selector numArgs = argArray size
ifFalse: [^ self error: 'incorrect number of arguments'].
(self class == lookupClass or: [self class inheritsFrom: lookupClass])
ifFalse: [^ self error: 'lookupClass is not in my inheritance chain'].
self primitiveFailed

c.f. e.g. the asInteger send in

Object>>at: index 
"Primitive. Assumes receiver is indexable. Answer the value of an 
indexable element in the receiver. Fail if the argument index is not an 
Integer or is out of bounds. Essential. See Object documentation 
whatIsAPrimitive."

<primitive: 60>
index isInteger ifTrue:
[self class isVariable
ifTrue: [self errorSubscriptBounds: index]
ifFalse: [self errorNotIndexable]].
index isNumber
ifTrue: [^self at: index asInteger]
ifFalse: [self errorNonIntegerIndex]

which allows one to write #(seriously ?) at: 1.0

HTH,
Eliot