- Combining modified flag with a class member modification - 2 Updates
- Reversing a Linked List using Recursion - 6 Updates
- OT: Github - 1 Update
"Öö Tiib" <ootiib@hot.ee>: Jun 17 01:17AM -0700 On Friday, 16 June 2017 23:09:01 UTC+3, JiiPee wrote: > do lobby-kind of things, its only a program running this particular > simple game. So I was kind of thinking keeping it "simple" rather than > creating many different classes etc. That was not what mine sentence you quoted said. Lets say you already have classes for player and game. When player is guaranteed to be always in game then that for example can make all the checks and handling like if(player.current_game == NULL) unneeded. That *is* keeping it simpler. No? > Player structure to be more general. Although that is not difficult to > do as its a simple game. > I should be thinking ahead even now (even though the game is very simple)? We never know future but it still does not hurt to plan ahead. Otherwise the changes needed later may be so major that it is better to write new program instead of making the changes. |
Richard Damon <Richard@Damon-Family.org>: Jun 17 05:38PM -0400 On 6/16/17 3:38 PM, JiiPee wrote: > mean that the game only starts when the first move is done? evertyghing > before that does not belong to game (like adding player to the > game/modifying players data etc)? Rolling up 'everything' about something in a single class works in some cases, but not in others. Particularly when something can get involved in different contexts. In yoour case I can see the use for several different classes for differing sorts of information in different contexts. It sounds like you have possibly one set of information about a player not connected to any particular game, global information about them. This information would be saved in permanent storage, and perhaps updated by specific actions. A second chunk of data is for a player in a particular game. This data would need to know what player it relates to and what game. This iis where your current points would be stored and updated as the player plays the game. This data might only live in the processors ram, or maybe saved as part of the game if you have that sort of functionality. A last chunk of data would be a historical record. When the game is over, a summary of how they did is stored in permanent storage, and that data is likely never changed thereafter. |
Jerry Stuckle <jstucklex@attglobal.net>: Jun 16 08:18PM -0400 On 6/16/2017 3:39 PM, Chris Vine wrote: > in tail position: there is still a destructor to execute. If on the > other hand it is in tail position, gcc will optimize the function call > away. No, I don't misunderstand. There is much more involved than just the optimization level. And you base everything on gcc - which is not the only compiler - and not always standards-compliant. > that there is "little difference" between tail calls and non-tail calls > as regards stack usage. With gcc and other modern compilers that is > wrong. See above. >> still considered recursive. > I prepended the words "in functional programming". You are talking out > of your ass, not for the first time. Once again you resort to ad hominem attacks instead of the facts. That shows you cannot refute facts. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 17 02:58AM +0200 On 16-Jun-17 5:42 PM, Tim Rentsch wrote: > tail call (usually called tail recursion). Often such function > bodies will be optimized during compilation so recursive calls > are turned into loops rather than calls. Good teaching point. For C++ it's important to note that if there are local variables with destructors, whose destructors run after the recursive call, then the term "tail-recursive" doesn't really apply, and the optimization can be foiled. I.e. one should not write code as if this optimization were an effectively guaranteed feature. In fact it's worse: at least some earlier version of Visual C++ failed to optimize the usual tail recursive factorial function beginner's example, when the return type was floating point (it optimized that tail recursion fine for `int`). > reverse( List &s ){ > s = reverse_onto( s, 0 ); > } [snipped a part that did not include discussion of how this works] > Using tail recursion has given us a nice compact loop to effect > list reversal. At the cost of clarity. > Do you understand how the list reversal functions shown > above work, or is more explanation needed? Can't say I did at first glance, so I am not at all sure that it helped the OP with the question of understanding. Though it probably helped in other ways, including teaching that tail recursion can often be optimized. At first this looked to me like something from a an obfuscated code contest, apparently intentionally using common obfuscation techniques: • uninformative single letter names, • inconsistent naming conventions (`List` versus `list_node`), • the perplexing and apparently misleading name `reverse_onto` (which however does make some sense /after/ figuring out how this works), • expression with side effects, and • a recursive call, indirection, in there, with apparent switching/change of meaning of arguments in each call. Instead I think it's good to teach beginners that • source code is about communicating to humans, not so much about communicating to a compiler. And therefore to use /self-describing names/, except where there is nothing easy to describe or where there is a strongly established convention such as `T` or `i`. And also, consistent with that principle, I think it's good to teach beginners that • programming is not a contest in brevity and terseness. And therefore to not at all be afraid of producing many lines of code, but rather to embrace that eagerly where it improves clarity. But of course, to not do it needlessly. Being able to fit much of the relevant code for something in one screen-full, is helpful in actual work. And third, also consistent with the first principle, that • comments can/should be used for non-obvious things. I rewrote the code according to the above principles: ------------------------------------------------------------------ using List = struct Node*; struct Node { int value; // Having this first supports curly braces init. List next; }; namespace impl { auto reversed( List const s, // A valid list Node* const node_originally_before_s // Start of a rev list ) -> List { if( s == nullptr ) { return node_originally_before_s; } List const rest_of_the_list = s->next; s->next = node_originally_before_s; return reversed( rest_of_the_list, s ); } } // namespace impl void reverse( List& s ) { s = impl::reversed( s, 0 ); } ------------------------------------------------------------------ With self-describing names, consistent naming conventions, unambiguous function name, and no side-effect expressions, the recursive call with the apparent switch/change of arguments should be easier to understand. However, as the English say, the proof is in the pudding. - Alf |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 09:27AM +0100 On Fri, 16 Jun 2017 20:18:53 -0400 Jerry Stuckle <jstucklex@attglobal.net> wrote: [snip] > Once again you resort to ad hominem attacks instead of the facts. > That shows you cannot refute facts. The facts are that: * In response to a poster who said "it's important to write such functions so any recursive call is a tail call", you said "Whether it is head, middle or tail recursion makes little difference in the amount of memory consumed", * That poster was right and you were wrong. Whatever obfuscation you may try to introduce now, as I pointed out the key to the issue with gcc and clang is to avoid having objects in function scope with non-trivial destructors, in order to keep the recursive calls as tail calls. |
guinness.tony@gmail.com: Jun 17 02:11AM -0700 On Saturday, 17 June 2017 01:59:05 UTC+1, Alf P. Steinbach wrote: <snip> > However, as the English say, the proof is in the pudding. No, we don't. We say "the proof of the pudding is in the eating." The mangled (and unintelligible) version you quoted probably originated on the other side of the Atlantic. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 17 12:53PM +0200 > No, we don't. We say "the proof of the pudding is in the eating." > The mangled (and unintelligible) version you quoted probably > originated on the other side of the Atlantic. Thanks! Learned something… :) From <url: https://en.wiktionary.org/wiki/the_proof_is_in_the_pudding >, essentially what you wrote: "Etymology: This phrase is a shortened form of the proof of the pudding is in the eating (14th century). The shorter version dates back to the 1920s and came into common use in the United States in the 1950s." Cheers!, - Alf |
Jerry Stuckle <jstucklex@attglobal.net>: Jun 17 05:33PM -0400 On 6/17/2017 4:27 AM, Chris Vine wrote: > gcc and clang is to avoid having objects in function scope with > non-trivial destructors, in order to keep the recursive calls as tail > calls. Nope. You went on to qualify IF there isn't an object with a non-trivial destructor... IF the function call is in the tail position... IF you use gcc ... IF you use -O2 or -O3 THEN gcc MIGHT make this a iterative call. One can always make special cases. However, the general case is not true. Any change in the above and it won't be iterative. Counting on it being an iterative operation is an invitation to bugs when maintenance changes those conditions and the call is no longer iterative. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
woodbrian77@gmail.com: Jun 16 06:58PM -0700 On Monday, May 29, 2017 at 12:23:35 PM UTC-5, Jorgen Grahn wrote: > only way to avoid broken builds. And you lose most of the benefits of > using Make, compared to using e.g. a straight shell script. --- But > if it works for you, I cannot object. With a new version of g++ and my efforts, a clean build now takes less than 4 seconds on that same machine. Now I'm trying to figure out a travis.yml file that would be helpful. Brian Ebenezer-group - The Name of The L-RD is a strong tower. The righteous runs into it and is safe. Proverbs 18:10 |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment