Jump to content

Wikipedia:Reference desk/Archives/Computing/2016 November 19

From Wikipedia, the free encyclopedia
Computing desk
< November 18 << Oct | November | Dec >> November 20 >
Welcome to the Wikipedia Computing Reference Desk Archives
The page you are currently viewing is an archive page. While you can leave answers for any questions shown below, please ask new questions on one of the current reference desk pages.


November 19

[edit]

Where can I get this book for reference?

[edit]

Hello, I'm currently doing a college seminar on the topic Special Effects in TV. When I googled, I came to know about 2 books by Bernard Wilkie - Special Effects in Television (1995), The technique of special effects in television (1971). But I couldn't find any digital version of these books anywhere on the internet, for the purpose of reference. Could anyone help me?--Joseph 05:20, 19 November 2016 (UTC)[reply]

Have you looked for them in print at public library, or a college library? If they don't have a copy themselves, they should be able to obtain them by interlibrary loan, though this takes time. --76.71.5.45 (talk) 09:25, 19 November 2016 (UTC)[reply]

Canonical deliberate undefined behavior

[edit]

Suppose I have an abstract List interface with multiple implementations:

struct List {
  virtual int size() const=0;
  virtual float& get(int)=0;
};
struct Array : List {
  float *a;
  int sz;
  Array(float *p,int n) : a(p),sz(n) {}
  int size() const {return sz;}
  float& get(int i) {return a[i];}
};
struct Empty : List {
  int size() const {return 0;}
  float& get(int) {}   // what goes here?
};
float sum(List &l) {
  float ret=0;
  for(int i=l.size();i--;) ret+=l.get(i);
  return ret;
}

(In general, Array is much more complicated, so that Empty e; cannot trivially be realized as Array e(0,0);.) What should Empty::get() do? It's valid the way it is; like for a real array of size 0 (new float[0] is valid!), calling Empty::get() with any argument at all should be undefined behavior. The undefined behavior (from flowing off the end) doesn't happen, because sum() knows better than to actually call Empty::get() at all. But there will be an egregious warning. There are a variety of relatively obvious options, but none of them are very good:

  1. Define it as deleted: float& get(int)=delete; (This is ill-formed: overrides of non-deleted functions can't be deleted.)
  2. Don't define the function: float& get(int);. (But then you fail to link, even if no one actually calls the bad function.)
  3. Return float instead: float Empty::get(int) {return 0;}. (But the reference can be important.)
  4. Return a local variable by reference: float& Empty::get(int) {float f; return f;}. (But that'll still be a warning.)
  5. Return a "null reference": float& Empty::get(int) {return *reinterpret_cast<float*>(0);}. (No warning from the compilers I tried, but I'd not be surprised if one were added. Also, it's ugly.)
  6. Return a static: float& Empty::get(int) {static float f; return f;}. (But allocating memory for nothing is dumb.)
  7. Throw something: float& Empty::get(int) {throw 0;}. (But that's not undefined behavior: someone could catch it.)
  8. Throw nothing: float& Empty::get(int) {throw;}. (But that's not undefined behavior: you just call terminate() if there's no current exception.)
  9. Abort: float& Empty::get(int) {std::abort();}. (But that's not undefined behavior.)

What's the canonical way to write "no, really, this is supposed to be undefined behavior"? --Tardis (talk) 05:28, 19 November 2016 (UTC)[reply]

Just do anything. Calling a.get(-1) or a.get(a.size()) on a valid Array a variable is UB, too, and you do nothing to handle it. Undefined behavior is just undefined, i.e. a program can do anything—it can produce some reasonably looking result, it can crash or proceed with some garbage data...
You can, of course, detect validity of n in Array::get(int) and throw some exception or raise a signal in case of invalid call; then you just make Empty:get(int) to do the same. But, as you noted, that is a defined behavior. AFAK there is no way to define in the code an undefined behavior...
Specifically, to cause an UB in this case you could take step 4, 5 or 6, and add a comment // Watch out, UB here. --CiaPan (talk) 09:30, 19 November 2016 (UTC)[reply]
I'm not interested in trapping bad input to Array::get(), but rather in not needlessly trapping it in Empty::get(). Put differently: of course a.get(-1) is UB; it is exactly that "natural" UB (Array::get() is UB exactly when you shouldn't be calling it) that I'd like to express in Empty::get(). The problem there is that all calls should be UB, and the compiler quite reasonably warns about a function that always results in UB. (This is not a reasonable thing to want, except in the case of a "poisoned" virtual override like this.)
I find myself wanting a function std::undefined() which is simply specified to have undefined behavior (something of an oxymoron, but it has already been implemented as __builtin_unreachable()), along the lines of the "unreachable" instruction in LLVM. Compilers would know better than to warn about its use, but could still do whatever appropriate optimizations based on the assumption that it was never called. (There aren't any optimizations to be had "through" a virtual call, so there's very little to be gained: theoretically, they could at least remove a virtual function that always had UB entirely and leave a dummy value in the vtable.)
I also thought of one more "obvious" way to provoke UB, infinite recursion: float& Empty::get(int) {return get(0);}. This also gets no warning (from G++ 5.4.0 with -W -Wall), and compiles at -O2 or better into an infinite loop(!) by tail recursion elimination. (From a practical perspective, I'd rather have a signal, but that's why they call it undefined; I can write abort() if I really want to.) --Tardis (talk) 15:38, 19 November 2016 (UTC)[reply]
I really don't understand why you'd want to invoke undefined behavior in the first place. It serves no other purpose than to create headaches for users trying to debug programs and degrade the quality of your software in general. Do something sensible instead: disable the function (ie: declare, but don't define it), throw an exception or, if nothing else, return a null reference. Just my opinion, of course... Earl of Arundel (talk) 18:05, 19 November 2016 (UTC)[reply]
I gave the reason in the example: to give a definition for a virtual function that, for a certain concrete class, shouldn't be called (and which has an obvious analogy to undefined behavior in the other classes). The purpose of undefined behavior in general is optimization; here the challenge is to write some function that compiles without warnings and preferably avoids doing useless work just to avoid them. Disabling the function doesn't work here because the vtable for Empty would be incomplete; a "null reference" is undefined behavior itself (although I'm not sure there's any text in the standard that explicitly disallows dereferencing a null pointer if all you do is bind a reference to the result). --Tardis (talk) 23:22, 19 November 2016 (UTC)[reply]
The only good thing about C++'s undefined behavior is that it enables various speed and space optimizations. In every other way it's bad. Empty::get obviously doesn't need to be fast. If you absolutely must make your executable as small as possible, putting __builtin_unreachable() (or the MSVC equivalent __assume(false)) in the function body will make compatible compilers generate no or minimal code for that function. (What they'll put in the vtable is anyone's guess. If you're lucky it'll be a null pointer, but it could be a pointer to whatever function happens to come next in the code segment, for example.)
If you don't need to save those few bytes, then I recommend something like { assert(false); throw std::out_of_range("Empty::get"); }, or absolutely anything else with defined behavior, over anything with undefined behavior. -- BenRG (talk) 23:44, 19 November 2016 (UTC)[reply]

why have they suddenly started promoting programming and STEM?

[edit]

everyone (Mozilla, Microsoft, WolframAlpha) seems to have some online program going on to teach people how to code. is it some weird social engineering thing? It's like DOSAAF, seriously. is it to make people think like machines? or to press wages? but the West can't out-cheap India. Even if everyone was a coder, wages can't fall below housing and food. This is the limiting factor, not the supply in labor. Asmrulz (talk) 12:52, 19 November 2016 (UTC)[reply]

This sounds like a rant to me. What's the question? Llaanngg (talk) 13:23, 19 November 2016 (UTC)[reply]
the question is %topic%. There is some recent, organized and well-funded effort to bring coding to the masses. Why? Don`t be distracted by the form Asmrulz (talk) 13:27, 19 November 2016 (UTC)[reply]
It might help us to understand you if you could point to some evidence of this "organized and well-funded effort". Or are you only seeing spam on your computer?--Shantavira|feed me 16:05, 19 November 2016 (UTC)[reply]
I have noticed no special drive to get adults to understand programming. The only drive I have seen to educate adults is to enable them to be able to read and even that is fairly low-key. Dmcq (talk) 19:06, 19 November 2016 (UTC)[reply]
Computers were, until some years ago, prohibitively expensive. I dare to say that they became a common household item only in the mid/late 90s. From the 70s until then, some people bought one for their home, but it was something kind of onerous for a middle-class family. They were also not so useful and easy to use as we know them today. It was meaningless to bring programming to the masses.
If nowadays companies like Mozilla, Microsoft, and Wolfram Alpha -among others- teach some IT skill, it's more plausible that this is for teaching people how to use their respective technologies. It's more about changing the market for their products or services, either obtaining direct clients, or bringing more developers (= cheaper) into the work-force, than changing society as a whole or enlighten people.
BTW, I don't see anyone promoting STEM. Are science, engineering and math also being promoted? Llaanngg (talk) 01:19, 20 November 2016 (UTC)[reply]
Your observation can be restated as, "Why are computer and software companies promoting more advanced use of their computers and software?" Then, I could be snarky and ask if you've noticed grocery stores promoting cooking or auto parts stores promoting car repairs. I might note that I've seen home repair lessons at both Lowes and Home Depot. Our local indoor pool has swimming lessons and our gym offers free workout lessons every now and then to get new members. Perhaps it is all a secret evil plot to get more customers and make more money. 71.85.51.150 (talk) 00:06, 21 November 2016 (UTC)[reply]
There is a rising trend. You can see it in the Raspberry Pi. But I also have heard it from politicians. But in earlier years there has been some of Keep it Simple Stupid. Instead of Lizards, do you mean Reptilians? Graeme Bartlett (talk) 11:09, 21 November 2016 (UTC)[reply]

Why symbols in Scheme?

[edit]

Why do they have something that's neither a variable nor a string? Couldn't we just use a string instead, like "abcd" in Python, when you don't want to execute something? And, use something like the pythonian eval("abcd") when you want to run it? — Preceding unsigned comment added by 123abcnewnoob (talkcontribs) 13:18, 19 November 2016 (UTC)[reply]

symbols are variables. they have two "slots", a function and a numeric or string value, in "2-lisps" such as the actual Lisp (accessible via (symbol-function n) and (symbol-value n), hence the whole function quoting thing (#'), and either one at a time in "1-lisps" such as Javascript. Thus in 2-lisps, you have to specify which one you mean. If you mean the function, you have to use (funcall f) to call it, whereas in Javascript, you can just do var x=function...; x();. Asmrulz (talk) 13:34, 19 November 2016 (UTC)[reply]
Scheme does not have two namespaces.
To the original question, I guess you are referring to functions. Those are compiled just like Python is compiled. Doing eval in Python can be a bit of a mess and you need to be careful about the environment passed over to eval. The argument is compiled and then executed and then thrown away. If you will have a more careful look at your directory with Python you'll notice .pyc files - they are the compiled versions of your source. For your Scheme presumably you have your source in a file just like in Python. Dmcq (talk) 19:21, 19 November 2016 (UTC)[reply]
Yes, if you're using eval, and you aren't an expert and understand exactly why using it is necessary in your situation, you're probably doing Bad Things. Read [1]. Chances are you've fallen into the XY problem trap, where you don't understand how to do something the Right Way but managed to figure out that if you kludge together some code dynamically and eval it, it seems to do what you want. --47.138.163.230 (talk) 01:03, 20 November 2016 (UTC)[reply]
For Scheme, it's always worth to read one of the RNRS standards - I recommend R5RS, because it is still fairly short and simple, and because I'm an old fart. In Scheme, a variable is just a place in memory that can hold a value (which, in Scheme, can of course also be a function). To be able to actually use that variable, you need to bind it to a symbol (what other languages call "variable name"). Symbols have several advantages/differences compared to strings. Symbols are immutable, and typically, the number of symbols in a program is smallish and the set of symbols is mostly static. Thus, symbols typically are implemented as tagged pointers into a symbol table (which stores the actual name). That means that comparing two symbols for equality is a one-word comparison, and it is quite easy to e.g. use symbols as keys into a hash map. Strings, on the other hand, are a more dynamic data types. Strings are created and destroyed, and in Scheme, strings are even mutable. Thus, strings are very rarely shared, and each string is stored in a separate memory location. So comparing two strings needs to be done by iterating over both strings in parallel, which is typically orders of magnitude slower than a single pointer comparison. --Stephan Schulz (talk) 20:30, 19 November 2016 (UTC)[reply]