tag:blogger.com,1999:blog-10106032.post1610799291532362432..comments2024-03-14T09:24:53.310+00:00Comments on Entropy Overload: Tiburon: fun with generics and anonymous methodsBarry Kellyhttp://www.blogger.com/profile/10559947643606684495noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-10106032.post-68681742741363710372008-09-11T03:16:00.000+01:002008-09-11T03:16:00.000+01:00@daniele - No. Closures capture locations, not val...@daniele - No. Closures capture locations, not values. The behaviour you are seeing is common across Scheme, Ruby, C# (both anonymous methods and lambdas), etc. For example, in Scheme:<BR/><BR/>(define (f x)<BR/> (cons<BR/> (lambda (new-x)<BR/> (set! x new-x))<BR/> (lambda () x)))<BR/><BR/>This defines a function that returns a pair of lambdas, one that gets and one that sets the value of x.<BR/><BR/>(define slot (f 10))<BR/><BR/>This evaluates (f 10) and assigns it to slot. Slot is now a pair of lambdas. I can evaluate it with the getter:<BR/><BR/>((cdr slot))<BR/><BR/>This prints out 10. I can change the value of the captured x with the setter:<BR/><BR/>((car slot) 42)<BR/><BR/>And re-evaluate the getter:<BR/><BR/>((cdr slot))<BR/><BR/>As expected this prints out 42.Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-68912697705312240912008-09-10T23:07:00.000+01:002008-09-10T23:07:00.000+01:00Hi Barry. Thanks for your post. I have a question:...Hi Barry. Thanks for your post. I have a question:<BR/>Closure should get actual local variable value for it's "internal state". In following code I'l expect that got "Hello world" and then "Hello there"... but I'm got "Hello There" (last variable x value) twice... I'm wrong?<BR/><BR/>procedure TForm1.Button5Click(Sender: TObject);<BR/>var<BR/> x: string;<BR/> p1,p2: TProc;<BR/>begin<BR/> x := 'Hello World';<BR/> p1 := procedure begin ShowMessage(x); end;<BR/> x := 'Hello There';<BR/> p2 := procedure begin ShowMessage(x); end;<BR/> p1;<BR/> p2;<BR/>end;Unknownhttps://www.blogger.com/profile/04445257317986095729noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-76946495286230789192008-08-31T11:36:00.000+01:002008-08-31T11:36:00.000+01:00@Jolyon - Mistake in the name is unintentional. So...@Jolyon - Mistake in the name is unintentional. Some time ago, I had mentally pronounced your name as I misspelled it. Sorry.<BR/><BR/>My point re "simple" is that it means something different to what you appear to think it means. Machine code is indeed more simple than a high-level language, because the primitives do less and are easier to understand individually.<BR/><BR/>Similarly, what you describe as simpler than the technique I outlined has primitives which do less and are easier to understand individually, in so far as they are less abstract.<BR/><BR/>However, higher-level abstraction allows writing more "dense" code. Sometimes, the <B>best</B> abstraction to use for a particular situation is passing code as an argument.<BR/><BR/>The example I had here was the problem of creating an enumerable stream. Normally, that requires creating two separate classes, and writing at least 3, if not 4 different methods. I reduced it down to a single method call.<BR/><BR/>You may not see the utility of the example, because you don't see the point of creating enumerable streams (perhaps you have never worked with C# LINQ). However, that criticism is specific to <B>you</B>, and is not general.Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-66775615641446175342008-08-30T23:56:00.000+01:002008-08-30T23:56:00.000+01:00I'm not sure if you are deliberately mis-spelling ...I'm not sure if you are deliberately mis-spelling my name, or why you would, but please note that you are.<BR/><BR/>My words are not "weasel" at all.<BR/><BR/>You seem to be trying to show the benefits of some new language features. I am suggesting that your attempt is falling short because your chosen examples are poor.<BR/><BR/>Applying these language features and techniques in the case of this example results in more complex and harder to follow code, not less and easier to follow.<BR/><BR/>As for the suggestion that the simplest possible implementation is machine code, those certainly are "weasel words".<BR/><BR/>I suspect that you know full well that by "simplest possible" I meant easiest to follow, and a machine code listing would fail that test just as much as your anon methods and generics approach.<BR/><BR/><BR/>My "trollish comment" on your Vista rant was intended as a tongue in cheek bit of light hearted ribbing, given that us "D7 Luddites" were lambasted by *some* CodeGear insiders for not "getting" the new IDE.<BR/><BR/>If a little light hearted ribbing is "trolling" then colour me green and call me "Shrek".<BR/><BR/>:)<BR/><BR/>I rather think you over-reacted.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10106032.post-30491107544139355222008-08-29T11:29:00.000+01:002008-08-29T11:29:00.000+01:00Hi Barry,@IEnumeable vs IEnumerable<T>Well, ...Hi Barry,<BR/><BR/>@IEnumeable vs IEnumerable<T><BR/>Well, you would not *have* to provide the inheritance as in the .Net world.<BR/>Since there is no legacy code that could be using IEnumerable, you could just opt for the generic one as the only one.<BR/>Otherwise an IEnumerable with Current as a Pointer could be possible as well (only used in cases where you don't know the type and thus pointer wouldn't be too bad a type choice).<BR/>IMO forcing class inheritence on collections is a very, very bad thing.<BR/>As an experienced .Net developer you probably came to appreciate the ease in which you can make your methods/classes work with any kind of container. As long as the container implemented either IEnumerable, ICollection<T>, etc...<BR/>Requiring this to be TEnumerable<T> means that *every* container had to be change to inherit from it, as opposed to just implement an interface to make it more usuable for the new Delphi.<BR/><BR/>Don't get this wrong, I think you showed what you're made of with this first compiler of yours. :-)<BR/>Just wanted to get some ideas of my chest...Unknownhttps://www.blogger.com/profile/04907718415714317724noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-82516288825990461692008-08-29T08:14:00.000+01:002008-08-29T08:14:00.000+01:00@Robert - they do not implement IEnumerable<T&g...@Robert - they do not implement IEnumerable<T> / IEnumerator<T> because those interfaces descend from IEnumerable / IEnumerator, and since Delphi doesn't have a rooted type system like C#, that causes a problem implementing the Current property. What should IEnumerator.Current return on an instance you get back from IEnumerable<Integer>?<BR/><BR/>Iterators - maybe. We'll see.Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-2364300192206767482008-08-29T06:55:00.000+01:002008-08-29T06:55:00.000+01:00Hi Barry,One thing that would be very interesting:...Hi Barry,<BR/>One thing that would be very interesting: Do the predefined Enumrator/Enumerable classes implement the interfaces IEnumerable<T>/IEnumerator<T>?<BR/><BR/>And are iterator methods on the horizon for next versions?Unknownhttps://www.blogger.com/profile/04907718415714317724noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-44346305133368645292008-08-25T14:13:00.000+01:002008-08-25T14:13:00.000+01:00@Svein - I was annoyed with Joylon for his trollis...@Svein - I was annoyed with Joylon for his trollish comment on the Vista rant post.<BR/><BR/>Re examples, I'm sorry if they're too complex for you. I'm a developer, not a teacher, or even a marketer. I'll post what I find interesting. If I posted for different reasons, I wouldn't be posting for much longer (i.e. I would stop).Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-56828096633699207402008-08-25T13:40:00.000+01:002008-08-25T13:40:00.000+01:00I give my support to Joylyon. Perhaps mr Kelly has...I give my support to Joylyon. Perhaps mr Kelly has forgotten that not all people who use Delphi are capable of writing compilers of their own? I agree wholeheartedly with Joylyon that the examples are complex, and I also think that this example didn't make me want to use the new features. I'm not saying the new features are no good, but the example didn't demonstrate their benefits in a way that appealed to me.<BR/><BR/>Also, the last comment from Barry struck me as quite patronizing. Maybe some humility would be better?Svein Bringslihttps://www.blogger.com/profile/16082096200806505547noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-17879201813780899322008-08-25T10:06:00.000+01:002008-08-25T10:06:00.000+01:00@Joylon -"that would produce the same output"You'r...@Joylon -<BR/><BR/>"that would produce the same output"<BR/><BR/>You're using weasel words when you talk about "the same output" - <B>of course</B> the case at hand is trivial, a listing of numbers. The case is trivial <B>so</B> that the mechanism is the <B>only</B> thing that is complex - otherwise there would be unnecessary complexity in the example.<BR/><BR/>"the simplest possible implementation" - would be a machine code listing, as that would be devoid of abstraction.<BR/><BR/>Or perhaps you have your own, biased, concept of simplicity? Maybe you use the word "simple" to mean "familiar to Joylon"? It seems that way to me, because I guess that you probably haven't internalized closures as a language construct.<BR/><BR/>I imagine that not everybody will be willing to limit their toolbox to only those tools "familiar to Joylon", however.Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-47196585079589630592008-08-25T08:33:00.000+01:002008-08-25T08:33:00.000+01:00I think you missed my point Barry - I wasn't sugge...I think you missed my point Barry - I wasn't suggesting that you only eliminate anonymous methods in the implementation but that you instead consider the simplest possible implementation that would produce the same output (i.e. the desired result).<BR/><BR/>That simplest-possible implementation may not be AS re-usable (then again, ime people are more likely to re-use something they understand) but when assessing the value of re-use you have to consider not only how re-usable something IS but how likely and how often it is going to BE re-used and how much a re-usable implementation is actually going to save/improve anything.<BR/><BR/>Things haven't changed much in the last year or so - there is still a dearth of compelling, recognisably applicable examples to showcase these additions to the language. imho.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10106032.post-81281391185473876522008-08-22T06:29:00.000+01:002008-08-22T06:29:00.000+01:00Nice work Bary. I look forward to follow on posts....Nice work Bary. I look forward to follow on posts.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10106032.post-20569205338718114062008-08-21T06:30:00.000+01:002008-08-21T06:30:00.000+01:00Hi, Barry Kelly.Next(from you) code(generic skelet...Hi, Barry Kelly.<BR/><BR/>Next(from you) code(generic skeleton) is exact C# YIELD keyword implementation sample. <BR/>Though on IL side C# compiler guys make it a bit different.<BR/><BR/>Well done, Barry.<BR/><BR/>Result := TSimpleEnumerable{Integer}.Create(function: TFunc{Integer}<BR/> var<BR/> myStart, myIncrement, myCount: Integer;<BR/> begin<BR/> myStart := Start;<BR/> myIncrement := Increment;<BR/> myCount := Count;<BR/> <BR/> Result := function: Integer<BR/> begin<BR/> if myCount <= 0 then<BR/> raise EEnumerationFinished.Create;<BR/> Result := myStart;<BR/> Inc(myStart, myIncrement);<BR/> Dec(myCount);<BR/> end;<BR/> end);Sergey Antonov aka oxffffhttps://www.blogger.com/profile/10045102019512764602noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-29540889927234314702008-08-21T03:22:00.000+01:002008-08-21T03:22:00.000+01:00@Joylon: Most of the code is in the article is reu...@Joylon: Most of the code is in the article is reusable library material. One of the problems with trying to show how to reduce effort in implementing A with some new applied abstraction f(A'), where A' < A, is that you have to introduce f(x); and it is typically the case with such abstractions that f(x) > A. Hopefully you can understand the example enough to see which bit is f(x) and which bit is A'. Probably the biggest problem with the post is that I never presented A, so you never saw the verbosity of that.<BR/><BR/>However, your complaint that all this does is list numbers, I find hard to take seriously. The point of the post is how to create an iterator without having to write a separate class (or two) and two (or three, if you include Reset) separate methods. Some imagination is required!Barry Kellyhttps://www.blogger.com/profile/10559947643606684495noreply@blogger.comtag:blogger.com,1999:blog-10106032.post-18428754880218616682008-08-21T02:01:00.000+01:002008-08-21T02:01:00.000+01:00I have to wonder whether this isn't counter-produc...I have to wonder whether this isn't counter-productive if your aim is to show how useful/desirable anon methods and generics are.<BR/><BR/>My first thought is: Geez, that's one heck of a lot of really quite complex code just to produce a simple, repeatable list of numbers.<BR/><BR/>My second thought is: I can do this much more simply without using anons or generics, and in a way that is going to be much easier to follow for anyone reading my code in the future.<BR/><BR/><BR/>It really doesn't make me want to use these new language features at all.<BR/><BR/>:(<BR/><BR/>Can't we find some more compelling examples?Anonymousnoreply@blogger.com