Path: news.daimi.aau.dk!news.daimi.aau.dk!eernst From: eernst@fraxinus.daimi.aau.dk (Erik Ernst) Newsgroups: comp.lang.beta Subject: Re: BETA-Syntax (Pattern variable and component). Date: 16 Oct 1995 21:44:25 GMT Organization: DAIMI, Computer Science Dept. of Aarhus Univ. Lines: 170 Distribution: world Message-ID: References: <43udur$3cr@fbi-news.Informatik.Uni-Dortmund.DE> NNTP-Posting-Host: fraxinus.daimi.aau.dk In-reply-to: zardi@margot.informatik.uni-dortmund.de's message of 22 Sep 1995 13:33:15 GMT In article <43udur$3cr@fbi-news.Informatik.Uni-Dortmund.DE> zardi@margot.informatik.uni-dortmund.de (Ahmed Zardi (LS4)) writes: 1- A pattern variable in BETA has the following syntax. F : ##P; where P (: (# ..... #);) is a pattern. we have a following situation. T : @P; A pattern variable assignment has the form T## -> F## I ask why has the syntax not the form T -> F. (Its known that F is a pattern variable and T is a pattern) And Kai Petzke already answered. I can't resist adding something to this discussion, though, as it's a nice opportunity for me to make a number of people angry ;-);-);-) Well, I think that 'T' denotes an object, but the question is equally interesting whether we talk about "T## -> F##" or "P## -> F##". I like to think about this in the following way: BETA makes implicit coercions in a lot of places to produce the kind of entity that you normally wish to obtain at that point. So if you have a dynamic reference to an object it'll automatically get coerced into the object referred, someThing: (# t1: @text; t2: ^text; do t1[]->t2[]; (* preparations .. *) t1.newline; (* remote access on an object *) t2.newline; (* .. looks the same as via a reference *) #) as opposed to C(++) (as well as Pascal, Modula-2 and others): some_thing(void) { Text t1,*t2=new(Text(...)); t1.newline; (* the programmer needs to keep track of these *) t2->newline; (* .. gratituous '.' or '->' differences *) } The same goes for references to patterns, someThing: (# pv: ##text; t: ^text; do text##->pv##; (* preparations .. *) &text[]->t[]; (* instantiating from a pattern and *) &pv[]->t[]; (* .. from a pattern reference looks the same *) #) The coercion can consist of more than one step, like in someThing: (# pv: ##text; t1: @text; do t1##->pv##; (* t1: object --> pattern --> pattern_ref *) &pv[]->...; (* pattern_ref --> pattern --> object --> object_ref *) #) BETA programmers are so extremely used to this kind of thing that they (we ;-) don't discover what is actually happening; even the wording x: @text; (* "static reference", not "item" or "object" *) y: ^text; (* "dynamic reference", not "pointer"!! *) suggest that we don't want to know about these differences and the coercions that hide them so well. But we may have more radical coercions, like someThing: (# l: list(# element::whatnot #); do l.scan (# do ... (* what? we can _execute_ an anonymous type? *) #); #) where an object descriptor specializing 'l.scan' suddenly appears in a context where an object is expected! An object descriptor describes the interface and structure of a (potential) set of objects, i.e. it is a type. A quite reasonable reaction to this challenge is to coerce the given anonymous type into an object by instantiating it, and that is exactly the meaning of this construct (known in the grammar as an "InsertedItem"). Now we have some syntax to express our desire that the coercions take a specific direction ('ospec' is some attribute denotation or an object descriptor, although the grammar doesn't quite allow this generality .. as yet ;^) ospec (* gimme an object, and execute it *) ospec[] (* gimme an object_ref *) ospec## (* gimme a pattern_ref *) This syntax can be used in the dopart as the grammatical construct "Transaction", for instance as an expression or as an imperative. This explanation makes it make sense to me why "T## -> F##" could not just as well be expressed "T -> F". The existing syntax ensures that different kinds of run-time entities are clearly flagged as such in the source code. To spot an object_ref being assigned or given as a value you just have to look out for "[]". If no expression contains the "[]" syntax (we must remember to check all the statically known enter/exit parts of objects in evaluations, though) then no object_ref is being manipulated. Focus is on the intended _use_, not on the (perhaps ever-changing) choice of implementation/representation. I think this ensures a much better readability. 2- A dynamic component in BETA has the following syntax. A: ^| P; An instance of P my be generated by executing the following imperative. &| P -> A I ask why has the syntax not the form & P -> A (Its known that A is a dynamic component reference) I assume (like Kai) that you mean "&|P[]->A[]" and "&P[]->A[]", making "A" refer to the newly created entity. I don't think that coercion should be influenced by context across '->' in an evaluation. By now it is confined within a small syntactic category (Transaction), and expanding it to automagically create a new _component_ in this context would probably not enhance the readability of the source code. In fact, I think there would be lots of problems in making a thing like that unambiguous, not to mention comprehensible. Quite another discussion is: if we create a new object and make "A" refer to it with "&P[]->A[]", do we have a (compile-time) error, or will we get a (run-time) coercion of this new object into a component? It should be possible to do someThing: (# oref: ^object; cref: ^|object; do &|someThingElse[]->oref[]; (* "down-casting" to object *) oref[]->cref[]; (* "up-casting" to component: run-time checked *) (* 'oref' and 'cref' refer to the same thing, but .. *) cref; (* co-routine attach semantics *) cref; (* .. means continue after 'suspend'ing .. *) oref; (* whereas object execution semantics *) oref; (* .. means starting at the beginning every time *) #) for which we'll generate special code when assigning a component_ref value to an object_ref attribute (different from normal object_ref assignment, that is, but guaranteed to succeed), and moreover generate a run-time check for the opposite direction: "this must be a component even though we refer to it through an object_ref; is it?". Or should we _coerce_ the object into a component? (This would call for a different run-time layout of components/object, but that could be fixed, I'm sure ;-) cheers, -- Erik Ernst eernst@daimi.aau.dk Computer Science Department of Aarhus University, Denmark