Questions and Answers
Here are my answers to the questions you asked on the registration survey. If you think of questions that were not asked, feel free to send them later (you can just send them to me buy email, which can be anonymous if you want the question to be anonymous).
In general, interfaces are a big challenge in computing. To make systems secure and robust, we want their interfaces to be narrow (that is, they can only do a small set of things, and there is a limited way of requesting them); to be powerful and general, we want universal interfaces (like programming languages) that an be used to do anything.
Computer science is excellent preparation for a wide range of careers. I know of recent CS majors who have gone on to build companies, law school, medical school, government, teaching, and consulting. The most direct careers are in software development (about 40% of CS majors go into software development jobs), but there are lots of possibilities.
For UVA computer science graduates, UVA Magazine has a nice visualization of where students go after graduation: Two Roads Diverged in a Wood
Like most things, what you get out of this course will depend greatly on what you put into it. As a 3-unit course, the course is supposed to involve 9 hours of academic work per week (which means 6.5 hours of work per week outside of class, assuming you are coming to all the classes and they count as academic work, which is sometimes questionable!). My intent is to design the course so that typical students will be able to succeed in it without working more than this amount (although working really means "working", in a focused and effective way during that time).
That said, I don't think any students in cs1120 are "typical". Some students may find it necessary to put in considerably more work than this to succeed in the course, and others will (hopefully) find the material and assignments so engrossing and enchating that you will be tempted to spend all of your time on them (perhaps to the detriment of other responsibilities). You should let me know if you feel like you are spending an unreasonable amount of time on the course (either because you find it necessary to succeed, or becuase you are becoming dangerously addicted to computing), but also keep in mind that many of the major assignments in this course are scheduled for two weeks so if you don't do any work on them for the first week, you should not be surprised if you need to spend 13+ hours on them the second week.
First, I question the premise — math isn't something people are inherently good or bad at, but something everyone can learn and improve at. People often struggle with math because they never recover from bad early experiences, and approach new math with fear and intrepidation instead of optimism and excitement. If certain early concepts are not learned well then everything that builds on them seems confusing and disconcerting. Smart and hard-working students can often find ways to get through math classes despite this, but without fixing the mental blocks that prevent everything from making sense as a whole find things to be much harder and less enlightening than they should be. (For more views on this, see You’re Not Actually Bad at Math (Slate, 3 September 2015) and The Myth of 'I'm Bad at Math' (The Atlantic, 28 October 2013).)
All that said, the math that is used in computing is quite different from most of the math you have encountered so far. In particular, we focus on discrete math (that is, math involving whole numbers), wheras most of math after about fourth grade (in the US) is dominated by continuous math (real numbers, as used in trigonometry, calculus, etc.). We also focus on using math as a tool for insight, not as a goal in itself. Often, there are many ways to gain the same insight, and the power of computing can enable us to gain keener insights with simple math than would be obtained using complex math without computing.
In general, the best way to improve one's programming ability is to attempt to solve problems just at the edge of your ability so you keep pushing yourself to learn new things, and then to work with mentors that are a level or two about you to learn new tricks and better ways to do things.
There are tons of great, free materials for learning programming. Different things work best for different people, so I'm wary of giving any specific recommendations, but some resources that many people find useful (and I think are mostly good) are:
Swaroop's A Byte of Python book.
MIT Introduction to Computer Science and Programming Open Courseware course taught by John Guttag.
Rice Interactive Python course (on Coursera.org) - uses Python to implement an interactive game.
Allan Downey's Think Python book.
Zed Shaw's Learn Python the Hard Way - lots of details and practice on the mechanics of writing Python programs.
Project Euler - progressive sequence of programming problems (mostly focused on math problems)
The real question should be why is course enrollment done by senority!
It is much more important that first year students get the courses they want, since they can impact what they do the rest of their time at the University (not to mention after that). By the time someone is a 3rd or 4th year, the potential impact of a class is much less (there are, of course, exceptions, and plenty of students don't really figure out what they want to do until their 4th year, but it is a lot tought to work out a different plan at that stage). The other reason early students should have priority is that by their 3rd year, students should have either learned on their own or hopefully both built strong enough relationships with some faculty to be able to get good advice on how to get what you want. I don't know of any case where a third-year student who really wanted into a course and did all the right things to make that happen wasn't able to get into the course they wanted, but it is much less fair to expect a first-year student to be confident and savvy enough to expect to be able to bend the rules.
Hence, the only way I could figure out with SIS to override the backwards system that is used for default registration, was to limit the class to 1st and 2nd years, until they had a fair chance to register. If the University switches to a reverse-seniority registration system, I won't need to have any restrictions.
By the end of the lessons in the Udacity cs101 course (which we'll finish around spring break), you'll have built a web crawler and back-end to a search engine (what is needed to build an index of the web, and to respond to search queries), but won't have done the mechanics of making a web front-end to your search engine so it can run as a web app (accepting queries from a web browser). If you reach the Black Belt level in the course, you will build a web application and know everything you need to put a fully-functional and useful search enging on the web.
Our department doesn't decide on courses until usually the week the course listings are needed by the University (or often, until several weeks after that). So, I have no idea what I'm teaching next semester, but will let you know when I do.
All programming languages are fundamentally the same in many important ways. The set of computations that can be expressed in all of these languages is exactly the same --- indeed, some define a programming language as a language that can express every possible computation. One way to show this is that you could use Python to implement a Matlab simulator, or use Matlab to implement a Python simulator, or use Python to implement R, etc.
At a pragmatic and superficial level though, programming languages
can be quite different, and Matlab and R. Matlab was designed to do
numerical computation well, and R was designed for statistics, wheras
Python was designed as a general-purpose programming language. But,
all of these languages have ways to do conditionals (
if in Python),
while in Python), and to define and call
procedures. They also all have variables, but there are subtle
differences in what they mean.
But, they vary in expressiveness (how much code you would have to write to implement something), "truthiness" (how likely it is programs mean what the programmer intended), performance (how fast the program will run and how much memory and energy it uses), and style (what symbols are used to indicate function calls, whether or not whitespace matters (Python is quite unusual for not just ignoring whitespace), what kinds of names you can use, etc.). The other big difference is what tools and libraries are available to make it easier to build programs in the language.
There is a site, RosettaCode.org, that collects examples of code in different languages so you can compare how the same function would be defined in different programming languages.
Here's one example:
function ninetyNineBottlesOfBeer() disp( [ sprintf(['%d bottles of beer on the wall, %d bottles of beer.\n'... 'Take one down, pass it around...\n'],[(99:-1:2);(99:-1:2)])... sprintf(['1 bottle of beer on the wall, 1 bottle of beer.\nTake'... 'one down, pass it around;\nNo more bottles of beer on the wall.']) ] ); %The end of this song makes me sad. The shelf should always have more %beer...like college. end
cat(paste(99:1,ifelse((99:1)!=1," bottles"," bottle"), " of beer on the wall\n",99:1, ifelse((99:1)!=1," bottles"," bottle")," of beer\n", "Take one down, pass it around\n", 98:0, ifelse((98:0)!=1, " bottles", " bottle"), " of beer on the wall\n\n", sep=""), sep="")
Python: (see this page for many different versions - this is either evidence of Python's popularity and expressiveness, or something more disturbing)
for n in xrange(99, 0, -1): ## The formatting performs a conditional check on the variable. ## If it formats the first open for False, and the second for True print(n, 'bottle%s of beer on the the wall.' % ('s', '')[n == 1]) print(n, 'bottle%s of beer.' % ('s', '')[n == 1]) print('Take one down, pass it around.') print(n - 1, 'bottle%s of beer on the wall.\n' % ('s', '')[n - 1 == 1])
Coding. By this, I mean being able to take a clear and precise description of a mechanical procedure and turn it into a program that executes correctly. Coding is an important skill, and one can't develop as a computer scientist without being able to quickly and reliably turn procedures you understand into programs that can run. Learning coding is like learning to play a musical instrument, or to make basketball free throws. It depends on reading and understanding how experts do it, and lots of practice. The best way to get good at coding is to try to write a program at a level that is just beyond the last program you wrote, and then get advice from an experienced coder at how you could have done things better, and keep repeating this process. As you get better, you should also be playing the role of the "experienced coder", looking at code written by others and advising them on how to make it better. What we can do in class is a very poor substitute for this: you read code from experienced coders in class and in what we provide for the projects, and get some feedback on your own code from the assignments you subject; hopefully, you also get some of the more direct mentoring experience from your classmates and in office hours.
Computer Science. Computer science is understanding how computers work and how to use them to solve problems. It includes programming (the art of turning a possibly not well-defined problem into a precise procedure that solves that problem), as well as reasoning about the costs of executing that procedure and about the best possible procedures to solve some problem. If learning coding is like learning to read music and play a musical instrument, learning computer science is more like learning to be a composer or songwriter. It depends on studying the theoretical foundations and understanding them deeply, as well as by learning from the "great works" of the masters (in computer science, "great works" are often algorithms designed by people like Tony Hoare, Edsger Dijkstra, Leslie Lamport, and Donald Knuth; programming languages designed by people like John Backus, John McCarthy, Barbara Liskov, Ken Thompson, Dennis Ritchie, and Niklaus Wirth). But it also depends on trying to solve problems yourself, and gradually getting better at this by solving increasingly more challenging problems with less and less help (both from other people and resources).
I haven't ever had what most people would consider a "real" job, but have spent some time in big industry research labs and small to medium-size startups. This can be fun for a while, and there are some advantages to such places (lots of high quality free food, more of an opportunity to be part of a team with a shared mission, roller-coaster of hyper-growth, and ability to have a direct impact on customers), but nothing that compares to the paradasicalness of academia.
* The original question used "coding" instead of "programming" (see the earlier question about for what I think the difference is), but I'm taking the liberty of changing this to "programming" (which is probably what the questioner meant, and consistent with common usage).
I firmly believe that no one fails at programming, only that some people give up before they would have succeeded. So, the real question is "why do some people pick up programming quickly and (fairly) easily, whereas others find it frustrating and unpleasant?"
I wish I knew the answer to this, but I don't (and I don't think anyone else has a great answer to it yet, either). My best guess is that there are two things that make a huge difference:
Mental models: learning to program depends on being able to keep a clear model in your head about what is going on in a simulater computer. Some people are able to do this more naturally than others, but I believe it is something everyone can learn.
How you deal with "adversity": people who are inclined to respond to failure (that is, things not doing what they expect or want) with frustration and despair, will tend to become frustrated and desparate. Whereas people who respond to unexpected behavior with curiosity and wonder, will use that curiosity to learn new things. This is a personality trait to some degree, but it is also the result of past experiences. People who have good experiences starting with failures and following their curiosity to learn how to solve problems on their own gain confidence that things do happen for good reasons and with effort it is possible to figure out why; people who start by having negative experiences where failures only lead to more failures and greater confusion tend to lose the ability and desire to explore curiously and thoughtfully, and get mired in frustration and mindless modification instead.
Its not about forgetting or remembering, its about being empowered by what you learn in this course to go on to do things you wouldn't do otherwise.
My hope is you will end up doing things long into the future that build upon what you've learned in this class. Even if you've forgotten almost everything you've learned, hopefully you'll have replaced it with better and more powerful knowledge that you've learned as a result!
If you have a new question, feel free to ask it either by email (feel
free to send anonymous email if you prefer) with subject line
AMA so I notice it or in the Slack group.