Tuples, iterators, and multiple return values in Eiffel?
Author |
Message |
Ulrich Win #16 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
[...] Quote: > However, I have a few comments, especially regarding the TUPLE/ROUTINE > proposal. First, I agree that the introduction of TUPLE cleans up some > problematic areas in the language (like manifest arrays having no > specific type). I am, however, not particularly convinced that the
Waht about an extension like ``<<1,2,3>>[INTEGER]'' to enforce all elements to conform to INTEGER (during compilation). Thus you'd get an ``ARRAY[INTEGER]''. To maintain compatibility with the existing implementation, one yould state that the type in square brackets defaults to the target type if omitted. [...] Regards, Ulrich
|
Mon, 26 Mar 2001 03:00:00 GMT |
|
|
David Clar #17 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
-- David Clark University of Canberra
Quote: > Dan Higdon: > > Repeated inheritance from a deferred class can simulate > > "function pointer" semantics well, as demonstrated in the iterator > > discussion of ETL. > Can it? You still cannot pass "function pointers" around. E.g. if you > have a COMMAND class with a single deferred feature 'execute', you can > inherit repeatedly, but you cannot pass multiple COMMAND references to > other parts of system -- all the COMMAND references you can extract will > call the implementation of 'execute' that is select-ed in the repeatedly > inheriting class.
In particular, this means that you can't implement the gang of four SimpleCommand. (Simplecommand doesn't require arguements, see Design Patterns, p240.) Hence you can end up with a proliferation of commands. However, I am in general reluctant about feature creep in a language to solve few problems - it reminds me too much of the common beaucratic practise of inventing a new rule for every administrative foul up. David
|
Tue, 27 Mar 2001 03:00:00 GMT |
|
|
Roger Brow #18 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
Quote:
> Repeated inheritance from a deferred class can simulate > "function pointer" semantics well...
> Can it? You still cannot pass "function pointers" around. E.g. if you > have a COMMAND class with a single deferred feature 'execute', you can > inherit repeatedly, but you cannot pass multiple COMMAND references to > other parts of system -- all the COMMAND references you can extract will > call the implementation of 'execute' that is select-ed in the repeatedly > inheriting class.
Franck is right. If you have feature replication under repeated inheritance you must use "select". If you use select, then you get anomalies in the presence of dynamic binding and polymorphism. Dan Higdon continued: Quote: > ...as demonstrated in the iterator discussion of ETL.
The example in ETL 2nd printing pages 174-177 has never worked on any Eiffel compiler. Sure, the compiler and/or language could be hacked to make this example work, but this would just squeeze the amiguities one class higher in the inheritance heirarchy. Quote:
> However, I am in general reluctant about feature creep in a language to > solve few problems...
Absolutely. So the answer here is to _remove_ feature replication and the "select" clause from the language. ETL pages 190-191 (the section marked with the "comment" box) describes a consequence of feature replication under repeated inheritance. Consider these classes: class A feature f / \ class B class C inherit A inherit A redefine f redefine f \ / class D inherit B rename f as bf inherit C rename f as cf select cf Now consider this code: b: B ... b.f Which version of 'f' is called? Not the one from class B, but the one from class C (because of the "select" clause in class D). The version from class C naturally cannot in general even be expected to maintain the invariant of class B! Suppose our original system included only classes A and B. Then the call "b.f" calls B's version of 'f'. Later we add classes C and D, and the behaviour of b.f suddenly changes! This just isn't consistent with a language which aims to promote correct software. With the addition to Eiffel of the precusor construct, and the suggested addition of ROUTINE classes, I can't see any reason to retain the pretense of feature replication under repeated inheritance. Regards, Roger
|
Tue, 27 Mar 2001 03:00:00 GMT |
|
|
Loryn Jenkin #19 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
Quote:
> > However, I am in general reluctant about feature creep in a language to > > solve few problems...
(I'd hardly think making this work correctly is 'feature creep'. Eiffel has had feature replication for a very long time now.) Quote: > Absolutely. So the answer here is to _remove_ feature replication and the > "select" clause from the language.
Even though the bathwater seems murky, let's not throw it out, it may contain our baby! Quote: > Which version of 'f' is called? Not the one from class B, but the one > from class C (because of the "select" clause in class D). The version > from class C naturally cannot in general even be expected to maintain the > invariant of class B!
This seems distressingly broken. However, I think you'd find that breaking the invariant is rare (if not impossible), because both C's and B's invariants must be satisfied in D. The point Roger makes echoes Bertrand's flagging of it in ETL on page 180, with the actual code being displayed at the foot of page 178. Current problems with feature replication and dynamic binding ------------------------------------------------------------- 1. In the context of the problem Roger raised, calls to b.f when b is dynamically bound to an instance of D executes C.f. 2. Franck reports that in some circumstrance calls to `f' and `Current.f' can execute different features. (I don't understand what context will cause this, though.) 3. Magic rebinding not intended to be deep. (! Again, something I don't understand.) 4. It's impossible to get more than one part object. (! Another thing I don't understand. Although, I suspect it refers to point 4.) 5. Calls from replicated features to replicated attributes fail to 'stick' to their partner feature. Instead, they are applied to the attribute chosen in the `select' clause. (Yuck!) Here is my proposal to 'fix' feature replication in the face of dynamic binding: Proposal: Introduce notion of "Dynamic Seed" -------------------------------------------- ETL defines the notion of a 'seed' as the origin of a feature (henceforward known as "seed of origin"). Where dynamic binding is in play, the select clause currently arbitrates between which inheritor of the seed is "closer" to the seed. [My interpretation of ETL.] In the case that both Roger and Bertrand identify, I believe it is the notion of the select clause arbitrating between the inheritors of the original seed that causes the problem. Instead, I would have the select clause arbitrate *only* between inheritors of the "dynamic seed", where dynamic seed is defined as follows. Dynamic Seed (definition): A feature identified in class declaration is known as the dynamic seed. It is not the seed of origin for the feature. But the seed of origin is not important: what is important is conformance to the declared (ie dynamic) seed. Dynamic Seed (examples): Given the situation in ETL pages 178-180 (and quoted by Roger, in the previous post), the seed or origin is plainly A.f. However, where Roger writes, b: B ... b := d ... b.f the "dynamic seed" is in fact B.f. Given that there is no competition for proximity to the dynamic seed, the select clause in D can be completely ignored. The call to `b.f' yields, through dynamic binding, execution of D.bf, otherwise known as B.f. The select clause need only be invoked when there is ambiguity between features vis a vis proximity to the dynamic seed. Such an ambiguity would only occur (in this particular case) with a call: A: a ... a := d ... a.f In this case, it is quite unambiguous that the call will result in execution of D.cf (otherwise known as C.f). Quite clearly, using these rules Franck's point about calls to f and Current.f should be solved, (even though I don't know why it would exist in the first place) because the dynamic seed of `f' is 'f' itself, and the select clause wouldn't be invoked. You could, however, invoke the select clause with the following (in class D): ... (in some feature) a: A ... a := Current a.f f ... But then, that's what you asked for! Proposal: Select clause clarification ------------------------------------- (1) The select clause exists solely for the purpose of resolving which feature is called in the face of dynamic binding. Where dynamic binding is not at play, the select clause is completely ignored. [This flags the fact that current interpretations by compilers in case 5. would be incorrect.] (2) The select clause is used to arbitrate between features when both vie for the primary role of being closer to the dynamic seed. The select clause is not consulted in order to arbitrate between claims to the original seed, except where the original seed is also the dynamic seed. Now, I'm not sure, but this proposal doesn't seem to shed much light on fixing problem 5. Unless someone can demonstrate that this proposal already contains the solution, I would propose another rule: (3) Where a replicated routine calls (or assigns to) another replicated feature (as specified in the text of the ancestor class), it will be inherited as calling the feature named in the same inheritance clause. [Of course, if it is redefined, the redefinition calls the feature named in *this* class; again having nothing to do with the `select' cluse.] In other words, when you have this going on: REPL_A select set_attr, attr end REPL_A rename set_attr as set_attr1, attr as attr1 end set_attr will assign to attr; and set_attr1 will assign to attr1. AND, when the select is reversed, the result is still the same: REPL_A REPL_A rename set_attr as set_attr1, attr as attr1 select set_attr1, attr1 end set_attr will assign to attr; and set_attr1 will assign to attr1. By corrolary, when you examine these rules, the following falls out: (4) Where a non-replicated routine calls (or assigns to) a replicated feature (as specified in the text of the ancestor class), it will be inherited as calling the feature named in the select clause. I actually don't think this needs to be a special rule, because I think the dynamic seed is clearly the feature in the ancestor class, and it needs resolving by the select clause anyway. It's good for explanation of how the mechanism should work, and stands in contrast to (3). ---------- Clearly, I didn't understand some of the points that Franck raised (namely, 2, 3, 4). However, I think you'll find that these emendations to the rules solves a number of problems inherent in replication and dynamic binding. I hope it doesn't introduce any of its own. I think whether or not the ROUTINE proposal is accepted, this aspect of replication should be addressed. I don't think replication should be outlawed, because I suspect the rules that would need to be enforced would be as troublesome as the current rules (wrt. class design, rather than language definition). As for Franck claiming that current Eiffel programmers don't need feature replication / iterating-several-actions, I recently documented four instances in which I wnated to use it (but couldn't). I also note that myself, Patrick Doyle, Ted Velkoff, Dan Higdon, and numerous others over the years have posted to c.l.e., asking why their code wasn't working as described in ETL. I suggest we clean this issue up, whether or not we also accept the ROUTINE proposal. Loryn Jenkins PS: Sorry for my poor drafting. I've never attempted to write language rules before.
|
Wed, 28 Mar 2001 03:00:00 GMT |
|
|
Bertrand Meye #20 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
I greatly appreciate the feedback on these proposals. For lack of time I can only write a short answer, which addresses only some of the questions and does not name individual commenters. No offense is meant to them and their thoughtful comments; it's just that there are only 24 hours a day. (Not added during proofreading: well, the note turned out not that short after all.) 1. It is really not true that the introduction of these mechanisms violates the principle that "there should be one good way to do anything". You will now be able to write the following: my_list: LINKED_LIST [SOME_TYPE] my_action (t: SOME_TYPE) is do ... end my_test (t: SOME_TYPE): BOOLEAN is do ... end ... my_list.do_if (~my_action, ~my_test) to apply `my_action' to every element of the list, or, if the routines have more arguments, something like my_list.do_if (~my_action, ~my_test, action_arg1, action_arg2, test_arg) Of course you can achieve the same effect with the current language, but not as nicely. 2. Very important: Contrary to what has been written, there is NO contradiction between routine objects and the technique, popular in Eiffel, of using command classes (see EiffelVision, EiffelBuild, chapter 20 of "Object-Oriented Software Construction", 2nd edition). Having routine objects simplifies command classes and makes them much more effective. The technique is used extensively in the new version of EiffelVision (described in an earlier message of today). Routine objects make command classes very nice and effective, simplifying the writing of the application by eliminating the need for many auxiliary classes. 3. Even the creation expression mechanism does not violate the "one good way" principle. Creation expressions are mainly useful for passing arguments. For creating an object attached to an attribute or local entity it's nicer to write `create x.make (...)' than using a creation expression and an assignment, since you don't need to specify the type if it's the one declared for `x'. 4. An argument for tuples is that they establish a better symmetry between routine arguments and results, which I think is good. As a special case this makes it possible to have functions with multiple return values without introducing a class just for that purpose. (It may be argued that this is not O-O enough; indeed using a tuple result is not a substitute for defining the right abstraction -- the right class -- when that abstraction does make sense on its own. But there are cases in which a tuple result seems the right approach, and defining a special class might be overkill. Think for example of a division operation (not necessarily on integers) that returns a pair <<quotient, remainder>>.) 5. Another nice application of tuples is for output operations. Formated output, for example, is nicely handled by tuples (although it can of course be dealt with in the current language). 6. As pointed out in the proposal, manifest arrays are in the current language the only kind of construct that doesn't have a clearly defined type (a manifest array actually has a set of types). This is an elegance concern rather than a practical problem (as the type rules for manifest arrays are safe and unambiguous), but it's nice to have it resolved. 7. The above points seem to confirm that we have a language extension that does satisfy one of the principal requirements: solving several problems at once, not just providing an ad hoc solution to one perceived concern. 8. Tuple-based iterators are not redundant with the proper implementation of replication under repeated inheritance. The latter has not been a major customer priority until now but of course it will be done. 9. It is true that `item (i)' for a tuple can only be declared as returning ANY, so that assignment attempt is needed to do something useful with the result. We have envisioned including well-typed functions `first', `second', `third', `fourth' and `fifth' (introduced respectively in TUPLE [X], TUPLE [X, Y] etc., hence declared as returning X, Y etc.). We have had the comment "why stop at 5?" (indeed, this is an arbitrary limit) and the suggestion of having an infinite set of features item_1, item_2 etc. with the proper types, which would have to be known to the compiler since they are really fictitious (if I can use these two words together). I have mixed feelings about this idea and would appreciate opinions about it. 10. The general idea behind the tuple etc. proposal is to provide more "meta" facilities for Eiffel. This is not a new idea; Roger Rousseau from the University of Nice has been lobbying me to do something like this for something like ten years. Richard Bielak and Nick Leaton have more recently started an independent effort with a similar goal, which I haven't had time to study yet. I think it's clear that a successful extension in this direction will not just address pet peeves but significantly elevate the expressive power of the language. Of course the trick is in "successful", which is what this discussion is all about. 11. We are very customer-driven. The catalysis for the tuple, routine object and iterator design was the request of a large customer -- a company which had convincing arguments that it needed some better ways of defining iterators. I am not using this observation as a shield, as I would never suggest a language change with which I disagree, whatever the customer, but simply to indicate that these mechanisms are not just the effect of too much summer sun on my restless mind. As another testimonial, Paul Dubois (referring to his work for the design and implementation of the EiffelMath library, http://eiffel.com/products/math.html, discussed in his book "Object Technology for Scientific Computing", Prentice Hall, see http://eiffel.com/doc/documentation.html#otsc) commented rather forcefully, when I presented the new constructs at TOOLS USA a few weeks ago, that he would really have liked to have them available when he did that work. I take this as evidence for both of the conjectures underlying this message: that it was possible, to work without the new mechanisms -- since EiffelMath is a very successful design; but also that the new mechanisms are powerful and desirable. 12. Eiffel as a language has been incredibly stable. The last significant language revision dates back to 92 (finalized over the following two years). Even that revision was a fairly incremental update of the original September 1985 version. Since 1990 most other languages have either gone away or undergone major revisions, and many are still changing all the time. During that time, of course, the computer industry has continued to experience constant upheaval. I take the stability of Eiffel's original ideas (and the fact that when an extension is proposed so many people react skeptically on comp.lang.eiffel) as a token of their success and adequacy. But after 8 years or so of almost total stability, it is not unreasonable to start looking at new, better ways of doing things, being very careful not to destroy the edifice, submitting every proposal to intense scrutiny, trying out implementations before finalizing the ideas, and taking account of every criticism. That's what we are trying to do right now. I intend to keep the process open and to continue discussing all issues within NICE and on comp.lang.eiffel, as was done (regarding the latter -- NICE wasn't in operation) between 1989 and 1991 for the greatest benefit of the Eiffel community. -- Bertrand Meyer, Interactive Software Engineering ISE Building, 2nd Floor, 270 Storke Road Goleta, CA 93117 USA 805-685-1006, Fax 805-685-6869,
|
Thu, 29 Mar 2001 03:00:00 GMT |
|
|
Reimer Behren #21 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
[...] Quote: > 1. It is really not true that the introduction of these mechanisms > violates the principle that "there should be one good way to do > anything". You will now be able to write the following: > my_list: LINKED_LIST [SOME_TYPE] > my_action (t: SOME_TYPE) is do ... end > my_test (t: SOME_TYPE): BOOLEAN is do ... end > ... > my_list.do_if (~my_action, ~my_test) > to apply `my_action' to every element of the list, or, if the routines > have more arguments, something like > my_list.do_if (~my_action, ~my_test, action_arg1, action_arg2, test_arg) > Of course you can achieve the same effect with the current language, > but not as nicely.
I have no problem with something like: class ACTION [T] feature { ANY } action(arg: T) is deferred end -- action end -- class ACTION class CONDITIONAL_ACTION [T] inherit ACTION [T] feature { ANY } test(arg: T): BOOLEAN is deferred end -- test execute(arg: T) is deferred end -- execute action(arg: T) is do if test(arg) then execute(arg) end end -- action end -- class CONDITIONAL_ACTION Then create subclasses from that. I do not see what about this approach is lacking elegance. In fact, it seems to result in a more powerful framework than the function pointer approach. Quote: > 2. Very important: Contrary to what has been written, there is NO > contradiction between routine objects and the technique, popular > in Eiffel, of using command classes (see EiffelVision, EiffelBuild, > chapter 20 of "Object-Oriented Software Construction", 2nd edition). > Having routine objects simplifies command classes and makes them > much more effective. The technique is used extensively in the new > version of EiffelVision (described in an earlier message of today). > Routine objects make command classes very nice and effective, > simplifying the writing of the application by eliminating the > need for many auxiliary classes.
I would like to point you to http://x10.dejanews.com/getdoc.xp?AN=104894350 This is an article with the Subject "Re: no function pointers in Eiffel", written by you, and arguing the exact opposite position. I also note that the article mentions EiffelMath, which you give further below as an example of a library that would have benefited from the extension. So I would like to know what changed your mind. Note: This is not meant as a personal attack; only fanatics never change their opinions. But your change in position is so dramatic that I'd really like to know what caused it. Quote: > 3. Even the creation expression mechanism does not violate the "one > good way" principle. Creation expressions are mainly useful for > passing arguments. For creating an object attached to an attribute > or local entity it's nicer to write `create x.make (...)' than using > a creation expression and an assignment, since you don't need to specify > the type if it's the one declared for `x'.
Hmm. I didn't see anything about creation expressions anywhere in either proposal (correct me if I'm wrong). However, I _do_ remember a forceful argument against them in ETL (sorry, can't give a page reference; my copy is still in Germany). You basically argued (I'm paraphrasing) that every instance of such a creation expression for a type T could be replaced by a function call new_T; and that introducing this additional language feature would violate the "one good way" principle. In fact, if I remember correctly, this was your most prominent example. Quote: > 4. An argument for tuples is that they establish a better symmetry between > routine arguments and results, which I think is good. As a special case > this makes it possible to have functions with multiple return values without > introducing a class just for that purpose. (It may be argued that this is not > O-O enough; indeed using a tuple result is not a substitute for defining > the right abstraction -- the right class -- when that abstraction does > make sense on its own. But there are cases in which a tuple result > seems the right approach, and defining a special class might be overkill. > Think for example of a division operation (not necessarily on integers) > that returns a pair <<quotient, remainder>>.)
class DIVISION_RESULT [T -> NUMERIC] creation make feature { ANY } -- creation make(a_quotient, a_remainder: T) is do quotient := a_quotient remainder := a_remainder end -- make feature { ANY } -- attributes quotient: T remainder: T end -- class DIVISION_RESULT Personally, I don't have any problem with this. In fact, one nice thing about Eiffel has always been that there were pretty much no complex anonymous entities, because you always had to give names to concepts. I would also like to point out that it makes the postcondition of a division operation far more readable if you can write: ensure is_equal(Result.quotient * divisor + Result.remainder) rather than: ensure is_equal(Result.first * divisor + Result.second) where due to the anonymity of the names it is easy to confuse both. Given that pre-/postconditions also serve as documentation, this is an important aspect. The same applies to _using_ the result, of course. I don't want to ask myself all the time: "Is x.first the quotient or the remainder?" Quote: > 5. Another nice application of tuples is for output operations. > Formated output, for example, is nicely handled by tuples (although > it can of course be dealt with in the current language).
I have no problems whatsoever with using manifest arrays for this purpose; in fact, I do not see what tuples gain you here. But I'd really like to see an in-depth explanation. Quote: > 6. As pointed out in the proposal, manifest arrays are in the current > language the only kind of construct that doesn't have a clearly > defined type (a manifest array actually has a set of types). This > is an elegance concern rather than a practical problem (as the type rules > for manifest arrays are safe and unambiguous), but it's nice to have > it resolved.
I would add that it also makes reasoning about the language easier. I have no problems with that part. But that does not in itself provide sufficient incentive for a language change. Quote: > 7. The above points seem to confirm that we have a language extension that > does satisfy one of the principal requirements: solving several problems > at once, not just providing an ad hoc solution to one perceived concern.
Frankly, I do not see what problems it solves any better than the current approach. [...] Quote: > 9. It is true that `item (i)' for a tuple can only be declared as > returning ANY, so that assignment attempt is needed to do something > useful with the result. We have envisioned including well-typed > functions `first', `second', `third', `fourth' and `fifth' (introduced > respectively in TUPLE [X], TUPLE [X, Y] etc., hence declared as > returning X, Y etc.). We have had the comment "why stop at 5?" > (indeed, this is an arbitrary limit) and the suggestion of having an > infinite set of features item_1, item_2 etc. with the proper types, > which would have to be known to the compiler since they are really > fictitious (if I can use these two words together). I have mixed > feelings about this idea and would appreciate opinions about it.
Well, that wouldn't be too different from the BIT n "magic". I agree that I don't feel too comfortable with it, either. In any event, that is a concern that arises _once_ it has been demonstrated that TUPLE is a useful addition to the language. Quote: > 10. The general idea behind the tuple etc. proposal is to provide more > "meta" facilities for Eiffel. This is not a new idea; Roger Rousseau > from the University of Nice has been lobbying me to do something like > this for something like ten years. Richard Bielak and Nick Leaton have > more recently started an independent effort with a similar goal, which > I haven't had time to study yet. I think it's clear that a successful > extension in this direction will not just address pet peeves but > significantly elevate the expressive power of the language. Of course > the trick is in "successful", which is what this discussion is all > about.
I cannot comment on this, as the ROUTINE/TUPLE proposal then obviously is a small piece of a much larger picture. If Eiffel is to be extended to include a number of meta facilities, I'd prefer to see the entire proposal first before I discuss individual facets of a complex mosaic. Quote: > 11. We are very customer-driven. The catalysis for the tuple, routine object > and iterator design was the request of a large customer -- a company which had > convincing arguments that it needed some better ways of defining > iterators. I am not using this observation as a shield, as I would never > suggest a language change with which I disagree, whatever the customer, > but simply to indicate that these mechanisms are not just the effect of > too much summer sun on my restless mind.
I do have a problem with this statement; obviously, "we" does not refer to NICE, as NICE doesn't have customers. On the other hand, if "we" refers to ISE, is NICE supposed to accept extensions implemented at ISE as a fait accompli? Or will NICE Eiffel and ISE Eiffel eventually diverge? [...] Quote: > 12. Eiffel as a language has been incredibly stable. The last significant > language revision dates back to 92 (finalized over the following two > years). Even that revision was a fairly incremental update of the > original September 1985 version. Since 1990 most other languages > have either gone away or undergone major revisions, and many are > still changing all the time. During that time, of course, the computer > industry has continued to experience constant upheaval.
I think most Eiffel programmers both like this stability and don't mind having the language reevaluated. However, the proposed extensions seem to herald a change in direction -- towards a different Eiffel. Allow me to
... read more »
|
Fri, 30 Mar 2001 03:00:00 GMT |
|
|
Roy MacLea #22 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
Quote:
> [...] > > 10. The general idea behind the tuple etc. proposal is to provide more > > "meta" facilities for Eiffel. This is not a new idea; Roger Rousseau > > from the University of Nice has been lobbying me to do something like > > this for something like ten years. Richard Bielak and Nick Leaton have > > more recently started an independent effort with a similar goal, which > > I haven't had time to study yet. I think it's clear that a successful > > extension in this direction will not just address pet peeves but > > significantly elevate the expressive power of the language. Of course > > the trick is in "successful", which is what this discussion is all > > about. > I cannot comment on this, as the ROUTINE/TUPLE proposal then obviously > is a small piece of a much larger picture. If Eiffel is to be extended > to include a number of meta facilities, I'd prefer to see the entire > proposal first before I discuss individual facets of a complex mosaic.
I would say that Eiffel has, so far, taken a fairly extreme 'non-meta' position, and Bertrand has expounded various cogent arguments for this. So if the language changes discussed previously are indeed part of a 'general idea ... to provide more "meta" facilities for Eiffel', then as Reimer says, it would be helpful for Bertrand to outline the nature and scope of this idea. From what I've seen so far, the Tuple, Routine Object, etc, proposals seem considerably more radical than, say, the Precursor construct, or the generic type creation proposals (fine by me). In anticipation... Regards Roy macLean
|
Fri, 30 Mar 2001 03:00:00 GMT |
|
|
Alexander Kogtenko #23 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
... Quote: > 9. It is true that `item (i)' for a tuple can only be declared as returning ANY, > so that assignment attempt is needed to do something useful with the result. > We have envisioned including well-typed functions `first', `second', `third', > `fourth' and `fifth' (introduced respectively in TUPLE [X], TUPLE [X, Y] etc., > hence declared as returning X, Y etc.). We have had the comment "why stop at 5?" > (indeed, this is an arbitrary limit) and the suggestion of having an infinite > set of features item_1, item_2 etc. with the proper types, which would have > to be known to the compiler since they are really fictitious (if I can use > these two words together). I have mixed feelings about this idea > and would appreciate opinions about it.
... Class TUPLE represents lists of objects, so it may provide usual "list" operations: head: "type of the 1st parameter" is require not_empty: count > 0 tail: TUPLE [2nd parameter type, 3rd parameter type, ...] is require not_empty: count > 0 ensure proper_result: ( count = 1 implies Result = Void ) and then ( count > 1 implies Result /= Void ) So for TUPLE[X, Y, Z] we will have head: X tail: TUPLE [Y, Z] This will solve the problem mentioned above in a uniform way. Though the fifth element of the tuple 'x' will be denoted as x.tail.tail.tail.tail.head in most cases we will need only a few first elements. Feature 'tail' may be either a function (as shown above) or a procedure (to avoid creation of the new object). -- Alexander Kogtenkov Object Tools, Moscow
|
Fri, 30 Mar 2001 03:00:00 GMT |
|
|
Alexander Kogtenko #24 / 35
|
Tuples, iterators, and multiple return values in Eiffel?
I would like to clarify the following situation with TUPLE: What is the type of << 1, Void, "a" >>? Accordingly to the definition, it is TUPLE [ INTEGER, NONE, STRING ]. Am I correct? Thanks, -- Alexander Kogtenkov Object Tools, Moscow
|
Fri, 30 Mar 2001 03:00:00 GMT |
|
|
Page 2 of 3
|
[ 35 post ] |
|
Go to page:
[1]
[2] [3] |
|