Array extend [
Array class >> bin: val left: l right: r [
^ super binSearch: val left: l right: r
]
binSearch: val left: l right: r [
|arr iter|
arr := self.
[l == r]
ifTrue: [^ (-1)].
iter := (r + l)/2.
[arr at: iter == val]
ifTrue: [^iter].
[arr at: iter < val]
ifTrue:[^ super binSearch val left: l right: iter]
ifFalse: [^ super binSearch val left: iter right: r]
]
]
arr := #(3 6 9 10).
arr bin: 6 left: 1 right: 4.
This is my current code, but I get a compilation error: "Object: Array new: 4 "<0x7fe20936e940>" error: did not understand #bin:left:right:". I was wondering what I was doing wrong.
Thanks
The first part makes no sense to me. Your algorithm is recursive and so it should call itself rather than delegating to the class, which is a different object.
To do this, replace
super
withself
and the same method will be invoked again with the new parameters.Further remarks
[Boleans] The receiver of
ifTrue:
& friends must be aBoolean
(i.e.,true
orfalse
). By enclosing the condition between squared brackets you are creating aBlockClosure
instead. I've mentally replaced[...]
with(...)
where appropriate and then removed them whenever they are not required (see [Precedence] below).[Comparisons] This is debatable but, while the condition
l==r
is not entirely wrong, however,l=r
is generally better. The reason: the semantics of==
corresponds to being the very same object (low level), the semantics of=
of being equal (or equivalent). Your algorithm doesn't care whetherl
andr
are represented by exactly the very same object, it only needs to know if both variables hold the same integer. Although the distinction is not relevant in this case, you might create an habit of using==
which will fail the day you deal with other kinds of objects (v.g.LargeIntegers
, etc.)[Parenthesis] There is no need to add parenthesis to
^ -1
.[Division] Since
+
and/
are messages, there is no need either to add parenthesis inr + 1 / 2
. However, the division may produce aFraction
where your code requires anInteger
. Use//
instead to get the quotient.[Colons] You had forgotten the colon after
binSearch
. This creates a DNU error.[Precedence] Parenthesis are needed around
arr at: iter
so to compare the result of this message withval
(Recall that the precedence order is: unary, binary, keyword).[DNU] Regarding the error you get: The selector you created is
binSearch:left:right:
, however you sent the messagebin:left:right:
which is not defined.[self] There is no need to assign
self
to something else: the receiver will not change along the recursion.[Return] Many Smalltalkers whould have moved the return symbol
^
to the beginning of the last expression.In Smalltalk, where arrays are 1-based, the convention broadly accepted consists in returning
0
(rather than-1
) when no index is found.Suggestions
Complete your work by adding sufficient unit tests to exercise and improve your method. I've restricted my answer to the coding style, not its correctness.
Add the following method so clients of your service don't need to be verbose when using it.