Re: Adapting foreign iterators to D ranges
On Wednesday, 24 April 2024 at 05:08:25 UTC, Salih Dincer wrote: Yes, `opApply()` works! You just need to use `do while()` instead of `while()` because it skips the first item. It depends on the type of structure being consumed, if it provides "next" as a direct pointer then yeah you would need to consume the item first before iterating to the next in line. However some APIs provide an opaque iterator type where you call a "next" method to get the first element, IIRC Lua does something like this.
Re: Adapting foreign iterators to D ranges
On Tuesday, 23 April 2024 at 06:02:18 UTC, cc wrote: Just to offer an alternative solution (since it sometimes gets overlooked), there is also the `opApply` approach. You don't get full forward range status, and checking whether it's empty essentially requires doing something like std.algorithm `walkLength`, but if all you need is basic iteration, it can be a simpler solution: Yes, `opApply()` works! You just need to use `do while()` instead of `while()` because it skips the first item. ```d struct Node { int item; Node* next; } class List { Node* root, iter; this(int item = 0) { iter = new Node(item, null); root = iter; } List dup() { auto backup = new List(); backup.root = root; backup.iter = iter; return backup; } void insertFront(T)(T item) { (*iter).next = new Node(item, null); this.Next; } bool empty() const => iter is null; auto front() inout => iter; auto popFront()=> iter = this.Next; auto getItem() => iter.item; auto rewind() => iter = root; } auto Next(List list) => list.iter = list.iter.next; auto gaussian(T)(T n)=> (n * n + n) / 2; void main() { import std.stdio; enum LIMIT = 10; auto list = new List(1); foreach(t; 2 .. LIMIT + 1) { list.insertFront(t); } auto tmp = list.dup; list.rewind(); size_t sum; do sum += list.getItem; while(list.Next); assert(gaussian(LIMIT) == sum); sum.writeln; // 55 auto next = LIMIT + 1; tmp.insertFront(next); tmp.rewind(); sum = 0; foreach(t; tmp) sum += t.item; assert(gaussian(LIMIT) + next == sum); sum.writeln; // 66 tmp.rewind(); auto range = Range(tmp); foreach(r; range) r.item.write(" "); writeln; // 2 3 4 5 6 7 8 9 10 11 // ? (1) --^ } struct Range { private List iter; int opApply(scope int delegate(Node* t) dg) { while(auto current = iter.Next) { if (auto r = dg(current)) return r; } return 0; } } ``` SDB@79
Re: Adapting foreign iterators to D ranges
On Monday, 22 April 2024 at 11:36:43 UTC, Chloé wrote: I wish to adapt this interface to a forward range for use with foreach and Phobos' range utilities. This amounts to implementing empty, front, and popFront, in terms of next and some state. But there is a choice to be made regarding the first call to next. Just to offer an alternative solution (since it sometimes gets overlooked), there is also the `opApply` approach. You don't get full forward range status, and checking whether it's empty essentially requires doing something like std.algorithm `walkLength`, but if all you need is basic iteration, it can be a simpler solution: ```d struct Range { private I iter; this(I iter) { this.iter = iter; } int opApply(scope int delegate(T* t) dg) { while (auto current = next(iter)) { if (auto r = dg(current)) return r; } return 0; } } void main() { I someIter; // = ... auto range = Range(someIter); foreach (const t; range) { writeln(*t); } } ```
Re: Adapting foreign iterators to D ranges
On Monday, 22 April 2024 at 11:36:43 UTC, Chloé wrote: The first implementation has the advantage is being simpler and empty being const, but has the downside that next is called even if the range ends up not being used. Is either approach used consistently across the D ecosystem? I always go for the simplest approach. So that means, pre-fill in the constructor. Yes, the downside is, if you don't use it, then the iterator has moved, but the range hasn't. But returning to the iterator after using the range is always a dicey proposition anyway. The huge benefit is that all the functions become simple and straightforward. But there is no "right" approach. And using composition, you may be able to achieve all approaches with wrappers. Phobos does various things depending on what people thought was good at the time. It sometimes causes some very unexpected behavior. I recommend always using the same approach for the same library, that way your users know what to expect! -Steve
Re: Adapting foreign iterators to D ranges
On Monday, 22 April 2024 at 11:36:43 UTC, Chloé wrote: The first implementation has the advantage is being simpler and empty being const, but has the downside that next is called even if the range ends up not being used. Is either approach used consistently across the D ecosystem? You can also place initialization logic inside front, then empty could become const. I don't think there is a preffered way of initializing such ranges, so imho consider what's best for your use case.
Adapting foreign iterators to D ranges
Assume a third-party API of the following signature: T* next(I iter); which advances an iterator of sorts and returns the next element, or null when iteration is done. No other information about the state of the iterator is available. I wish to adapt this interface to a forward range for use with foreach and Phobos' range utilities. This amounts to implementing empty, front, and popFront, in terms of next and some state. But there is a choice to be made regarding the first call to next. One could call next during range construction: struct Range { private I iter; private T* current; this(I iter) { this.iter = iter; current = next(iter); } bool empty() const => current is null; inout(T)* front() inout => current; void popFront() { current = next(iter); } } Or do not call it until the first call to empty: struct Range { private bool initialized; private I iter; private T* current; this(I iter) { this.iter = iter; } bool empty() { if (!initialized) { current = next(iter); initialized = true; } return current is null; } inout(T)* front() inout => current; void popFront() { current = next(iter); } } The first implementation has the advantage is being simpler and empty being const, but has the downside that next is called even if the range ends up not being used. Is either approach used consistently across the D ecosystem?
Need help how to get started with D ranges
I see that ranges is primitive to organzie universal approach to write some algorithms. But I'm using algorithms from the library but I still can't start with writing my own algorithms based on ranges. For example I have the following function written without ranges. I want to improve it and make it working with different types of strings (char[], string, wchar[], etc...). So could someone give me an example how to rewrite this function in `range`-style? //Parses HTML form data dstring[dstring] parseFormData2(dstring queryStr) { size_t LexStart = 0; dstring curKey; dstring curValue; for( size_t i = 0; i queryStr.length; ++i ) { if( queryStr[i] == '=' ) { curKey = queryStr[LexStart..i].idup; curValue = null; LexStart = i+1; } if( (queryStr[i] == '') || (i+1 == queryStr.length) ) { curValue = queryStr[ LexStart .. (i+1 == queryStr.length) ? ++i : i ].idup; if( curKey.length 0) { result[curKey] = curValue; //result[curKey] ~= curValue; } curKey = null; LexStart = i+1; } } return result; }
Re: Need help how to get started with D ranges
On Monday, 24 March 2014 at 12:13:43 UTC, Uranuz wrote: I see that ranges is primitive to organzie universal approach to write some algorithms. But I'm using algorithms from the library but I still can't start with writing my own algorithms based on ranges. For example I have the following function written without ranges. I want to improve it and make it working with different types of strings (char[], string, wchar[], etc...). So could someone give me an example how to rewrite this function in `range`-style? //Parses HTML form data dstring[dstring] parseFormData2(dstring queryStr) { size_t LexStart = 0; dstring curKey; dstring curValue; for( size_t i = 0; i queryStr.length; ++i ) { if( queryStr[i] == '=' ) { curKey = queryStr[LexStart..i].idup; curValue = null; LexStart = i+1; } if( (queryStr[i] == '') || (i+1 == queryStr.length) ) { curValue = queryStr[ LexStart .. (i+1 == queryStr.length) ? ++i : i ].idup; if( curKey.length 0) { result[curKey] = curValue; //result[curKey] ~= curValue; } curKey = null; LexStart = i+1; } } return result; } Have you read this: http://ddili.org/ders/d.en/ranges.html ?
Re: Need help how to get started with D ranges
Have you read this: http://ddili.org/ders/d.en/ranges.html ? Yes I have read it. It's difficult to formulate the question in English bu I'l try. In this example I searching for special symbols '' and '='. So when symbol found I use *save* method of range to remember start of *name* or *value* string of URL encoded param. Then I trying to find next special symbol. And when I found it I need to take a slice and insert in result AA. Should input range be RandomAccess for it? And if it's not random access range should should I append this substring by symbol to some temp variable and then (when delimiter found) insert into Associative Array. So result is that I will implement two different behaviours for InputRange and for RandomAccessRange. Am I right or not?
Re: Need help how to get started with D ranges
I have another question. For example I have some range with input data (for example some array). I using method popFront() to iterate to next element. Then with property front I check element if it has some value. Then I *save* it. But how could I get position of this derived range in original range without overhead. As I see it is only possible via additional variable that will keep this position. In this case I can't understand what is the benefit of range over iterators or simply iterating using some integral index. I should admit that I haven't used iterators a lot in C++ so I don't know all of it's possibilities/ advantages. It's why I asking. In my algorithms for parsing some strings I often save positions of beginings of some tokens in order to take a slice and put it into some buffer. But for opearting with them in terms of ranges I need to have RandomAccessRange, because (as far as I understand) only it have ability to take a slice. But with input I will need to operate (save parsed data) element-wise. And this will realocate and slow execution. What is preferable startegy opearating with ranges that will be flexible and productive?
Re: Need help how to get started with D ranges
On Monday, 24 March 2014 at 14:12:58 UTC, Uranuz wrote: Have you read this: http://ddili.org/ders/d.en/ranges.html ? Yes I have read it. It's difficult to formulate the question in English bu I'l try. In this example I searching for special symbols '' and '='. So when symbol found I use *save* method of range to remember start of *name* or *value* string of URL encoded param. Then I trying to find next special symbol. And when I found it I need to take a slice and insert in result AA. Should input range be RandomAccess for it? And if it's not random access range should should I append this substring by symbol to some temp variable and then (when delimiter found) insert into Associative Array. So result is that I will implement two different behaviours for InputRange and for RandomAccessRange. Am I right or not? If you want to be able to *slice*, then you need an `RandomAccessRange` with `hasSlicing`. a RandomAccessRange is a special kind of ForwardRange, which itself is an Input Range.
Re: D Ranges
On Monday, 16 September 2013 at 13:05:56 UTC, Chris wrote: On Saturday, 14 September 2013 at 02:10:13 UTC, Jesse Phillips wrote: There isn't a guide in the manner you desire. In my experience I generally don't hold any more data than the value returned by front (to prevent recalculation). Right now I don't recall what situations I've needed to store the intermediary data, but I know how you feel about having a input rang which is like an output range simply returning a range to provide the chaining ability. Yes, this occurs sometimes. But I think it's due to my lack of experience with ranges, that's why I was asking, if there was a rough guide. I don't think I really need to store intermediate data in my components. I'm not sure, however, if I should slowly migrate from OOP to structs. A of now I use them in two scenarios: 1. input / output ranges (flexible and interchangeable workhorses) 2. storage of user defined data types, e.g. you could have a struct like this for an entry in a dictionary: struct LexEntry { string lemma = digital; string transcription = Some IPA symbols; string[] definition = [1. bla bla, 2. bla bla]; } At the moment, I use a lot of singletons in my program, because a lot of the data and data processing is handled by designated classes that do not to be reinstantiated. They just sit there waiting for input. In fact, without even noticing it, I designed parts of my program in an OO fashion that, in a way, makes OOP superfluous. So I'm beginning to wonder whether classes are really necessary. If I need features like sublcassing, I could just right another input range and add it to the chain. I'm still hesitant because a. if it's not broke, don't fix it and b. there might be some usage scenario when I'll need OO design and that I cannot yet foresee. But I agree that OO design is hard to unittest, it's not easy to single out a component and test it, because it's like a neurological network. that do not _have_ to be reinstantiated I could just right = write (sorry, it's the Monday bug in my head!)
Re: D Ranges
On Saturday, 14 September 2013 at 02:10:13 UTC, Jesse Phillips wrote: There isn't a guide in the manner you desire. In my experience I generally don't hold any more data than the value returned by front (to prevent recalculation). Right now I don't recall what situations I've needed to store the intermediary data, but I know how you feel about having a input rang which is like an output range simply returning a range to provide the chaining ability. Yes, this occurs sometimes. But I think it's due to my lack of experience with ranges, that's why I was asking, if there was a rough guide. I don't think I really need to store intermediate data in my components. I'm not sure, however, if I should slowly migrate from OOP to structs. A of now I use them in two scenarios: 1. input / output ranges (flexible and interchangeable workhorses) 2. storage of user defined data types, e.g. you could have a struct like this for an entry in a dictionary: struct LexEntry { string lemma = digital; string transcription = Some IPA symbols; string[] definition = [1. bla bla, 2. bla bla]; } At the moment, I use a lot of singletons in my program, because a lot of the data and data processing is handled by designated classes that do not to be reinstantiated. They just sit there waiting for input. In fact, without even noticing it, I designed parts of my program in an OO fashion that, in a way, makes OOP superfluous. So I'm beginning to wonder whether classes are really necessary. If I need features like sublcassing, I could just right another input range and add it to the chain. I'm still hesitant because a. if it's not broke, don't fix it and b. there might be some usage scenario when I'll need OO design and that I cannot yet foresee. But I agree that OO design is hard to unittest, it's not easy to single out a component and test it, because it's like a neurological network.
Re: D Ranges
On Saturday, 14 September 2013 at 06:18:02 UTC, Jonathan M Davis wrote: On Friday, September 13, 2013 23:07:03 H. S. Teoh wrote: OTOH, I find myself switching to classes just to get the reference semantics in other cases, even if I never actually do any inheritance. Trying to do reference semantics with structs, while certainly possible, is just too error-prone IME. Just a few days ago, I encountered what looked like a nasty functionality bug in my program, only to eventually discover that it was caused by a missing 'ref' in a function's struct parameter, so updates to the struct didn't persist as the code assumed it would. I found myself seriously considering using classes instead, just for the default ref semantics. In general, if you want to have structs with reference semantics, it's probably better to just give them reference semantics by making it so that any of their members which are value types are on the heap or by putting all of the struct's guts on the heap. At some point, it becomes debatable as to whether that's better than using a class, but it does have less overhead. There's also RefCounted, which does incur the bookkeeping overhead of the refcounting, but it does make it so that the memory is freed as soon as you don't need the object anymore. - Jonathan M Davis I have a few issues with ref counted. First, if you *ever* place one in an array or an AA, then you will leak. It is NOT designed for simply incorporating reference, but for deterministic finalization. Second, it has an elaborate postblit and opAssign. This is not a big issue in itself, but their sole existence does cause dmd to generate code that is sub-optimal. It also means it can't take the optimal route in a lot of algorithms (array has to emplace each element individually, for example). Finally, a RefCounted will implicitly cast to its payload. I think this is *horrible*. Before you know it, the Payload will have jettisoned its wrapper, and you'll be operating on your value-type payload raw. For example: void foo(T t); RefCounted!T myRecCounted; foo(myRefCounted); //Passes. Oops! The workaround would be to either require explicit get to go from ref counted to payload (breaking existing code), or to entirelly wrap the RefCounted as a member inside the struct (requires boilerplate code). Overall, if I need a reference semantic struct, I find it much simpler for it to just hold a GC pointer to a payload. Though to be honest, as H.S. Teoh, I seriously wonder why I even bother, when I could just use a final class. With proper private constructors + non-member make function, you can make your choice outright transparent to the final user too, meaning you can fast prototype with classes, and later change to structs if you think it is worth it.
Re: D Ranges
On Sunday, September 15, 2013 10:39:40 monarch_dodra wrote: I have a few issues with ref counted. First, if you *ever* place one in an array or an AA, then you will leak. It is NOT designed for simply incorporating reference, but for deterministic finalization. Second, it has an elaborate postblit and opAssign. This is not a big issue in itself, but their sole existence does cause dmd to generate code that is sub-optimal. It also means it can't take the optimal route in a lot of algorithms (array has to emplace each element individually, for example). Finally, a RefCounted will implicitly cast to its payload. I think this is *horrible*. Before you know it, the Payload will have jettisoned its wrapper, and you'll be operating on your value-type payload raw. For example: void foo(T t); RefCounted!T myRecCounted; foo(myRefCounted); //Passes. Oops! The workaround would be to either require explicit get to go from ref counted to payload (breaking existing code), or to entirelly wrap the RefCounted as a member inside the struct (requires boilerplate code). Yeah. RefCounted could/should definitely be improved, but the concept is essentially the same as smart_ptr in C++11. In many ways, smart pointers are far superior to using the GC, and I really think that we should do a better job of supporting them and promoting them. There are obviously plenty of cases where the GC is better or even necessary, but in many cases - particularly with objects - smart pointers are arguably a much better way to go. - Jonathan M Davis
Re: D Ranges
15-Sep-2013 12:39, monarch_dodra пишет: On Saturday, 14 September 2013 at 06:18:02 UTC, Jonathan M Davis wrote: I have a few issues with ref counted. First, if you *ever* place one in an array or an AA, then you will leak. It is NOT designed for simply incorporating reference, but for deterministic finalization. Another problem with built-in AAs... Second, it has an elaborate postblit and opAssign. This is not a big issue in itself, but their sole existence does cause dmd to generate code that is sub-optimal. It also means it can't take the optimal route in a lot of algorithms (array has to emplace each element individually, for example). Seriously we could do a better job then that.. For instance blit the whole data, then call postblits on that range. Exception safety would be trickier to achieve. Even better one day I now expect compiler to be able to know that e.g. RefCounted is registered as ARC-capable type then the compiler should elide call to ref-counting. Finally, a RefCounted will implicitly cast to its payload. I think this is *horrible*. Before you know it, the Payload will have jettisoned its wrapper, and you'll be operating on your value-type payload raw. For example: void foo(T t); RefCounted!T myRecCounted; foo(myRefCounted); //Passes. Oops! Well it does a copy. Which is IMO perfectly fine. If you want to prevent that (at least in theory) you should simply mark postblit of T as disabled. The workaround would be to either require explicit get to go from ref counted to payload (breaking existing code), or to entirelly wrap the RefCounted as a member inside the struct (requires boilerplate code). There is no need to prevent that in general case. Only RAII kind of things implemented with RefCounted would have problem copying-out the payload but these should have post-blit disabled for their value and consequently would not compile. Overall, if I need a reference semantic struct, I find it much simpler for it to just hold a GC pointer to a payload. Ehm.. Isn't finalized class is just that? Plus bit of overhead for monitor. Though to be honest, as H.S. Teoh, I seriously wonder why I even bother, when I could just use a final class. With proper private constructors + non-member make function, you can make your choice outright transparent to the final user too, meaning you can fast prototype with classes, and later change to structs if you think it is worth it. This is true. And in fact I would encourage every D programmer to never expose constructors and always provide factory functions. These days constructors are constrained by a set of arcane limitations thusly suck beyond measure in every way possible. But you need them to say initialize immutable members, hence _use_ - but don't _expose_ them. -- Dmitry Olshansky
Re: D Ranges
On Sunday, 15 September 2013 at 12:17:34 UTC, Dmitry Olshansky wrote: 15-Sep-2013 12:39, monarch_dodra пишет: On Saturday, 14 September 2013 at 06:18:02 UTC, Jonathan M Davis wrote: I have a few issues with ref counted. First, if you *ever* place one in an array or an AA, then you will leak. It is NOT designed for simply incorporating reference, but for deterministic finalization. Another problem with built-in AAs... Second, it has an elaborate postblit and opAssign. This is not a big issue in itself, but their sole existence does cause dmd to generate code that is sub-optimal. It also means it can't take the optimal route in a lot of algorithms (array has to emplace each element individually, for example). Seriously we could do a better job then that.. For instance blit the whole data, then call postblits on that range. Exception safety would be trickier to achieve. Even better one day I now expect compiler to be able to know that e.g. RefCounted is registered as ARC-capable type then the compiler should elide call to ref-counting. Well, if a struct has no elaborate opAssign, then = *is* blit+postblit. And it doesn't get much more efficient than that. If not, you have to pull out the memcpy, and things just go downhill from there. Finally, a RefCounted will implicitly cast to its payload. I think this is *horrible*. Before you know it, the Payload will have jettisoned its wrapper, and you'll be operating on your value-type payload raw. For example: void foo(T t); RefCounted!T myRecCounted; foo(myRefCounted); //Passes. Oops! Well it does a copy. Which is IMO perfectly fine. If you want to prevent that (at least in theory) you should simply mark postblit of T as disabled. It depends how you look at it. If the original intent was to have a type with reference semantics, because your value type was so damn big (eg, PRNG), then that would *not* be OK (and the original point I was making that RefCounted is a bad contender for just reference semantics). If you are *trully* using it for deterministic finalization, then yeah, it's OK.
Re: D Ranges
15-Sep-2013 17:02, monarch_dodra пишет: It depends how you look at it. If the original intent was to have a type with reference semantics, because your value type was so damn big (eg, PRNG), then that would *not* be OK (and the original point I was making that RefCounted is a bad contender for just reference semantics). If user don't have the access to the wrapped internal type there should be no problem. E.g. the wrapped type is private and only usable inside the PRNG's module. Then having public alias for RefCounted!PRNG touted as THE PRNG should suffice. (Truly wicked folks can crack open it with a carefully applied piece of template deduction but each to their own goals). If you are afraid of these dark mages of templates you can do something like: struct RefPRNG{ RefCounted!PRNG payload; mixin ForwardCallsTo!payload; } And let them suck it down. IMHO there is no reason to go that far. If you are *trully* using it for deterministic finalization, then yeah, it's OK. See above I don't see the problem. -- Dmitry Olshansky
Re: D Ranges
Am 15.09.2013 10:52, schrieb Jonathan M Davis: ... Yeah. RefCounted could/should definitely be improved, but the concept is essentially the same as smart_ptr in C++11. In many ways, smart pointers are far superior to using the GC, and I really think that we should do a better job of supporting them and promoting them. There are obviously plenty of cases where the GC is better or even necessary, but in many cases - particularly with objects - smart pointers are arguably a much better way to go. - Jonathan M Davis Actually, it is much easier to write exception safe code in languages with GC. Or in case of ref-counting if the compiler is aware of them. The problems with exception safe code in C++ with memory leaks are related to its C compatibility rules and having to cope to optional exceptions. After watching the Going Native 2013 videos, I really wonder how much of a push C++ will win back from younger developers, outside the game industry and device drivers. Now back to C++ coding. :) -- Paulo
Re: D Ranges
On Fri, Sep 13, 2013 at 10:49:23PM -0400, Jonathan M Davis wrote: On Saturday, September 14, 2013 04:10:09 Jesse Phillips wrote: Anyway, my recommendation isn't to build up a class structure just because that is what you would do in another language. Figure out if the usability provided by inheritance is what you want, if not struct with helper functions seems to be simplest in development and maintenance. Destroy. I find that I use classes very rarely in D. Once in a while, I need polymorphism, and in that situation, I use classes, but at least in the types of programs that I've usually been writing, polymorphism has rarely made much sense. Structs deal with most everything just fine. Classes definitely have their uses, but IMHO, they should not be the first tool to pull out of your toolbox when writing a D program. Just use them when you actually need them. [...] I've found myself hovering between structs and classes when writing D code. I almost always use structs for ranges, just because value types incur less overhead, which does add up when you use a lot of UFCS chaining. OTOH, I find myself switching to classes just to get the reference semantics in other cases, even if I never actually do any inheritance. Trying to do reference semantics with structs, while certainly possible, is just too error-prone IME. Just a few days ago, I encountered what looked like a nasty functionality bug in my program, only to eventually discover that it was caused by a missing 'ref' in a function's struct parameter, so updates to the struct didn't persist as the code assumed it would. I found myself seriously considering using classes instead, just for the default ref semantics. While D's decision to make structs value-only and classes ref-only is certainly clever, it also introduces some tricky gotchas for the unwary. T -- May you live all the days of your life. -- Jonathan Swift
Re: D Ranges
On Friday, September 13, 2013 23:07:03 H. S. Teoh wrote: OTOH, I find myself switching to classes just to get the reference semantics in other cases, even if I never actually do any inheritance. Trying to do reference semantics with structs, while certainly possible, is just too error-prone IME. Just a few days ago, I encountered what looked like a nasty functionality bug in my program, only to eventually discover that it was caused by a missing 'ref' in a function's struct parameter, so updates to the struct didn't persist as the code assumed it would. I found myself seriously considering using classes instead, just for the default ref semantics. In general, if you want to have structs with reference semantics, it's probably better to just give them reference semantics by making it so that any of their members which are value types are on the heap or by putting all of the struct's guts on the heap. At some point, it becomes debatable as to whether that's better than using a class, but it does have less overhead. There's also RefCounted, which does incur the bookkeeping overhead of the refcounting, but it does make it so that the memory is freed as soon as you don't need the object anymore. - Jonathan M Davis
Re: D Ranges
On 2013-09-14 08:07, H. S. Teoh wrote: OTOH, I find myself switching to classes just to get the reference semantics in other cases, even if I never actually do any inheritance. I agree, it seems I most times want a reference type (not talking ranges here but in general). -- /Jacob Carlborg
D Ranges
A short report on component programming and ranges. A lot of my code deals with transforming and reformatting input, e.g. text is split into sentences and words for grammatical parsing (part of speech) and phonetic transcriptions. I'm using D ranges and component programming and I'm quite happy with one-liners like foreach (bySentence().byWord().byWhateverFormat().byReformatAgain()) { // Whatever } The code is much easier to maintain, neater and more efficient within each component. Sometimes, however, I wonder how I should design my ranges. It is hard to decide whether to use them as pure pipes or semi-output ranges. Semi because they're not sinks as defined by put() but still they can hold data (an array of reformatted strings for example) that could be accessed by using Range.data. I'm not sure as regards best practice and whether or not I'm wasting resources by storing data internally. On the other hand, it might be handy to have access to the data stored internally. Does anyone have a rough guide to D ranges? Like Case 1: Use XYZ, Case 2: Use ZYX etc. (I've read this tutorial http://ddili.org/ders/d.en/ranges.html, and I'd like to thank Ali for that! It helped me a lot.) Another issue I've come across is how to integrate CP and ranges into an OO framework. I figure that ranges are good work horses, but it makes sense to keep the overall logic in an OO fashion. Or could it be that D's structs and ranges will replace OOP as we no it (a class-free system).
Re: D Ranges
Chris: A short report on component programming and ranges. A lot of my code deals with transforming and reformatting input, e.g. text is split into sentences and words for grammatical parsing (part of speech) and phonetic transcriptions. I'm using D ranges and component programming and I'm quite happy with one-liners like foreach (bySentence().byWord().byWhateverFormat().byReformatAgain()) { // Whatever } In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile
Re: D Ranges
On Friday, 13 September 2013 at 13:31:18 UTC, bearophile wrote: In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile ...but you shouldn't if you care about readability (leave at least the last pair in the line) :P
Re: D Ranges
On Friday, 13 September 2013 at 13:42:07 UTC, Dicebot wrote: On Friday, 13 September 2013 at 13:31:18 UTC, bearophile wrote: In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile ...but you shouldn't if you care about readability (leave at least the last pair in the line) :P It also helps other people (and me) to realize that it actually _does_ something and doesn't just return a value. Often (not always of course), if you omit the brackets it returns a value without doing anything. But that's just a personal convention I might abandon further down the road.
Re: D Ranges
On Friday, 13 September 2013 at 13:42:07 UTC, Dicebot wrote: On Friday, 13 September 2013 at 13:31:18 UTC, bearophile wrote: In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile ...but you shouldn't if you care about readability (leave at least the last pair in the line) :P That is my gideline as well. Keep at least the last one.
Re: D Ranges
On Friday, 13 September 2013 at 14:39:29 UTC, Chris wrote: On Friday, 13 September 2013 at 13:42:07 UTC, Dicebot wrote: On Friday, 13 September 2013 at 13:31:18 UTC, bearophile wrote: In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile ...but you shouldn't if you care about readability (leave at least the last pair in the line) :P It also helps other people (and me) to realize that it actually _does_ something and doesn't just return a value. Often (not always of course), if you omit the brackets it returns a value without doing anything. But that's just a personal convention I might abandon further down the road. Since most ranges in std.algorithm are lazy they are usually not doing anything but setting a few members and returning a new range, often without having even touched the input range. Thinking about it I think I may start using () to denote eager versus lazy ranges in my UFCS chains.
Re: D Ranges
On Friday, 13 September 2013 at 17:35:21 UTC, Brad Anderson wrote: On Friday, 13 September 2013 at 14:39:29 UTC, Chris wrote: On Friday, 13 September 2013 at 13:42:07 UTC, Dicebot wrote: On Friday, 13 September 2013 at 13:31:18 UTC, bearophile wrote: In most cases today you are free to omit those (): foreach (bySentence.byWord.byWhateverFormat.byReformatAgain) { Bye, bearophile ...but you shouldn't if you care about readability (leave at least the last pair in the line) :P It also helps other people (and me) to realize that it actually _does_ something and doesn't just return a value. Often (not always of course), if you omit the brackets it returns a value without doing anything. But that's just a personal convention I might abandon further down the road. Since most ranges in std.algorithm are lazy they are usually not doing anything but setting a few members and returning a new range, often without having even touched the input range. Thinking about it I think I may start using () to denote eager versus lazy ranges in my UFCS chains. This reminds me, I have to check whether my ranges are lazy enough (like myself).
Re: D Ranges
On Friday, 13 September 2013 at 11:31:24 UTC, Chris wrote: Sometimes, however, I wonder how I should design my ranges. It is hard to decide whether to use them as pure pipes or semi-output ranges. Semi because they're not sinks as defined by put() but still they can hold data (an array of reformatted strings for example) that could be accessed by using Range.data. I'm not sure as regards best practice and whether or not I'm wasting resources by storing data internally. On the other hand, it might be handy to have access to the data stored internally. Does anyone have a rough guide to D ranges? Like Case 1: Use XYZ, Case 2: Use ZYX etc. (I've read this tutorial http://ddili.org/ders/d.en/ranges.html, and I'd like to thank Ali for that! It helped me a lot.) There isn't a guide in the manner you desire. In my experience I generally don't hold any more data than the value returned by front (to prevent recalculation). Right now I don't recall what situations I've needed to store the intermediary data, but I know how you feel about having a input rang which is like an output range simply returning a range to provide the chaining ability. I also generally don't find a need to specify output ranges. Output ranges are the end of the line so they kill component programming Another issue I've come across is how to integrate CP and ranges into an OO framework. I figure that ranges are good work horses, but it makes sense to keep the overall logic in an OO fashion. Or could it be that D's structs and ranges will replace OOP as we no it (a class-free system). I spent much of my initial time programming in Java, so I have a good grasp of the constructs behind OOP (and a little bit of the prototyping style known to be in Javascript). I also think I have a pretty good grasp on designing for OOP, though I do have a lot I could learn. I hate OOP. I believe it has a place in software design, I just haven't found it yet. Templates cause a lot of problem, though I need to look into using the trick using /final/. Trying to do inheritance when your interface defines that it takes a range or returns a range. Though generics in C# work quite nicely. The other issue I have is that OOP is very resistant to change and testing. It is hard enough to get all the data needed for your test cases, then throw in designing mock objects and blah blah, it quickly becomes a mess. And even if you skip all the testing aspects, if you want to make changes there is a giant structure you're making changes for. Yes had I done a better job designing my structure up front to allow for such change I wouldn't be in this mess... Anyway, my recommendation isn't to build up a class structure just because that is what you would do in another language. Figure out if the usability provided by inheritance is what you want, if not struct with helper functions seems to be simplest in development and maintenance. Destroy.
Re: D Ranges
On Saturday, September 14, 2013 04:10:09 Jesse Phillips wrote: Anyway, my recommendation isn't to build up a class structure just because that is what you would do in another language. Figure out if the usability provided by inheritance is what you want, if not struct with helper functions seems to be simplest in development and maintenance. Destroy. I find that I use classes very rarely in D. Once in a while, I need polymorphism, and in that situation, I use classes, but at least in the types of programs that I've usually been writing, polymorphism has rarely made much sense. Structs deal with most everything just fine. Classes definitely have their uses, but IMHO, they should not be the first tool to pull out of your toolbox when writing a D program. Just use them when you actually need them. - Jonathan M Davis
Re: D Ranges in C#
On 05/31/2013 11:17 PM, David Piepgrass wrote: I'm adding D-style ranges to my new C# collections library. In case anyone would like to comment, please see here: http://loyc-etc.blogspot.ca/2013/06/d-style-ranges-in-c-net.html (I wrote the following comment on the blog page but it is not visible at this time.) Thank you for writing this. I think the range article that you mentioned is Andrei Alexandrescu's On Iteration: http://www.informit.com/articles/article.aspx?p=1407357 Ali
Re: D Ranges in C#
On Sat, 01 Jun 2013 04:11:59 -0400, bearophile bearophileh...@lycos.com wrote: David Piepgrass: In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. This is true. In dcollections, I have the concept of cursors. These are 1 or 0 element ranges (they are 0 after the first popFront). For almost all cases, they require an extra boolean to designate the empty state. So while not consuming 2x, it's more like 1.5x-ish. Because of alignment, it pretty much requires 2x. There have been suggestions on utilizing perhaps unused bits in the pointer to designate the empty flag, but I'm a bit aprehensive on that, especially if the node is GC-managed. But besides the space requirements the *concept* of a single-element pointer is very much needed. And cursors fill that role. As an example, std.algorithm.find consumes a range until it finds the specific value. It then returns a range of the remaining data. But what if you wanted the range of the data UNTIL the first value? In std.container, we have three functions to deal with this, upperBound, lowerBound, and equalRange. But even with these, it can be difficult to construct intersections of these two ranges. In dcollections, we have one function, find, which returns a cursor. Then using the cursor, you can construct the range you need: auto r = mymap[mymap.find(5)..$]; // opDollar not supported yet, but will be. auto rbefore = mymap[mymap.begin()..mymap.find(5)]; All of this is safe and correct, and I think it reads rather well. There are other good places where single-element ranges are useful. It is important to note that a cursor is NOT equivalent to a range of one element. Such a range in a node-based container has two node pointers. A cursor MUST only point at exactly one element. This is important when considering cursor invalidation -- removing an element unreferenced by a cursor should not invalidate that cursor (depending on how the container is structured). For example, adding a new value to a hash set, or removing an unrelated value from a hash set may invalidate all ranges, but not cursors. -Steve
D Ranges in C#
I'm adding D-style ranges to my new C# collections library. In case anyone would like to comment, please see here: http://loyc-etc.blogspot.ca/2013/06/d-style-ranges-in-c-net.html
Re: D Ranges in C#
David Piepgrass: http://loyc-etc.blogspot.ca/2013/06/d-style-ranges-in-c-net.html From the article: Ranges are an improvement on the C++ concept of iterators. I don't exactly know how ranges were invented in D, but perhaps someone noticed that most of the C++ STL algorithms require pairs of iterators: Ranges are an improvement over iterators about as much as oxygen molecules are an improvement over oxygen atoms. You breath mostly O2, and it allows you to live, but they are made of atomic oxygen. Atomic oxygen is more fundamental, it is here to stay (as Alexander Stepanov says), and it has capabilities that molecules don't have. In your normal life you can think to use only molecular oxygen, but sometimes you can even desire some ozone :-) And in chemistry reactions that happen inside you all the time, like oxidation, the oxygen molecules usually break apart to react. In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. Bye, bearophile
Re: D Ranges in C#
On Saturday, 1 June 2013 at 08:12:00 UTC, bearophile wrote: David Piepgrass: In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. Hashmaps would be the most common example. Usually implemented as a linked list of key-value pairs along with a vector of list iterators. Iterators are also useful for constructing sub-ranges, which proves useful in the implementation of some algorithms. Writing std::next_permutation in D with ranges is quiet frustrating compared to C++. https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L10901 http://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01045_source.html#l03619 Notice that in D you need to maintain a count of the elements popped off the back and then use takeExactly to retrieve that portion again. In C++ you just move the iterators around and create ranges from pairs of iterators as you need them. When I implemented nextPermutation in D, I constantly felt as if I was fighting with ranges instead of working with them - I knew exactly what I wanted to do, but ranges only provide a roundabout way of doing it.
Re: D Ranges in C#
On 6/1/13 2:17 AM, David Piepgrass wrote: I'm adding D-style ranges to my new C# collections library. In case anyone would like to comment, please see here: http://loyc-etc.blogspot.ca/2013/06/d-style-ranges-in-c-net.html http://www.reddit.com/r/programming/comments/1fgnyl/dstyle_ranges_in_c_net/ Andrei
Re: D Ranges in C#
On Saturday, 1 June 2013 at 06:17:30 UTC, David Piepgrass wrote: I'm adding D-style ranges to my new C# collections library. In case anyone would like to comment, please see here: http://loyc-etc.blogspot.ca/2013/06/d-style-ranges-in-c-net.html Lol I am just preparing a blog post on D ranges in C++, a piece of code I did after Andrei's Iterators must Go presentation. It was not super usable before C++11 and auto but now is pretty cool thing to have.
Re: D Ranges in C#
David Piepgrass: In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. Hashmaps would be the most common example. Usually implemented as a linked list of key-value pairs along with a vector of list iterators. In theory. But the .NET hashtables are implemented with an *array* of key-value pairs and an array of *indexes*. The former forms a virtual linked list that is more efficient than a traditional linked list, and the latter is more efficient than a vector of iterators (especially on x64, as the indexes can be 32-bit.) Iterators are also useful for constructing sub-ranges, which proves useful in the implementation of some algorithms. Writing std::next_permutation in D with ranges is quiet frustrating compared to C++. https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L10901 http://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01045_source.html#l03619 Notice that in D you need to maintain a count of the elements popped off the back and then use takeExactly to retrieve that portion again. In C++ you just move the iterators around and create ranges from pairs of iterators as you need them. When I implemented nextPermutation in D, I constantly felt as if I was fighting with ranges instead of working with them - I knew exactly what I wanted to do, but ranges only provide a roundabout way of doing it. Hmm, very interesting. I suppose the problem with C++ iterators is that they are useless without external context: you can't increment or decrement one without also comparing it to begin() or end() in its container, which implies that the caller must manually keep track of which container it came from. Thus, an iterator is hardly an improvement over a plain-old integer index, the only advantages being 1. You can dereference it (*if* you can be sure it doesn't point to end()) 2. Unlike an index, it's compatible with non-random-access data structures But perhaps the iterator concept could be improved by being made self-aware: if the iterator knew and could tell you when it was at the beginning or end of its container. This would increase the storage requirement in some circumstances but not others. For example, an iterator to a doubly-linked list node can tell when it is at the beginning or end, but an iterator to a singly-linked list node can only tell when it is at the end. A pointer inside an array may or may not be able to tell if it is at the end depending on how arrays work, e.g. perhaps the way D heap arrays work would allow an array iterator, implemented as a simple pointer, to still know when it is safe to increment and decrement. The simplest possible .NET array iterator is an array reference plus an index, and again the iterator can know when it is at the beginning or end of the array--except that if the iterator came from inside a range, it would be unaware of the range's boundaries, which may be smaller than the array's boundaries.
Re: D Ranges in C#
On Saturday, 1 June 2013 at 16:30:05 UTC, David Piepgrass wrote: David Piepgrass: In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. Hashmaps would be the most common example. Usually implemented as a linked list of key-value pairs along with a vector of list iterators. In theory. But the .NET hashtables are implemented with an *array* of key-value pairs and an array of *indexes*. The former forms a virtual linked list that is more efficient than a traditional linked list, and the latter is more efficient than a vector of iterators (especially on x64, as the indexes can be 32-bit.) Iterators are usually (but not always) faster, as they don't have an extra level of indirection involved -- the iterators tell you directly where to look in memory, whereas indices are useless without containers (or iterators) backing them. You shouldn't be using 32-bit indices on x64, that defeats the whole point of x64. Hmm, very interesting. I suppose the problem with C++ iterators is that they are useless without external context: you can't increment or decrement one without also comparing it to begin() or end() in its container, which implies that the caller must manually keep track of which container it came from. No, that's exactly the opposite of what happens. The caller just accepts two iterators (like std::unique), so that it has the end iterator as well as the begin iterator.
Re: D Ranges in C#
Am 01.06.2013 20:23, schrieb Mehrdad: On Saturday, 1 June 2013 at 16:30:05 UTC, David Piepgrass wrote: David Piepgrass: In fact, most STL algorithms require exactly two iterators--a range--and none require only a single iterator I think there are some C++ data structures that store many single iterators. If you instead store ranges you double the data amount. Hashmaps would be the most common example. Usually implemented as a linked list of key-value pairs along with a vector of list iterators. In theory. But the .NET hashtables are implemented with an *array* of key-value pairs and an array of *indexes*. The former forms a virtual linked list that is more efficient than a traditional linked list, and the latter is more efficient than a vector of iterators (especially on x64, as the indexes can be 32-bit.) Iterators are usually (but not always) faster, as they don't have an extra level of indirection involved -- the iterators tell you directly where to look in memory, whereas indices are useless without containers (or iterators) backing them. You shouldn't be using 32-bit indices on x64, that defeats the whole point of x64. As of .NET 4.5, 64bit array indexes are supported as well. http://msdn.microsoft.com/en-us/library/hh285054.aspx
Re: D Ranges in C#
You shouldn't be using 32-bit indices on x64, that defeats the whole point of x64. As of .NET 4.5, 64bit array indexes are supported as well. http://msdn.microsoft.com/en-us/library/hh285054.aspx Don't forget that we're talking about a *hashtable* here. If a .NET hashtable used 64-bit indexes (or pointers) it would require 8-12 bytes more memory per entry, specifically 32 bytes total, including overhead, if the key and value are 4 bytes each. An in-memory hashtable that requires 64-bit indexes rather than 32 bits would have to contain over 4 billion entries which would take at least 128 GB of RAM, assuming 8 bytes for each key-value pair!!! In fact it's worse than that, as the dictionary grows by size-doubling and contains a certain amount of unused entries at the end. No thanks, I'd rather save those 8 bytes and accept the 4 billion limit, if you don't mind.
Re: D Ranges in C#
On Saturday, 1 June 2013 at 18:23:31 UTC, Mehrdad wrote: [cut] You shouldn't be using 32-bit indices on x64, that defeats the whole point of x64. Some would disagree: have a look at x32: http://en.wikipedia.org/wiki/X32_ABI Being able to use efficiently 64 bit doesn't mean that you *have* to use 64bit when 32bit is enough.. renoX
Re: D Ranges in C#
Am Sat, 01 Jun 2013 23:20:19 +0200 schrieb renoX reno...@gmail.com: On Saturday, 1 June 2013 at 18:23:31 UTC, Mehrdad wrote: [cut] You shouldn't be using 32-bit indices on x64, that defeats the whole point of x64. Some would disagree: have a look at x32: http://en.wikipedia.org/wiki/X32_ABI Being able to use efficiently 64 bit doesn't mean that you *have* to use 64bit when 32bit is enough.. renoX No wait, the whole 'efficiency' point was that on x64 you don't have to waste memory with the native word size for indexes, but can go with 32-bits. So it saves memory. But Mehrdad argued that we have x64 to be able to address beyond 2^32 (bytes, items, objects). And 32-bit indexes in generic code are thus asking for overflow bugs on x64 one day. x32 adds nothing to the discussion as you'd always use 32-bit indexes there. There is no point in storing more than 2^32 items when the address space is 32-bit. (Exceptions: bit arrays, file offsets, etc.) -- Marco
Ali Cehrili on D Ranges at D Conference 2012
Elements of containers (and pseudo-containers) are accessed by the range abstraction of D. D's InputRange, ForwardRange, BidirectionalRange, RandomAccessRange, and OutputRange are sufficient to connect many types of containers and many types of algorithms. Most modules of Phobos, including std.range, provide algorithms and ranges that make programs consistent, fast, and easy to maintain. -- http://astoriaseminar.com/sessions.html
Re: Ali Cehrili on D Ranges at D Conference 2012
On 05/27/2012 01:12 PM, Walter Bright wrote: Elements of containers (and pseudo-containers) are accessed by the range abstraction of D. D's InputRange, ForwardRange, BidirectionalRange, RandomAccessRange, and OutputRange are sufficient to connect many types of containers and many types of algorithms. Most modules of Phobos, including std.range, provide algorithms and ranges that make programs consistent, fast, and easy to maintain. -- http://astoriaseminar.com/sessions.html Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Re: Ali Cehrili on D Ranges at D Conference 2012
On 5/27/2012 1:38 PM, Ali Çehreli wrote: Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) OOPS! Fixed. What's the Unicode number for the first letter, so I can fix that, too? Is there an entity name for it?
Re: Ali Cehrili on D Ranges at D Conference 2012
On Sunday, May 27, 2012 13:53:24 Walter Bright wrote: On 5/27/2012 1:38 PM, Ali Çehreli wrote: Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) OOPS! Fixed. What's the Unicode number for the first letter, so I can fix that, too? Is there an entity name for it? According to this import std.stdio; void main() { writefln(%x, 'Ç'); } it's \u00c7. - Jonathan M Davis
Re: Ali Cehrili on D Ranges at D Conference 2012
On Sunday, May 27, 2012 14:01:09 Jonathan M Davis wrote: On Sunday, May 27, 2012 13:53:24 Walter Bright wrote: On 5/27/2012 1:38 PM, Ali Çehreli wrote: Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) OOPS! Fixed. What's the Unicode number for the first letter, so I can fix that, too? Is there an entity name for it? According to this import std.stdio; void main() { writefln(%x, 'Ç'); } it's \u00c7. Having .d files be able to be UTF-8 combined with unicode support built into the language itself can be _very_ handy. - Jonathan M Davis
Re: Ali Cehrili on D Ranges at D Conference 2012
On 5/27/2012 2:01 PM, Jonathan M Davis wrote: On Sunday, May 27, 2012 13:53:24 Walter Bright wrote: On 5/27/2012 1:38 PM, Ali Çehreli wrote: Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) OOPS! Fixed. What's the Unicode number for the first letter, so I can fix that, too? Is there an entity name for it? According to this import std.stdio; void main() { writefln(%x, 'Ç'); } it's \u00c7. - Jonathan M Davis Thanks! Checking it out, there's an entity for it: Ccedil; Fixed the web pages.
Re: Ali Cehrili on D Ranges at D Conference 2012
On 5/27/2012 2:03 PM, Jonathan M Davis wrote: Having .d files be able to be UTF-8 combined with unicode support built into the language itself can be _very_ handy. I also love D's support for entities: http://dlang.org/entity.html I'm amazed this is not adopted by other languages. It is so damned convenient.
Re: Ali Cehrili on D Ranges at D Conference 2012
On 05/27/2012 01:53 PM, Walter Bright wrote: On 5/27/2012 1:38 PM, Ali Çehreli wrote: Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) OOPS! Fixed. What's the Unicode number for the first letter, so I can fix that, too? Is there an entity name for it? Thanks but the misspelling has overpowered the correct one: Now both the Speakers and the Sessions page has the wrong name! :D Also, there is a rogue Ddoc at the end of the speaker bio. About the letter, if you are using ddoc as I suspect, just copy paste the Ç into the ddoc source file. Both D and ddoc support Unicode. ;) Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Re: Ali Cehrili on D Ranges at D Conference 2012
On 5/27/2012 2:15 PM, Ali Çehreli wrote: Thanks but the misspelling has overpowered the correct one: Now both the Speakers and the Sessions page has the wrong name! :D Also, there is a rogue Ddoc at the end of the speaker bio. Alas! Someday, I might get this right. Fixed. About the letter, if you are using ddoc as I suspect, just copy paste the Ç into the ddoc source file. Both D and ddoc support Unicode. ;) I generally prefer using named entities, as some of my programs cannot deal with non-ascii. I've also had trouble with copy-pasta of these things, because I'll get the hex value for some random code page, rather than the Unicode code point.
Re: Ali Cehrili on D Ranges at D Conference 2012
On 5/27/12 3:38 PM, Ali Çehreli wrote: On 05/27/2012 01:12 PM, Walter Bright wrote: Elements of containers (and pseudo-containers) are accessed by the range abstraction of D. D's InputRange, ForwardRange, BidirectionalRange, RandomAccessRange, and OutputRange are sufficient to connect many types of containers and many types of algorithms. Most modules of Phobos, including std.range, provide algorithms and ranges that make programs consistent, fast, and easy to maintain. -- http://astoriaseminar.com/sessions.html Great! :) Walter, there is a typo in my last name and it's not the first letter. ;) Also please make sure the C has a cedilla. Andrei
Re: Tutorial on D ranges now on reddit
Le 28/01/2012 04:10, Jonathan M Davis a écrit : On Saturday, January 28, 2012 04:05:53 deadalnix wrote: Le 28/01/2012 03:08, Andrei Alexandrescu a écrit : Just posted it: http://www.reddit.com/r/programming/comments/ozzgn/tutorial_on_d_ranges/ Andrei In this tutorial, save is not a property. I see a lot of code where it is. I do think that save shouldn't be a property, but it would be very interesting if a clear guideline was written on that point. No guide needed. It must be a property, or it won't compile with -property. The fact that properties haven't been being enforced is what's making it so that people are mistakenly not making save a property. As soon as -property becomes the normal compiler behavior, anything that has save as a function rather than a property won't compile. - Jonathan M Davis So this tutorial has to be corrected.
Tutorial on D ranges now on reddit
Just posted it: http://www.reddit.com/r/programming/comments/ozzgn/tutorial_on_d_ranges/ Andrei
Re: Tutorial on D ranges now on reddit
Le 28/01/2012 03:08, Andrei Alexandrescu a écrit : Just posted it: http://www.reddit.com/r/programming/comments/ozzgn/tutorial_on_d_ranges/ Andrei In this tutorial, save is not a property. I see a lot of code where it is. I do think that save shouldn't be a property, but it would be very interesting if a clear guideline was written on that point. If We put that remark aside, this is a great tutorial ! This is exactly the type of docuement we need to promote D and help newcomers. If we succed in getting more of this, we probably would be able to conquier the world soon.