So I just had a "magic"/"more magic" moment today.

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Steve the Pocket
Posts: 592
Joined: Mon Apr 23, 2007 4:02 am UTC
Location: Going downtuuu in a Luleelurah!

So I just had a "magic"/"more magic" moment today.

Postby Steve the Pocket » Thu Dec 17, 2009 9:44 pm UTC

I just thought I'd share this, since most of you have probably read the story of the mysterious switch that was linked to on the XKCD Store page. If you haven't, read it now; I'll wait.

Anyway, I had such an experience today, in Flash of all things, working on a project for work.

It was a Christmas e-card I had made last year, and the client wanted to re-release it with some edits. So I opened up the old file, resaved it with a new name, and went to work. There were several objects in the object library that were no longer needed, so I deleted them. One, strangely, was a movie clip (Flash's term for any object that you can manipulate with ActionScript code) labeled "blankMovie" that was, indeed, blank. One frame, nothing in it. No code, no reference to it in any other code, and as far as I could tell the clip wasn't in the main timeline anywhere either. So I deleted it too, assuming from the name that it was like those "New Folder"s I occasionally create by accidentally hitting the "New Folder" button in Windows.

That was the other day. Today I was putting in the last changes, namely replacing the two music clips with the ones the client had just emailed me, and compiled and tested the finished file. Everything worked smoothly up to the point where clicking a button makes the first piece of music fade out and a second one fade in. Instead, the second piece of music started and they immediately both faded out. I remember having the same problem when I first designed the thing last year, but couldn't for the life of me remember what I had done to fix it, and more importantly why it wouldn't still work. I inspected every piece of code I could find, and none of it seemed to have been changed, so I was stumped.

Then it hit me. I opened up the old version, removed the blankMovie object, recompiled as "temp" and tested it. Sure enough, same problem. I copy-pasted blankMovie into the new file's library, hoping desperately that was all I needed to do, and of course it wasn't. So I started copying my new material into the old file and testing it, and even after replacing the music clips (which were tagged with different names than the first ones), it worked perfectly.

I still have no freaking clue where I had placed blankMovie in my timeline (being blank, it would be invisible) or why it made the darned thing work. All I know is that it's somehow critical to the operation of the file. It's my own little "more magic" switch. :)
cephalopod9 wrote:Only on Xkcd can you start a topic involving Hitler and people spend the better part of half a dozen pages arguing about the quality of Operating Systems.

Baige.

User avatar
lulzfish
Posts: 1214
Joined: Tue Dec 16, 2008 8:17 am UTC

Re: So I just had a "magic"/"more magic" moment today.

Postby lulzfish » Fri Dec 18, 2009 7:51 pm UTC

Except in this case, it's merely proof of how terrible Flash is.

User avatar
TheChewanater
Posts: 1279
Joined: Sat Aug 08, 2009 5:24 am UTC
Location: lol why am I still wearing a Santa suit?

Re: So I just had a "magic"/"more magic" moment today.

Postby TheChewanater » Sat Dec 19, 2009 3:48 am UTC

So, is this "The 'IT DOESN'T WORK!' Thread", except more like "The 'IT DOES WORK!' Thread"?
ImageImage
http://internetometer.com/give/4279
No one can agree how to count how many types of people there are. You could ask two people and get 10 different answers.

User avatar
MHD
Posts: 630
Joined: Fri Mar 20, 2009 8:21 pm UTC
Location: Denmark

Re: So I just had a "magic"/"more magic" moment today.

Postby MHD » Sat Dec 19, 2009 9:05 pm UTC

Sometimes MingW compilers do that too. Having a line of C++ code that does nothing at all and if it's there the program works, if it isn't it segfaults.
EvanED wrote:be aware that when most people say "regular expression" they really mean "something that is almost, but not quite, entirely unlike a regular expression"

User avatar
headprogrammingczar
Posts: 3072
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: So I just had a "magic"/"more magic" moment today.

Postby headprogrammingczar » Sun Dec 20, 2009 1:13 am UTC

I had that in Java once. If you added an empty comment to the beginning of the main method, it worked. If you didn't, when you pressed a button with no listeners, an anonymous JLabel teleports halfway across the window.
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you

Alexander The 1st
Posts: 44
Joined: Fri Apr 17, 2009 10:47 pm UTC
Contact:

Re: So I just had a "magic"/"more magic" moment today.

Postby Alexander The 1st » Mon Dec 21, 2009 1:39 am UTC

#usr/bin/env/python

Makes no sense to me; I understand that it's the file path for python in Linux sometimes, but since I'm on Windows, I don't see the purpose of this line at all - it's in a comment, none the less!

Doesn't help that almost everyone who puts this into their code doesn't explain it - those that do just say "You need this line on Unix machines".

...So great - why should I bother what line, if I do python linux server work?

Clear example of work/more work.
...YOU DIDN'T SEE ANYTHING...

Ended
Posts: 1459
Joined: Fri Apr 20, 2007 3:27 pm UTC
Location: The Tower of Flints. (Also known as: England.)

Re: So I just had a "magic"/"more magic" moment today.

Postby Ended » Mon Dec 21, 2009 1:54 am UTC

Alexander The 1st wrote:Makes no sense to me; I understand that it's the file path for python in Linux sometimes, but since I'm on Windows, I don't see the purpose of this line at all - it's in a comment, none the less!

It's a shebang - its purpose is to tell the OS which interpreter to use to run the script (in this case, python).
Generally I try to make myself do things I instinctively avoid, in case they are awesome.
-dubsola

User avatar
lulzfish
Posts: 1214
Joined: Tue Dec 16, 2008 8:17 am UTC

Re: So I just had a "magic"/"more magic" moment today.

Postby lulzfish » Mon Dec 21, 2009 1:55 pm UTC

Yeah. If you call "./script.py", the shell reads the first line to check for a hashbang and then calls that interpreter to read the script.
You don't need it if you call "python script.py".

User avatar
Arancaytar
Posts: 1641
Joined: Thu Mar 15, 2007 12:54 am UTC
Location: 52.44°N, 13.55°E
Contact:

Re: So I just had a "magic"/"more magic" moment today.

Postby Arancaytar » Mon Dec 21, 2009 2:05 pm UTC

Alexander The 1st wrote:#usr/bin/env/python

Makes no sense to me; I understand that it's the file path for python in Linux sometimes, but since I'm on Windows, I don't see the purpose of this line at all - it's in a comment, none the less!

Doesn't help that almost everyone who puts this into their code doesn't explain it - those that do just say "You need this line on Unix machines".

...So great - why should I bother what line, if I do python linux server work?

Clear example of work/more work.


Note that you're missing an exclamation mark on that, which means it will break on Unix (on Windows the line is just ignored since it goes by file extension). The point is that this line is not read by Python at all on Unix, so it's not really a "comment". It's read by the shell interpreter, which implicitly interprets every script you execute in a shell. The shell interpreter then knows which other interpreter to use; otherwise it will assume you are executing a .sh file.
"You cannot dual-wield the sharks. One is enough." -Our DM.
Image

User avatar
Resuna
Posts: 1
Joined: Tue Apr 30, 2013 2:46 pm UTC

Re: So I just had a "magic"/"more magic" moment today.

Postby Resuna » Tue Apr 30, 2013 3:04 pm UTC

Actually, the Shebang is interpreted by the operating system. Shebang was invented in Version 7 UNIX, as a result of the split between East Coast UNIX and West Coast UNIX.

In Version 6 UNIX there was only one shell. It was a pretty horrible shell, too. It didn't have control structures. It didn't have comments. It didn't have file name expansion or wildcards - they were sort of transparently handled by having the shell run a separate program called "glob". You couldn't pipe into shell scripts because the shell interpreted scripts by reading them from standard input. There was no buffering, so it was possible to control the flow of a shell script by seeing around on standard input, looking for a line starting with ":" to indicate a label. ":" wasn't a comment marker, mind, it was a command that didn't do anything, like /bin/true. It may have even been a link to /bin/true.

On the east coast, this fellow at AT&T named Steve Bourne was coming up with a new shell that would end up in Version 7 UNIX.

On the west coast, there were two competing improved shells, the pascal shell (which never took off) and the C shell.

The C shell had control structures and comments and all kinds of cool stuff. The comment character was "#". So when you ran a shell script it forked, opened the file, and looked at the first character, and if it was "#" it execed a new instance of the C shell to interpret it, otherwise it just execed the old /bin/sh with stdin set to the file. OK, that's a lot of jargon, let's just say that the first character was used by the C shell to determine what shell to use to run the script.

Now I'm going to digress into more jargon. When the kernel ran a program, it used the first two bytes of the program to determine how to run it. Originally it just loaded the program and jumped into location zero, but by the time of V6 and V7 there were a number of different things that had to be done to set up the program, so it opened up the file and read the first two bytes. If the first two bytes were a jump to one particular location, it knew it was one kind of program, if it was a jump to another location, it was another kind of program. So this jump instruction became a "magic number" that the kernel used to decide how to run the program. Other magic numbers got created, and they didn't have to be PDP-11 jump instructions, (or even run on a PDP-11) but one number was as good as any other so those just happened to be kept.

Anyway, by this time in UNIX the first 16 bits of the program was a magic number... the kernel read it and used that to decide how to run a program.

OK, in Version 7, they defined a new 16-bit magic number whose value looked like "#!" and said "this magic number is interpreted by reading a line of text, breaking it up into two words separated by a space, and calling an interpreter whose name was in the first word, and passing the second word and the name of the file to that interpreter".

This was the Shebang born. Like many great ideas it was simple, brilliant, and extraordinarily useful.

User avatar
amylizzle
Posts: 41
Joined: Sat Mar 02, 2013 10:02 pm UTC

Re: So I just had a "magic"/"more magic" moment today.

Postby amylizzle » Tue May 07, 2013 6:12 pm UTC

Resuna wrote:Actually, the Shebang is interpreted by the operating system. Shebang was invented in Version 7 UNIX, as a result of the split between East Coast UNIX and West Coast UNIX.

In Version 6 UNIX there was only one shell. It was a pretty horrible shell, too. It didn't have control structures. It didn't have comments. It didn't have file name expansion or wildcards - they were sort of transparently handled by having the shell run a separate program called "glob". You couldn't pipe into shell scripts because the shell interpreted scripts by reading them from standard input. There was no buffering, so it was possible to control the flow of a shell script by seeing around on standard input, looking for a line starting with ":" to indicate a label. ":" wasn't a comment marker, mind, it was a command that didn't do anything, like /bin/true. It may have even been a link to /bin/true.

On the east coast, this fellow at AT&T named Steve Bourne was coming up with a new shell that would end up in Version 7 UNIX.

On the west coast, there were two competing improved shells, the pascal shell (which never took off) and the C shell.

The C shell had control structures and comments and all kinds of cool stuff. The comment character was "#". So when you ran a shell script it forked, opened the file, and looked at the first character, and if it was "#" it execed a new instance of the C shell to interpret it, otherwise it just execed the old /bin/sh with stdin set to the file. OK, that's a lot of jargon, let's just say that the first character was used by the C shell to determine what shell to use to run the script.

Now I'm going to digress into more jargon. When the kernel ran a program, it used the first two bytes of the program to determine how to run it. Originally it just loaded the program and jumped into location zero, but by the time of V6 and V7 there were a number of different things that had to be done to set up the program, so it opened up the file and read the first two bytes. If the first two bytes were a jump to one particular location, it knew it was one kind of program, if it was a jump to another location, it was another kind of program. So this jump instruction became a "magic number" that the kernel used to decide how to run the program. Other magic numbers got created, and they didn't have to be PDP-11 jump instructions, (or even run on a PDP-11) but one number was as good as any other so those just happened to be kept.

Anyway, by this time in UNIX the first 16 bits of the program was a magic number... the kernel read it and used that to decide how to run a program.

OK, in Version 7, they defined a new 16-bit magic number whose value looked like "#!" and said "this magic number is interpreted by reading a line of text, breaking it up into two words separated by a space, and calling an interpreter whose name was in the first word, and passing the second word and the name of the file to that interpreter".

This was the Shebang born. Like many great ideas it was simple, brilliant, and extraordinarily useful.


That was a good post, and you should feel good.

EvanED
Posts: 4314
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: So I just had a "magic"/"more magic" moment today.

Postby EvanED » Tue May 07, 2013 6:22 pm UTC

Resuna wrote:This was the Shebang born. Like many great ideas it was simple, brilliant, and extraordinarily useful.
Agreed except for the "two words" bit. The fact that you can't say, for instance, #!/usr/bin/env python -u and have it not do something stupid, is occasionally very annoying.

(That example is where I first learned about the limitation; it's not a great example as you can set that from inside the interpreter. But that's not a general solution, and in general it's more obnoxious..)

User avatar
TheChewanater
Posts: 1279
Joined: Sat Aug 08, 2009 5:24 am UTC
Location: lol why am I still wearing a Santa suit?

Re: So I just had a "magic"/"more magic" moment today.

Postby TheChewanater » Thu May 09, 2013 2:40 am UTC

You can put the program in a here document.

Code: Select all

#!/bin/bash
python -<< 'EOF'

print 'test'

EOF


The disadvantage is that you will not be able to use stdin within the program. The cool thing, though, is that you can use it with lisp interpeters that normally don't work with shebangs because # doesn't start a comment.
ImageImage
http://internetometer.com/give/4279
No one can agree how to count how many types of people there are. You could ask two people and get 10 different answers.

EvanED
Posts: 4314
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: So I just had a "magic"/"more magic" moment today.

Postby EvanED » Thu May 09, 2013 2:53 am UTC

TheChewanater wrote:You can put the program in a here document.

Code: Select all

#!/bin/bash
python -<< 'EOF'

print 'test'

EOF


The disadvantage is that you will not be able to use stdin within the program. The cool thing, though, is that you can use it with lisp interpeters that normally don't work with shebangs because # doesn't start a comment.
The other disadvantage is that it's really ugly and stupid. :-)

And saying "you can't use stdin" to me is pretty much like saying "don't worry about me hitting you with this baseball bat; it's like a feather, but harder." But yes, you can.

jareds
Posts: 435
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: So I just had a "magic"/"more magic" moment today.

Postby jareds » Thu May 09, 2013 6:56 am UTC

If you're willing to use crazy bash features, you can do this:

Code: Select all

#!/bin/bash

python -u <(cat <<'EOF'

line = raw_input('> ')
while line != '':
    print line.upper()
    line = raw_input('> ')

EOF
)

The bash docs call this feature "process substitution". <(stuff) will create a named pipe, run stuff with the named pipe as its stdout, and substitute the pipe's name for <(stuff). Still ugly though.

EDIT: Warning! This isn't just ugly, but kind of broken because bash looks for the closing parentheses of the "<(" with some sort of shitty parsing that doesn't recognize here-documents. This might not quite be a problem for Python most of the time because its strings and comments match shell syntax pretty well, but it's easy to see the problem if they don't:

Code: Select all

$ cat /tmp/scheme.sh
#!/bin/bash

racket -f <(cat <<'EOF'

; unmatched )
(display "test\n")

EOF
)
$ /tmp/scheme.sh
/tmp/scheme.sh: line 5: warning: here-document at line 3 delimited by end-of-file (wanted `EOF')
default-load-handler: cannot open input file: "/dev/fd/63
(display test\n)

EOF
)" (No such file or directory; errno=2)


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 9 guests