Jump to content

Yamoto42

Member
  • Posts

    235
  • Joined

  • Last visited

Everything posted by Yamoto42

  1. It is harder to debug code than it is to write it. Therefore if you right the smartest code you are capable of writing, you are not capable of debugging it. To quote "The Zen of Python":
  2. Where I went to college, they combined it and a few other topics with a combined CS/EE design/practicum 2 semester sequence. They would assign group projects projects, and have a few presentations throughout the 2 semester sequence. The lectures though, started with basic design procedures (ie business cases and design docs), after a few weeks of that the lectures went into other rarely covered topics like ethics, patents and legal stuff, etc.
  3. As far as pointers and references...yes. A pointer is just an address and a reference is negligibly different from a const pointer. But again, the original question isn't about a reference or a pointer...it's about an explicitly declared instance. What you're saying doesn't necessarily disagree with what I said. The question is, in memory, what exactly are an 'Entity' and a 'Hero'. Polymorphism is achieved via what are called vtables. The spec doesn't exactly say where they have to be, but where they are located actually doesn't matter so much as how they work. Essentially, a vtable is a table of function pointers. Lets take the following methods: virtual void Entity::spam() { does something; } void void Hero::spam() override { eggs(); } virtual void Hero::eggs() { does something else; } When you create an Entity, the resulting data structure's vtable will have a single entry: Entity.spam() The thing is, the vtable for a Hero also only has a single entry: Hero::eggs(). You see, the actual layout of a Hero has 2 vtables: one for Entity, and one for Hero. Hero::spam() is not an addendum, it is a replacement. It overwrites the Entity::spam() entry in the Hero instance's Entity vtable. Therefore, a raw memory copy of the Entity portion would leave you with a pointer to Hero::spam(), which when called would (correctly, mind you) receive a 'this' pointer of type Hero...meaning it would think it had a valid Hero vtable and thereby a pointer to Hero::eggs()... So, the answer is a copy constructor. They have default implementations that just copy all data members, or you can explicitly declare one. They take a reference to an object of their own type. But being a constructor, they also implicitly contain the logic to properly set up the vtable based on the class. Since the declared variable is an Entity, even if it's being copied form a hero, the Hero constructor won't run and therefore the Entity vtable won't be modified to point to Hero::spam().
  4. Yeah, in C++ you have to be concerned with where and how memory is allocated. If it is not a pointer, it is allocated where the container is. for a local function variable, that means on the stack. Therefore if you declare a 'Hero', the memory layout of 'Hero' is allocated on the stack. However, if you declare an 'Entity', the stack will only have the memory layout of an 'Entity', so (including the vtable, which is a table of virtual function pointers) it can only contain at most the members of an entity. Now, you can probably see how if you are arbitrarily calling virtual methods of 'Entity' that are override by 'Hero', that might cause some major data errors. Even if we assume 'Entity' is written with proper encapsulation, and therefore cannot be erroneously modified by its subclasses, that doesn't let us off the hook. In fact, that is only the lesser problem. All member variables are stored as offsets to the beginning of the data structure...so what happens when a 'Hero' member method is called on an 'Entity'...the answer is we have no idea. It may edit something in the vtable, ie rewriting executable code, or it may rewrite something outside the owning data structure entirely. We have effectively written to a random memory location. But it's actually slightly worse, because it's not truly random. We know it is actually nearby the data structure...and since the data structure isn't dynamically allocated, that is purely relative to its declared location (as opposed to an arbitrary heap allocation and a pointer reference). That is to say the location we have written to is guaranteed to be nearby or on top of other in-use memory. So...instead of doing all that, there is a safe option that the compiler can take: Just make it an 'Entity' and use Entity's copy constructor.
  5. No, but it's far form unheard of to have said getters and setters defined in a purely virtual class. It is a bit overboard for a PODO class, unless it contains some validation logic or needs to guarantee event callbacks are performed, or something else of that like...but especially in languages like C++ where you can avoid runtime dispatch and therefore let optimizer can cut out any of the additional complexity, its never bad practice to properly encapsulate data.
  6. One of the (few) nice thing in java over C# is you can actually reference constructors as delegates.
  7. the interfaces Comparator<T> (for a delegate) and Comparable<T> (defines this.compareTo(T other)) respectively. @BuckGup There's also (since java 8 ) plenty of static methods defined in the Comparator interface for dynamically building more complex Comparators out of simple ones. One thing to remember is to read the documentation. Sometimes things are said about classes and interfaces that aren't necessarily enforceable by the language. In this case about Comparable<T>: "Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false."
  8. Yeah, the big problem with generics in Java is type erasure. Simply put, type parameters are effectively lost at runtime...and it can really messes with overloading and reflection. What you actually get from the compiler is something like: // This is your code public class GenericExample<T> { private T myVar; public T getVar() { return myVar; } public void setVar(T var) { myVar = var; } static main(String ... args) { GenericExample<MyOtherClass> tmp = new GenericExample<>(); MyOtherClass var = 1; tmp.setVar(var); var = tmp.getBar(); } } // This is what the compiler actually compiles public class GenericExample { private Object myVar; public Object getVar() { return myVar; } public void setVar(Object var) { myVar = var; } static main(String ... args) { GenericExample tmp = new GenericExample(); MyOtherClass var = 1; tmp.setVar(var); // Because of compile time checking, there may not be a hard type check here. var = (MyOtherClass)tmp.getBar(); } } You will notice that the compiled class looses its reference to T. Type restrictions are also solved by inserting casts. // Example classes public interface Customer { boolean likesSpam(); } public class GrahamChapman implements Customer { public boolean likesSpam() { return false; } } // What you wrote public class Server<T extends Customer> { private T myCustomer; public Server(T customer) { myCustomer = customer; } public String getBreakfast() { if (!myCustomer.likesSpam()) return "Spam"; else return "Eggs"; } public static main() { Server<GrahamChapman> eric = new Server<>(new GrahamChapman()); String meal = eric.getBreakfast(); } } // What gets compiled public class Server { private Object myCustomer; public Server(Object customer) { myCustomer = customer; } public String getBreakfast() { Customer tmp = (Customer)myCustomer; if (!tmp.likesSpam()) return "Spam"; else return "Eggs"; } public static main() { Server eric = new Server(new GrahamChapman()); String meal = eric.getBreakfast(); } } You'll see again, the type itself looses the actual type information, and the compiler just inserts cases where needed. Without getting into too much detail about dynamic dispatch, a good example of a side effect are the types Collection<Double> and Collection<Integer>: Or more specifically the singular type Collection. public class TypeErasureExample { public double sum(Collection<Double> values) { ... } public int sum(Collection<Integer> values { ... } } Because generics are implement as type Object, then cast to T, the original type T is not stored as part of the type. Ergo, if the above were allowed to compile the runtime would see: public class CompiledTypeErasure { public double sum(Collection values) { ... } public int sum(Collection values) { ... } } And (as return types are not part of a method signature in Java) not know what method to actually call.
  9. I wont necessarily tell you how to do it, but think about how you might be able to store the type information alongside each pointer. Edit: As a minor aside since it's a data structures class, RPN is processed in a stack, not a queue.
  10. Implementation. Interpretation requires a minimum of two operations in the interpreter per instruction of its input. The first operation is interpretation, the second is execution. Let P represent Python and C represent..well..C... the default implementation of the python interpreter is written in C. therefore the speed of a python program must be P >= 2C. BUT, python and C are both Turing complete, so the converse is also possible: writing a C interpreter in python. Therefore the speed of C must be expressible as C >= 2P. It is a paradox. The only thing that has a speed is how much time it takes to execute an instruction on the processor. It's the implementation of the language, the compiler or interpreter, not the language itself that possesses this attribute. And again, because of Turing completeness, implementations are 100% interchangeable.
  11. Speed is not a property of a language to begin with...anyone with half a brain can prove that.
  12. While good practice, it's not the problem. That does nothing to make it run, it only makes it NOT execute if the module is imported as opposed to being the initial entry point....hence good practice. @riklaunim got it with the missing closing parenthesis.
  13. Similar situation I mentioned...actually at AMD's fault. But yes, it has as just as much factual basis as: I can't convert a true believer, so don't expect further responses. But I do hope for all of our sakes you're right and there's nothing shady going on...but even if you are, because you allowed lack of transparency it's inherently impossible to ever know.
  14. Good to know how much credence you give every 12 year old who claims to have 5 FPS less than <insert reviewer here> playing...what do kids play these days? Or perhaps I should word it differently: If this is as harmless as you believe, then anyone worth listening too should have already signed it, thereby And "friendly advice" on selling Intel stock from a board member a few weeks ago in no way can be construed as insider trading...no particular reason for selling...just a hunch. That is to say it doesn't take a law degree to make an argument for intentional testing based on, and with intent to lead to exposure of, confidential data. Because if they lack the integrity to decline the initial agreement...surely we can count on them to leak it when it reaches some (as of yet undefined) goalpost. Because actor A provides evidence that they lack trait B, we can depend on them them performing action C that requires trait B. Your argument is inherently self contradictory. Yes. you must not have read anything I put in parenthesis. I use them rather liberally to ensure I am being as specific as possible.
  15. Actually...there is precedence for this. I honestly forget the details, but I believe it was AMD, actually, a couple of years ago asked its reviewers to use specific settings to avoid their cards'...shall we say weaker points. So, even if they were not to acquiesce to said request, we would effectively be disallowed from knowing the request was made in the first place. But this NDA is not for a "said product". Even if it were, it 'technically' does allow them to disclose known flaws in confidence, and therefore (due to the first sentence of [the first] item 3) bar the flaw form being publicly disclosed (at least by any reviewer) for the effective product lifespan. See also: Xanatos Gambit. That is to say, bringing up the first example...they might actually not be able to share a card's known weak point, since that is confidential information that is not beneficial to Nvidia. What is even more, because again, this is NOT PRODUCT SPECIFIC, it allows Nvidia to approach signers about other..propositions...under its terms. For example...the GPP. But remember, the GPP was made under terms that they knew might become public...and if they're willing to do that publicly...just imagine what they might be willing to try in private.
  16. I've heard convincing arguments for Excel considering how much of the world is run by spreadsheets...
  17. No...we use 2's complement is because it turns the rather complex operation of subtraction into the simple operation of addition, meaning you no longer need separate circuitry for the two operations.
  18. They use python because its the best tool for the job. There's kind of a chicken and the egg situation there. Part of the reason the scientific tools are so well developed for python is because the scientists liked that python was easy to pick up and didn't require much boilerplate...so its ultimately the result of a feedback loop... Python isn't without its problems...duck typing is nice and all...but it leads to documentation that technically tells you what is returned...but not necessarily any indication of how to use it. Method Spam returns an Egg if successful, else none...or maybe every 2nd Tuesday in July on a leap year it returns a Bacon. Ok...well where the heck is the documentation on what an Egg or Bacon is...or at least (since duck typing) their common methods of interest? Sample size AND a bandwagon? not bad... But some people just do have problems disassociating logical constructs from languages. And quite frankly, the real difference between C/C++/Java and python on that front is boilerplate, of which python requires significantly less. I could see how it might be more difficult for someone inexperienced to go from less structured to more structured syntax. Ultimately, given we're talking about network administration and not software development...I'd go with python.
  19. Binary 0111 isn't 7/16. It is just 7. It's an integer...there's no real reason to convert it to a floating point.
  20. It's not just that per se, as that is itself ultimately rooted in the bootstrap problem of cryptography. Much like how people call TCP reliable, yet it is absolutely 100% impossible to create a reliable transport protocol on top of an unreliable medium. It is literally impossible to establish a secure channel within an insecure medium. Therefore we "solve" the problem of impossibility by bypassing the medium entirely at the start of the process (ie. sysadmins externally deciding to mutually trust a CA). As you note, it is not a true solution, but it is the best approximation we have been able to come up with so far to a truly impossible problem.
  21. Yeah...rule 1 of cryptography: Don't do it yourself.
  22. @Unimportant And I do agree as a rule of thumb. J = C+x && J = C <-> x = 0 But the C STANDARD does not guarantee x=0, or that x > 0, or x < 0. Undefined literally means we know nothing about x. It could be negative, making C slower for all the language should assume. And you'd have to be a certain kind of stupid to use an implementation of C where x<=0...which is while it's not TECHNICALLY correct, I do agree in general.
  23. In object oriented programming, there is a concept of abstract and concrete types. Concrete types are what you are likely familiar with. They consist of data, methods, etc. Abstract classes are similar to concrete classes, except they may have data or methods that are DECLARED, but not DEFINED. As an example: public class Concrete { public Int32 GetAnInt() { return 42; } public Int64 GetALong() { return 1234567890; } } public abstract class Abstract { public Int32 GetAnInt() { return 64; } public abstract Int64 GetALong(); } Now, because the definition of Abstract is incomplete, you cannot call its constructor...but don't worry about that for now. We have a special case for classes where NOTHING is defined. We call them interfaces. // By convention in C# we start them with an uppercase I public interface INumberMaker { In32 GetAnInt(); } public class Spam : INumberMaker { public In32 GetAnInt() { return 42; } } public class Eggs : INumberMaker { public In32 GetAnInt() { return 64; } public In64 GetALong() { return 42; } } Now for teh code ... INumberMaker myNum = new Spam(); System.out.println(myNum.GetAnInt()); // Will print 42 myNum = new Eggs(); System.out.println(myNum.GetAnInt()); // Will print 64 System.out.println(myNum.GetALong()); // Will not compile ... What we have effectively done is said "I don't care what myNum is, as long as it has a method called GetAnInt() that returns an Int32." The second time we assign it, it may have a method called GetALong...but we don't care. By DECLARING it of type INumberMaker, even though we INSTANTIATED eggs, we have explicitly said INumberMaker and its GetanInt() method is all we care about. That's what interfaces are used for. We declare what matters, for example IList<T> defines what MAKES a list, but not how it is implemented. It says what does a list do? It stores items an a specific order, allows retrial based on their order, etc... It doesn't say how they are stored, only that they exist and what method names will be used to access them. (this is called an API) List<T> then says "lets store it as an array" and LinkedList<T> says "Lets store it as a path of nodes". But they both implement IList<T>. ...and in this case your code should care about how it's ACCESSED, not how its STORED. That decision only has to be made once...and it may often change. If your code needs to know how its stored, you've probably put too much responsibility on a single area. Let the initialization worry about how its stored, let the accessor only worry about how its accessed.
  24. I do understand what you are saying. And no reasonable implementer of the the C language would perform a bound check on the array access...or for that matter differentiate it from pointer arithmetic...much like no reasonable C programmer would not take the time (read development cost) to write the check themselves before making the access in any non-trivial situation. But a rule of thumb is not necessarily technically correct. The thing is this: Speed is in no way an attribute of the language. It is entirely an attribute of implementation. I keep bringing up Turing completeness because its core concept creates contradiction when speed is considered an attribute of the language. If a language, lets call it A (C wat I did thar?), is Turing complete, then by the definition of Turing completeness I can write an interpreter for A in the A language itself...That quality is exactly what lets you write a C compiler in C. Now, if you write a program in A, and compile it with Richard M. Stalin's latest gaa compiler, then run it in my A interpreter, then only two results are possible: They finish at the exact same time or one finishes before the other (it doesn't matter which one is first). Now, since my A interpreter is doing effectively run-time compilation AND execution, it is performing more computation than the result of gaa. From this, if the programs complete at the same time, since the extra work included the execution time of both must have been zero. Both execute your program A, but one has run-time compilation overhead. A * n = A * (n+x) -> A = 0...so I feel comfortable throwing that out saying they won't finish simultaneously. But what happens if they don't finish simultaneously? Well, if speed is an attribute of the language and not the implementation you are effectively saying A != A. //======== In practice, however, the latter will tend to be true. They will not finish simultaneously. However, it is not a contradiction because the difference comes from the native language vs. interpreted IMPLEMENTATIONS. In fact, it's largely a moot point because my computer doesn't speak C, java, or python. It only speaks x86...if anything we're more debating compilers than languages... But as a rule of thumb, I fully agree a program written in C will halt faster than a program written to perform the same task in Java or Python....but the key phrase is "rule of thumb".
×