Mombu the Programming Forum

Go Back   Mombu the Programming Forum > Programming > array exists feature
User Name
Password
REGISTER NOW! Mark Forums Read




Reply
1 1st November 23:36
ryan paul
External User
 
Posts: 1
Default array exists feature



Loops seem like needless overkill for many tasks. I shouldnt have to
write a six line loop to do a simple check for an item with a particular
property in an array.

I noticed that the array class has an 'exists' feature, but i'm not
entirely sure how to use it. I'd like to be able to do something like:

my_feature (s:STRING) is
do
if users.exists(lambda x is x.name = s) then
-- do something ...
end
end

I know that eiffel doesnt really have anonymous functions (I'm aware that
the standard does define them but nobody likes the syntax) so how do I use
'exists' to concisely perform this operation without having to use a loop?
Do I have to create an external function? I'm I better of just using a
horribly verbose loop? Is there a better way to do this kind of thing?

Thanks!

--SegPhault
  Reply With Quote


 


2 1st November 23:36
ryan paul
External User
 
Posts: 1
Default array exists feature



I just realized... to add insult to injury Eiffel doesnt have a break
keyword! How do you folks tolerate it? Is there something i'm missing? The
working alternative to my three line example above would have to be at
least four times as long, as far as I can tell.

-- SegPhault
  Reply With Quote
3 1st November 23:36
berend de boer
External User
 
Posts: 1
Default array exists feature


Ryan> I just realized... to add insult to injury Eiffel doesnt
Ryan> have a break keyword! How do you folks tolerate it? Is there
Ryan> something i'm missing? The working alternative to my three
Ryan> line example above would have to be at least four times as
Ryan> long, as far as I can tell.

a loop should have just one exit point. Makes code easier to read and
change. And perhaps it has implications for proof technology as well.

--
Regards,

Berend.

** you're welcome to the #eiffel irc channel on irc.freenode.net
  Reply With Quote
4 1st November 23:36
berend de boer
External User
 
Posts: 1
Default array exists feature


Ryan> I know that eiffel doesnt really have anonymous functions
Ryan> (I'm aware that the standard does define them but nobody
Ryan> likes the syntax) so how do I use 'exists' to concisely
Ryan> perform this operation without having to use a loop? Do I
Ryan> have to create an external function? I'm I better of just
Ryan> using a horribly verbose loop? Is there a better way to do
Ryan> this kind of thing?

It would be nice if containers would export a for_each feature. I'm
sure Gobo will get it when we get agents in VisualEiffel.

But indeed, you have to write a feature to do this. The advantage is
that the feature could be reused, redefined in a descendent, and
equipped with DbC.

--
Regards,

Berend.

** you're welcome to the #eiffel irc channel on irc.freenode.net
  Reply With Quote
5 1st November 23:36
roger browne
External User
 
Posts: 1
Default array exists feature


It's a tough job, but someone has to do it.


As Berend has explained, there are some advantages to a "one-entry, one-
exit" control structure (readability, understandability,
maintainability, provability etc). The downside is that you sometimes
need an extra if-instruction, or a duplicated call-instruction.

For many people, the advantages exceed the downside. For other folks,
there is Java, C, etc.

Regards,
Roger Browne
  Reply With Quote
6 1st November 23:36
External User
 
Posts: 1
Default array exists feature


Break is a thinly-disguised goto.

Living without spaghetti code is not something I tolerate, it's
something I seek out.

In the 20 years since I first learned this tenet of Structured
Programming 101, I've never seen a C-style or Pascal-style 'for' loop
that wasn't clearer after the 'break' had been removed.

Structured loops often require just as few lines of code as their
spaghetti-break equivalent. I say this from experience, having
refactored 'break' out of hundreds of loops over the years.

- Peter Gummer
  Reply With Quote
7 1st November 23:37
ryan paul
External User
 
Posts: 1
Default array exists feature


It certainly is, but state variables are essentially doing the same thing,
but with much less syntactic grace. For my example, I'm going to use
explicit return instead of break. The argument is really the same...

lets compare:

for user in users do
if user.name = blah then
return true
end
end

now in eiffel:

from i := users.lower until (i = users.count or Result = true) loop
if (users @ i).name = blah then
Result := true
end

i := i + 1
end

The eiffel version still essentially does a break, but it does it based
on a condition specified at the beginning of the loop. The problem gets
progressively worse as you try to add more until conditions. It's really
nasty when you use integers for instance, instead of bools, and some of
the values returned are generated programmatically:

for user in users do
if user.name.count > 3 then
return 2
end

if user.name = blah then
return 5 * 2
end
end

from i := users.lower until (i = users.count or
Result = 2 or Result = (5 * 2)) loop
if (users @ i).name.count > 3 then
Result := 2
end

if (users @ i).name = blah then
Result := 5 * 2
end

i := i + 1
end

In this particular case you can use a predicate like Result /= 0, but
there are going to be situations where you just cant do that.

How do you write the eiffel style loop so that it is both more clear and
concise than my psuedo-code alternative? Manual incrementation also seems
like an unnecessary pain. I think of it much the same way I think of
memory management - its something that the compiler should abstract out.

I dont mean to be an argumentative troll, i'm just trying to understand.
CQS seemed totally inane until somebody explained the advantages and
I'm not willing to dismiss the possibility that there are good reasons for
some of eiffel's other seeming deficiencies as well.
  Reply With Quote
8 11th November 07:10
peter horan
External User
 
Posts: 1
Default array exists feature


In ISE Eiffel:
================================
users: ARRAY[USER]

my_feature (s: STRING) is
do
users.linear_representation.do_if (agent action (?),
agent name_matches(?, s))
end

action (user: USER) is
do
io.put_string("Name = " + user.name.out +
" Value = " + user.value.out + "%N")
end

name_matches(user: USER; s: STRING): BOOLEAN is
do
Result := user.name.is_equal (s)
end
===============================
It would be nice to write
do_if (agent instruction, agent conditional expression)
--
Peter Horan School of Information Technology
peter@deakin.edu.au Deakin University
+61-3-5227 1234 (Voice) Geelong, Victoria 3217, AUSTRALIA
+61-3-5227 2028 (FAX) http://www.cm.deakin.edu.au/~peter

-- The Eiffel guarantee: From specification to implementation
-- (http://www.cetus-links.org/oo_eiffel.html)
  Reply With Quote
9 11th November 07:10
ryan paul
External User
 
Posts: 1
Default array exists feature


Similar to what I ended up doing with smarteiffel:

state_username (s:STRING) is
do
if users.exists(agent username_is(?,s)) then
-- ...
else
-- ...
end
end

username_is (u:USER; s:STRING): BOOLEAN is
do
Result := u.username = s
end
  Reply With Quote
10 11th November 07:10
External User
 
Posts: 1
Default array exists feature


No, the Eiffel example does not do a break. Its loop has a single exit
point. The first example has two exit points.

By the way, your example reminds me of the straw-man arguments in
favour of 'break' and 'return' found in Martin Fowler's Refactoring
book. Like Fowler, you do a lot more than just compare the
single-exit-point version with its multiple-exit-point equivalent. You
have made the multiple-exit version simpler by using some kind of
syntactic sugar in the 'for' construct that eliminates the need for
index variables. You have also made the single-exit version
unnecessarily complex; I would write:
from i := users.lower until i > users.count or Result loop
Result := (users @ i).name = blah
i := i + 1
end

Let's see you more complex examples now:


Now that spaghetti's really cookin'!


Code like this is crying out for some better form of abstraction. In
this particular case, I think that 'users' should be of a class that
has a function encapsulating the logic currently expressed in the body
of this loop.

The main thing that happens when you get out of the multiple-exit-point
mindset is that you start regarding big ugly conditionals, like the one
above, as a sign that you should be looker for a cleaner abstraction.
Sometimes it's as simple as the 'Result /= 0' insight that you
mentioned. Other times there's a function just waiting to be
discovered. Sometimes there's a whole new class just trying to burst
into existence.

I'm pretty sure this is the point that people like Wirth were getting
at, 35 years ago. I've found that it works in practice.


I have to agree with you there. It's a different issue, but definitely
related. I programmed C# for a couple of years, and I fell in love with
'foreach', which looks almost identical to your pseudo-code 'for'.
There is a danger to 'foreach', however: it's unsafe if the collection
is modified during iteration. This leads to subtle, hard-to-detect bugs.

understand.

I'm glad you're asking too. I often have difficulty convincing people
that break = goto. Everyone seems to know that goto is bad, but few
seem to remember why. I appreciate the opportunity to question whether
this 35-year-old wisdom has somehow become obsolete.

- Peter Gummer
  Reply With Quote
Reply


Thread Tools
Display Modes




666