From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,de7dd126d6737f3a X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!feeder.news-service.com!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Ludovic Brenta Newsgroups: comp.lang.ada Subject: Re: Callback in Ada Date: Sat, 27 Nov 2010 11:22:23 +0100 Organization: A noiseless patient Spider Message-ID: <87bp5boylc.fsf@ludovic-brenta.org> References: <8lc2d0Fb6jU1@mid.individual.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx01.eternal-september.org; posting-host="j4YxrvVpIXn8pN+4VgMnVw"; logging-data="2746"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Ceqd0Iok6of3nKfcMcpVw" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) Cancel-Lock: sha1:yDJKmfejqHEEFR89OwnSggphB0w= sha1:lFHmHhdLbXtkdQeCelrf9VuOcQ8= Xref: g2news2.google.com comp.lang.ada:16645 Date: 2010-11-27T11:22:23+01:00 List-Id: Georg Maubach writes: > Hi All, > > today I learnt what a callback function is and also how it is used in > Python. I have tested the following code which runs in Python: > > def apply_to (function, valueList): > resultList = [] > > if __debug__: print "Calling function ", function > > for value in valueList: > if __debug__: print "value: ", value > r = function (value) > if __debug__: print "result: ", r > resultList.append(r) > > return resultList This function "apply_to" is a classic example of a "passive iterator". This example is not type-safe; apply_to assumes that function takes exactly one argument and returns exactly one result. What happens if you pass a function that takes zero or two arguments? Or if it does not return anything? > How would I do that in Ada? There are several ways, most of them type-safe. Statically compiled, see ARM 12.1(24) for this example: generic type Item is private; type Vector is array (Positive range <>) of Item; with function Sum(X, Y : Item) return Item; package On_Vectors is function Sum (A, B : Vector) return Vector; function Sigma(A : Vector) return Item; Length_Error : exception; end On_Vectors; The body is in 12.2 and an example instantiation in 12.3(25). The Ada containers library provides several examples of dynamically bound callbacks, e.g. in Ada.Containers.Vectors (A.18.2(74/2)): procedure Iterate (Container : in Vector; Process : not null access procedure (Position : in Cursor)); The above is another classic example of a passive iterator. In both of these cases, the compiler enforces type safety between the elements in the vector, the arguments passed to the function, etc. In the static (generic) case, the compiler makes it impossible to call the iterator without a callback; in the dynamic case, the compiler cannot always check at compile time, so it inserts a run-time check. A third, type-unsafe way to pass callbacks, is to use addresses, e.g: type Array_Of_Items is array (Positive range <>) of Item; procedure For_Each_Element (Of_Array : in Array_Of_Items; Action : in System.Address) is procedure Act (On_Item : in out Item; At_Index : in Positive); for Act'Address use Action; begin for J in Of_Array'Range loop Act (On_Item => On_Array (J), At_Index => J); end loop; end For_Each_Element; Apart from passive iterators, callbacks are heavily used in GUI programming. You can find many examples of callbacks in the "slot/signal" model of GtkAda. There are alternatives to callbacks; for example I believe Claw and Qt use overriding primitive operations instead of callbacks. -- Ludovic Brenta.