Angelgate is missing the point. What about the entrepreneurs? - <AUTHOR>

Now that Silicon Valley is on fire with accusations, and Arrington is getting deserved accolades for blowing the doors wide open in the Angelgate story, there is clearly a missing piece that isn't getting any coverage.
What about the entrepreneurs?
I know of a seed-stage startup that literally just launched and has funding interest from people on both sides of this firestorm. While the world reads the opinions of super angels on every blog that covers tech, where is the coverage on the impact on entrepreneurs who are raising money... say the fresh batch of just-launched YC startups? This needs to end so we can all get back to building companies.
Maybe Hitler knows the answer: http://www.youtube.com/watch?v=ZlZOfHCpFFs <comment><USER2> Mark Suster gave a good summation of the whole deal on his blog a few minutes ago in regards to #Angelgate and price fixing: <http://bothsid.es/7W0>

</comment><comment><USER3> War stories are best told after the hostilities.

</comment><comment><USER4> Here the debate: <http://office.mashape.com/question/debate.html>

</comment><comment><USER5> Couldnt agree with you more.</comment>


The Differences Between Red, Blue, and Purple Teams - <AUTHOR> https://danielmiessler.com/study/red-blue-purple-teams/ <comment><USER2> As I was reading and scrolling I encountered a popup that obscured the content asking for email, and promptly left without finishing.</comment>


Twitter Scam: Elon Musk is not giving you free ETH, one tweet scammed 155 ETH - <AUTHOR> https://medium.com/coinremix/twitter-scam-elon-musk-is-not-giving-you-free-eth-one-tweet-has-collected-155-eth-and-counting-2f52fe35b5a8 <comment><USER2> A single tweet scammed over $120k. That is insane how easy it is to do that with basically no recovery options.</comment>


Computational solution to quantum foundational problems - <AUTHOR> http://arxiv.org/abs/1403.7686 <comment><USER2> Scott Aaronson has commented on the paper; he considers it as garbage:

> > [http://www.scottaaronson.com/blog/?p=1767#comment-103591](http://www.scottaaronson.com/blog/?p=1767#comment-103591)

Also look at the update at the beginning of [http://www.scottaaronson.com/blog/?p=1767](http://www.scottaaronson.com/blog/?p=1767)

<comment><USER3> Does somebody know of good papers about potential links between computation complexity and why we do not observe large scale quantum behaviours ? As a basic computer guy, I have always suspected that the large computer that is running our universe does not have the resources to handle quantum entanglement on a large number of particules, and has to fallback to some classical approximation to be able to run the full simulation in real time ;-)

<comment><USER4> why would it have to run it in 'real time'? what's the difference between this universe being simulated by a very slow computer in the super-verse, vs being simulated by a very fast computer in the super-verse? for us, I'd argue there's no difference at all.

<comment><USER5> Not always a fan of linking xkcd, but:

[http://xkcd.com/505/](http://xkcd.com/505/)

</comment></comment></comment></comment><comment><USER6> If someone's interested in a hard problem: design a density functional that's exact with regards to strong correlation and you have my respect.

<comment><USER7> It's instructive to remember at this point that Feynman used to call the exchange-correlation energy "the stupidity energy" out of frustration. Many Bothans died to give us PBE and B3LYP (at least it seems like it)

<comment><USER6> I actually never read that quote before, thanks. I'm a 1st year M. Sc. student in a theoretical chemistry group. Although most members in the group do DFT, I don't. My knowledge of the literature extends to some Perdew, Yang, HK and KS.

<comment><USER7> What do you do then? H-F? In any case, do not just stick to DFT. I can't emphasize enough how essential a book like Negele and Orland is to make yourself useful in dealing with strongly correlated systems -- running codes on these things is going to fail badly in terms of results deliverables useful to experimentalists or for further theory unless you can do some model building yourself. Way too many of these groups turn out people whose only skill is running ABINIT or VASP or QUANTUM-ESPRESSO or maybe writing some multi-threaded FORTRAN if they're lucky (shudder). Endeavor to make contact with developments in modern condensed matter theory (it doesn't have to be holography or AdS or anything that hardcore, just get used to the idea of a field as something other than what a plow goes into)

<comment><USER6> The project I was assigned requires only Hückel level theory, for the moment. I'm concerned with molecular electronics, specifically trying to use CAPs (complex absorbing potentials) to model conduction through aromatic molecules.

Thanks for the recommendation. The group I'm in is definitely focused on method development. Calculations are mostly done on atoms and diatomic molecules to benchmark the functionals.

<comment><USER7> You may want to have a look at some of Jorge Hirsch's papers on complex aromatics and ring currents. The guy is a bit of crackpot on superconductivity, but what he says on aromatics might be of interest to you.

</comment></comment></comment></comment></comment></comment><comment><USER8> I´ll repeat one of my comments in a previous submittion of the same paper:

There are some experiments where it's easy to see quantum effects in "big" things. There are experiments that show explicitly the wave behavior of helium atoms (they have like 2 electrons and 12 quarks, and a lot of gluons, they are not a single particle) [http://en.wikipedia.org/wiki/Helium_atom_scattering](http://en.wikipedia.org/wiki/Helium_atom_scattering) . I think there are bigger examples, but I should google a little to find them.

Also, the superconductivity and superfluity effects are due to quantum mechanics effects (a lot of properties of solids only can be explained correctly using quantum mechanics, but they are not so evident).

There is more hand waving that a proof here. Obligatory Xkcd: [http://xkcd.com/1240/](http://xkcd.com/1240/)

<comment><USER9> Don't forget the obligatory Wikipedia article: [https://en.wikipedia.org/wiki/Macroscopic_quantum_phenomena](https://en.wikipedia.org/wiki/Macroscopic_quantum_phenomena)</comment></comment>


What are some overshadowed careers that pay well? - <AUTHOR> Careers that might never cross someones mind when reviewing their options. Great salary. Nice benefits. <comment><USER2> It's bound to come up in almost every conversation about this topic online nowadays but skilled trades can be great. Especially if you plan to own your own service business. I'm talking Electricians, Plumbers, HVAC technicians, etc.

Competition is low. If you show up on time, present yourself well, and you don't show up to work under the influence, then you can be in the top 10% of the workforce easily.

I worked in the trades for about 6-7 years before switching to software engineering. I took a paycut for my first job in software. I was making $80k in a low cost of living area working in the trades. First year was $55k, on the job training was provided.

Downsides are: \- Weekend work is typical \- On-call is typical \- Hard labor, working in the elements. Freezing conditions and/or 100*F + days working on HVAC equipment is rough. \- Non-trade folk will commonly talk to you like you're not intelligent. Not a lot of prestige

Upsides: \- Learn valuable hands-on skills. Can be applied to your own home to save money \- Physical job = built-in exercise \- Low competition \- Easy to parlay into a business

<comment><USER3> > _Competition is low. If you show up on time, present yourself well, and you > don 't show up to work under the influence, then you can be in the top 10% > of the workforce easily._

I'm still infatuated with a mason who worked at our house one time. I doubt he ever really existed. Dreamy.

Let me walk you through this romantic 50 Shades of Cement...

He rang the bell and I opened the door. He didn't look like a mason: well dressed, clean shaven with impeccable combed hair and a case for tools. I showed him to his floor. He brought pencils and markers, rulers, a compass, etc. The guy reminded me of my course in industrial/technical drawing.

I lived a floor downstairs of the floor he had to build. He was punctual, consistent, and silent. I didn't hear a thing while he worked and yet I would go up at the end of the day and appreciate the progress he was making. I didn't find broken bricks or sloppy cement/sand/water traces. It was clean and precise, and the guy was a ninja.

I didn't have his contact information but I would have referred anyone and everyone to him, whether they had something to build or not. I must have told this story like a grandpa tells tales of his youth.

<comment><USER2> There are some truly amazing people in the trades.

Some of the absolute best problem solvers I ever met, I met in the trades. I'm talking masters of troubleshooting. Breaking things down into component parts, understanding how systems work together, and being able to pinpoint what exactly was causing the underlying issue. People who just had to know how everything worked. People with knowledge of Refrigeration, electrical troubleshooting, PCB repair, etc.

Working in the trades gave me strong troubleshooting skills.It also gave me an appreciation that a lot of folks in our industry seem to lack for our blue collar brethren. Blue collar != dumb/uneducated.

</comment></comment></comment><comment><USER4> Underwriters/actuaries.

Many underwriting jobs can be remote. Entry level salary is around 50-60k with just a BS. Fair amount of growth and opportunities. Can get an MBA/go into management and make > 100k.

Actuaries require more math/stats but can be hired with a BS. But, I've got a friend who started at 80k with a Stats BS in a low cost of living area.

<comment><USER5> Anyone with the aptitude to pass actuarial exams could be making more elsewhere.

<comment><USER6> That absolutely makes no sense. Actuary's regularly start in the $70,000 - $80,000 range and can definitely move into the $200,000 range of salary without dipping into any management. I guess there are jobs which make more. But I don't know a lot of them.

<comment><USER5> SWE make more than that easily and is a much easier field to learn than passing actuary exams.

</comment></comment></comment></comment><comment><USER7> Lots of the work in remote areas pay extremely well and have low skill requirements. Offshore petroleum engineer is well known as a well paid job.

Less commonly known is menial labor shipping jobs. A friend of the family bought a car in cash after a trip.

Plantation managers can get well above the average pay rate, with substantial benefits like a large home, live-in maid, little work, for diploma level education.

I'd bet something like deep sea fishing also pays quite well.

</comment><comment><USER8> A cousin is a pool guy in SoCal. He builds a book of business, sells off part, rinse and repeat. Last I heard, he was making six figures.

</comment><comment><USER9> Orthodontist

[https://www.ziprecruiter.com/Salaries/What-Is-the-Average- Or...](https://www.ziprecruiter.com/Salaries/What-Is-the-Average-Orthodontist- Salary-by-State)

NY average is $320k, but range is $80k to $435k. Braces ain't cheap!

<comment><USER10> I'm not sure this one is overshadowed, maybe by dentists. But Orthodontists are doctors (DDS or DMD) and those are generally pretty well paying types of careers.

</comment></comment><comment><USER11> Undertaker: people are dying to get in :-) No matter how bad things get, you'll have a job.

</comment><comment><USER12> Technical Recruiting. High pay for entry-level (Internal recruiters in NYC starts at 50k for 0 years exp and goes into low 200s).

No education requirements. HUGE need. On-the-job training.

<comment><USER13> Correct. I'm currently hiring for a senior internal recruiter in NYC and am expecting to pay at least $150k.

The demand is only going to continue to increase so salaries will continue to rise.

<comment><USER14> I've been interested in this route and I'm an engineer by day - I feel like my understanding of the technical side could really set me apart from the recruiters I've talked to in the past. I was under the impression this is a grueling field though based almost 100% on commission?

<comment><USER13> Agency recruitment and internal recruitment are _very_ different fields.

Agency recruitment is massively commission based. Internal recruitment tends to focus on higher base salaries to remove the terrible incentive of cash for humans.

</comment></comment></comment></comment><comment><USER15> Software architect. Pays more than (non-FAANG) developer jobs and quite often is pretty easy if you have the necessary skills.

<comment><USER16> I've found the interviews very difficult because your opinions on software design have to match the interviewers.

Interviewer likes micro services and you don't? No job. Interviewer doesn't see the benefits of cloud computing? No job.

<comment><USER17> Just from what you present in the comment, maybe you're stating your opinions in a way that comes off too black-and-white?

There's times where microservices work and can be a beneficial move, there's people who have been burned by cloud computing costs or lack of customer service in the past.

Maybe you could write down your strongest opinions and find a way to put them in a way that reflects you're open to circumstance or being convinced.

Not 100% microservices negative, but strongly microservices cautious. Not 100% gung ho about cloud computing, but excited about cloud computing as a way to accomplish x y z.

<comment><USER16> You certainly raise a good point. But sadly in those examples they asked me how I would recommend designing a giving system. And then didn't like the answer.

</comment></comment></comment></comment><comment><USER18> Scrum master seems to pay well around these parts.

</comment><comment><USER19> Divers for oil and gas companies. The more dangerous the place the higher the pay, $100k-$500k.

Although, this is hearsay, so... Check before you sign up with some company saying they have a rig of Somalia.

<comment><USER20> how do i sign up for a $500k job?

ill go to Somalia.

I've been to worse places for much less</comment></comment>


Implementing Scheme in F# - <AUTHOR> http://blogs.msdn.com/ashleyf/archive/2010/01/15/fscheme-0-0-0.aspx

<comment><USER2> This is interesting; reminds me of lisp in Haskell <http://www.defmacro.org/ramblings/lisp-in-haskell.html>

Is there any practical use for these kind of projects? I imagine it might make make it easier to write multithreading programs when the lisp is implemented in a purely functional language. At least Haskell seems to have decent multithreading support, I don't know about F#. Are there any other reasons other than curiosity to do this?

<comment><USER3> IMHO embedding in F# or Haskell isn't particularly useful, but embedding in C is pretty neat. You can add scripting support to an application in a day or two. This was gimp's trick. Arguably it is emacs trick too. Nowadays, It's probably better to use something like guile or lua.

<comment><USER4> Beyond that, if you're on .Net it's trivial to add scripting to your application via IronPython or IronRuby (or any other .Net language, I suppose).

</comment></comment></comment><comment><USER5> are all languages implementable in every other language?

<comment><USER6> Not all languages, but many: <http://en.wikipedia.org/wiki/Turing_completeness#Examples>

<comment><USER7> From that wikipedia page: "The untyped lambda calculus is Turing-complete, but many typed lambda calculi, including System F, are not."

Anyone have any details about System F not being turing complete? Is it not straightfoward to implement an untyped lambda calculus in a typed one?</comment></comment></comment>


The Hercules System/370, ESA/390, and z/Architecture Emulator - <AUTHOR> http://www.hercules-390.eu/ <comment><USER2> The learning curve for Hercules can be pretty steep, as it drops you in to a working version of MVS 3.8j. If you are familiar with all that means, you are golden. The rest of us need some guides. Moshix has a great YouTube channel with lots of good videos. I started with his "IBM's MVS 3.8 on Linux for newcomers - M50"[0], and I had a sample ancient COBOL program, with assembly language subprograms, running in under an hour. My main issue was the editor or shell (not sure which) locking up and not able to get out. I can kill the Linux process, but that leaves all the mounted disks in a slightly corrupted state, and doing the equivalent of fsck is beyond my skill level. I just reinstalled the Hercules package again, with a pristine set of disks, but that isn't going to help if I had a real program I was working on. Maybe there is a recovery guide for common hangups that I haven't discovered yet.

[0] [https://www.youtube.com/watch?v=N6sK_BhVD8g](https://www.youtube.com/watch?v=N6sK_BhVD8g)

<comment><USER3> > The learning curve for Hercules can be pretty steep, as it drops you in to a > working version of MVS 3.8j.

Hercules does not come with MVS 3.8j, that just happens to be the version of MVS that is available publicly. You can also run several other mainframe operating systems on it.

> My main issue was the editor or shell (not sure which) locking up and not > able to get out.

More likely, the terminal locked up. If you try to type where there is no field to type into, you'll lock the keyboard. To reset it, press Escape, then tab to the field you want to type in.

</comment></comment><comment><USER4> Hercules is really cool! There's even a old version of the zOS ADCD on pastebin you can download and get IPL'd in Hercules. But if you want to just muck around with a current zOS environment check out master the mainframe and grab a learning ID. Then get playing around!

[https://www.ibm.com/it-infrastructure/z/education/master- the...](https://www.ibm.com/it-infrastructure/z/education/master-the- mainframe)

<comment><USER5> Has the MTM/learning system been submitted to HN before, do you know? I'm getting kinda tired of copy-pasting the same links over and over :)

<comment><USER6> Once without traction: [https://news.ycombinator.com/item?id=22783438](https://news.ycombinator.com/item?id=22783438). Submit it again.

<comment><USER5> Thank you. I can't believe I only just noticed the 'search' box at the bottom of the page...

</comment></comment></comment></comment><comment><USER7> FYI Unisys also makes available free emulators of their two mainframe environments. The ex-Burroughs MCP IMHO is a lot more interesting than the yucky IBM stuff.

<comment><USER8> Do you happen to have a link to it?

I've been playing with MVS 3.8j on Hercules on and off for the last year and found it rather interesting. I'd love to play around with the Unisys stuff as well, since I've never used it before.

<comment><USER5> I went looking for it myself a while back:

[https://www.unisys.com/offerings/clearpath- forward/clearpath...](https://www.unisys.com/offerings/clearpath- forward/clearpath-forward-products/clearpath-mcp-software/clearpath-mcp- express)

Unfortunately, I haven't got access to a Windows machine at the moment.

</comment></comment></comment><comment><USER9> There is a guy on Youtube, moshix, that does a number of videos on IBM mainframes and does quite a bit with Hercules and various OS distributions that run on it. He helped my remember some stuff from my early career. I was able to get some of my old FORTRAN code running on a MVS 3.8 setup.

I also setup a vm370 system with a few different things running on an older Raspberry PI. It was fun to think I could run the old application I maintained on a system that is about the size of the pack of cigarettes my old boss use to keep on his desk.

</comment><comment><USER10> If you feel like a quick visit to your own mainframe, you can use this:

        docker run -it -p 3270:3270 rbanffy/vm370

<comment><USER11> That's cute that it runs on port 3270.

<comment><USER5> I thought everybody did it that way!

<comment><USER10> We could standardize on port 3277 for 12-line, 40-column uppercase displays, 3278 for monochrome with a beautiful and warm shade of green and 3279 for color ;-)

<comment><USER5> Thanks for your 3270 font by the way. It's my daily driver for terminal sessions.

<comment><USER10> Thank you for the encouragement. :-)

</comment></comment></comment></comment></comment></comment><comment><USER12> I put MVS 3.8J (emulated under Hercules) inside a Docker container – [https://github.com/skissane/mvs38j](https://github.com/skissane/mvs38j)

The idea of running a 1970s vintage operating system inside a Docker container amuses me. Old meets new. (For extra "old meets new", I should make it run under k8s.)

</comment><comment><USER5> Most active development is happening on the SDL fork I believe:

[https://github.com/SDL-Hercules-390/hyperion](https://github.com/SDL- Hercules-390/hyperion)

</comment><comment><USER13> It is easy to up (I were an Ibm system programmer for dos/vse and doing xa migrate your esa). But writing a cobol program is hard as far as I find. Hope it is better these days.

</comment><comment> non-entity I have some old mainframe modems and online information on them are scarce (basically nothing outside of old ads). I'd like to figure out how it worked, but no idea how to get started. Are the drivers something that the OS would support built-in, or would you have to install them somehow. Would this emulator help me at all?

<comment><USER14> Do you have a model number?

It's most likely a synchronous modem meant for 4 wire leased lines, which don't really exist anymore.

<comment> non-entity Yep, the model is 3865-2. Would it be possible to create a "fake" four wire leased line? I've looked into creating fake dial up lines for DSL modems and that seems to be possible.

<comment><USER14> Should be. The 4 wire connection is the round one on the back. You would need to crossover the tx and rx pairs between the modems.

The other port is standard rs232.

<comment> non-entity Cool, as far as protocol / communication standards go am I looking at one of the V. _x_ standards?

</comment></comment></comment></comment></comment><comment><USER15> I've always associated the "Hercules" name with the mono-monitor from the past :)

<comment><USER16> I had what I think may have been a CGA and EGA emulator, so even though I was in monochrome, we could still run high resolution graphics with a little grayscale. Very nice. I wonder if DOSBox can do that...

</comment></comment><comment><USER17> Jay Maynard (tron guy) is a really talented guy![https://www.youtube.com/watch?v=t9dutFhebw4](https://www.youtube.com/watch?v=t9dutFhebw4)

<comment><USER18> That was very painful to watch. I feel like he never even started.

People have such short attention spans and the judges kept making him start over repeatedly... and when they started booing I genuinely felt for the guy.. Props to the guy for keeping clear, that would have destroyed my spirit.

</comment></comment><comment><USER19> Any chance to get MTS running?

I remember exploring MTS back in the day, UBC was running it on some kind of machine in the mid-1970s.

<comment><USER7> [http://archive.michigan-terminal- system.org/mts-d60A](http://archive.michigan-terminal-system.org/mts-d60A)</comment></comment>


42 (Answer) - <AUTHOR> https://simple.wikipedia.org/wiki/42_(answer) <comment><USER2> It's also the atomic weight of Molybdenum or the first page of my old web site. [http://www.chrisbennet.com/](http://www.chrisbennet.com/)</comment>


Adventures of an imperative programmer in the land of fp - <AUTHOR> http://jacquesmattheij.com/Adventures+of+an+imperative+programmer+in+the+land+of+fp <comment><USER2> I've recently jumped into Erlang, and have come to some of the same conclusions. I read Armstrong's Erlang book, and thought 'that seems cool' and didn't at all grok what was going on beyond the superficial. Then a few months later, just sat down and started solving Project Euler problems. At first it was strange and foreign and I was mad variables were immutable. A day later and it just clicked, I'd never had that much fun writing code.

The FP paradigm is (to me, even after 15 years of imperative programming) so much more natural for development, since you're able to sanely start attacking the problem directly -- instead of architecting a big-picture solution up front that's probably wrong anyway because you've ignored some detail you haven't yet discovered.

Building things with actions instead of objects just makes much more sense. Reuse comes much more naturally, and doesn't seem as contrived as a lot of OOP reuse seems. I've noticed that working my FP muscles out has made me a much better imperative programmer -- I write a lot more clever and effective code (not clever like 'tee-hee-no-one-will-ever-figure-this-out'!).

<comment><USER3> One thing that raises my eyebrows is how much functional programmers talk about Project Euler problems. The actual programming for solving these problems is in fact extremely trivial. They require some mathematical insight, especially after the first one hundred or so, and you need to do some external research on Pell's Equation to avoid getting stuck, and you need a fraction library if your language doesn't have it built in. But am I wrong in thinking that these kind of problems are almost no test or strain for your actual _programming_ at all?

<comment><USER2> They're an absolutely fantastic way to start 'getting' any language. They're small, discrete, and varied tasks that require you to build different types of operations and structures. Sure, they're not at all reflective of 'real programming' nor are they necessarily particularly challenging, programming wise.

I'd rather cut my teeth in a new language on the first 50 or so PE problems, than take on a bigger, less defined, or more domain limited task.

I'm conversant in Python and Erlang because of PE problems entirely. They've enabled me to start actual projects in both languages.

<comment><USER3> > varied tasks

That's where I'd argue. It would be like saying you're an all around gamer when you play only chess but with different openings every time.

Varied simple tasks would be doing some Euler problems, doing some basic algorithms (Dijkstra's with Heap, A* pathfinder on a 2d map, etc... TopCoder problems are great for this), write a Mandelbrot zoomer, Conway's Life app with position setup and step-through and save/load, write a Tetris clone, write a basic HTML form builder, write a blogging engine, write a multi-user chat room server, write a simple side-scrolling shooter game, write a basic Roguelike game, write a simple text adventure. Things like this can all be afternoon projects.

Every time I read someone claiming that Project Euler is for developing general-purpose programming, I roll my eyes more than a little.

<comment><USER4> Any similar sites you'd suggest, besides Project Euler and TopCoder? I've worked through much of PythonChallenge, but I'm more interested in sites that aren't as closely tied to a specific language.

<comment><USER3> Do you know about Sphere Online Judge? (<http://www.spoj.pl/>) It supports a lot of languages. It still contains mostly algorithmic problems though, making it a superset of the kinds of problems at Project Euler but still a tiny subset of general programming.

<comment><USER4> That's what I had in mind, thanks.

</comment></comment></comment></comment></comment></comment></comment><comment><USER5> If you really start studying FP literature you'll discover that an enormous amount of ideas that are in vogue in today's languages have been invented years ago by functional programmers. For example, this paper from 1965(!) describes DSLs: <http://www.cs.cmu.edu/~crary/819-f09/Landin66.pdf>

I think learning a language like Haskell can be extremely good for you as a programmer. The problem is that you just can't expect to be productive, if you're new to it, and that might be very frustrating if you're doing to do work. However, just as jacquesm writes, if you're doing it for fun you'll learn a lot (that you can sometimes apply directly to your normal programming).

</comment><comment><USER6> There are about a thousand FP programmers to every imperative programmer, if not ten thousands. They use a tool you may have heard of, called "Excel", which is quite limited in scope.

It is an FP subset which is at the same time trivial to understand (much more so than imperative programming for most users!), and coupled with a usable I/O capabilities, is surprisingly sufficient for many uses.

(IDE, documentation, maintainability all suck, though; I wouldn't recommend it as your main FP tool if you can avoid it)

<comment><USER7> And many Java programmers doing FP programming unknowingly when writing an Ant script.

<comment><USER4> No - ant is _logic programming_ , not functional programming. Same with make.

</comment></comment></comment><comment><USER8> it's funny, in French engineering schools we have the opposite reaction; in "prep" schools students are taught OCaml which is their first programming language if they're not geeks.

Functions returning functions seem a natural thing as they are used to the exact same kind of abstraction in math (and even sometimes order 3+ functions when you study duality!). Conversely, they are initially puzzled when they are taught Java in their engineering school because of the difference between static variables and attributes, constructors and other unnatural concepts.

<comment><USER9> `Unnatural' in the sense of `not relating to natural transformations'?

<comment><USER10> Unlikely since natural transformations are a statement on how a particular collection of functions behave under composition.

</comment></comment></comment><comment><USER7> It's great that more people are exposed to the functional programming style. Kudos to OP for trying something new.

It bugs me whenever FP people talk about state being bad as if it should be avoided at all cost. State is bad if its scope is not carefully managed. Global state is generally bad because its scope allows the whole program to modify it, making it difficult to follow its validity. Local state maintained as a local variable in a function is perfectly fine. Its scope is small and its changes can be tracked easily. Pure functional code actually also implicitly maintain state in their parameters and return values, and the passing of the return values as parameters to next function.

<comment><USER4> It's ultimately about making code easier to reason about. Immutability (at least as a default) makes the dataflow between independent portions of your program clearer, since every value is determined by where it came from, not where it came from _and_ everything that could have potentially touched it along the way.

<comment><USER4> Oh: Easier for the compiler to reason about, too. Not just the programmers.

</comment></comment></comment><comment><USER11> One thing you haven't mentioned but it is related to anonymous functions (or lambdas) and is an important part of the fp style is _passing around functions as first class objects_. It is quite unusual in imperative programming and it is normally only used there to provide callbacks.

Let's say, you want to write a function that exports your video library to an arbitrary medium. In FP, one way to do this is to create generator functions that create DVDs, Blu-Ray discs, etc. Then your export function would take the input and a generator function, and export the library using that function. In Common Lisp:

      (defun make-dvd () ... )
      (defun make-blu-ray () ... )
      (defun export-library (data make-medium) ... )

And then you would

      (export-library *my-data* #'make-dvd)
      (export-library *my-data* #'make-blu-ray)

Or if you want to use an inline lambda (anonymous) function:

      (export-library *my-data* (lambda () ...))

<comment><AUTHOR> I'm going to do a completely separate post on the subject of first class functions because I think it is too complicated a subject (and with too many implications) to be squeezed in there as an aside, besides that I don't think I'm qualified just yet to write the article in a strong enough way yet. More understanding is required first.

It must be funny to all the FP gurus here to see someone struggling to understand the things that are second nature to them, but I find that it is surprisingly hard to teach this old dog a new trick. One part of me wants to say 'enough of this' all the time and reach for a C compiler just to get the job done :)

<comment><USER12> The real trouble here is probably closures.

        function foo(x) { return function(y) { return x+y; }; }

        bar = foo(3)
        bar(5)
        // Returns 8, wait how did the x in the inner function remember the 3?!
        // It's supposed to be gone already because the call to foo is over...

One way to understand this is to notice that it always "just works". It seems like magic. The 'aha' for me was when I learned how closures are implemented.

<comment><USER4> But you'd probably only get hung up on that being "magic" if your mental model of programming assumed stack-based scope for everything.

Besides, how about this pseudocode?

        class Foo {
            field x;
            constructor(x) { this.x = x; }
            fun add(y) { return x + y; }
        }

        bar = Foo(3);
        bar.add(5)  // returns 8, wait how did the x in the object remember the 3?

<comment><AUTHOR> Stack based 'mental' scope is one of the bigger things to 'unlearn'.

When I look at a function I build up a mental image of what is going on on the stack as the function executes. Things that I don't see declared within the function or that are explicitly allocated update the heap. To get away from that image is very hard to do at first.

I compare it to learning real life languages, like English versus German. If you've never seen a language that has declinations in the endings of words then it can completely overwhelm you. Likewise tonal languages are strange when you've only spoken English _or_ German.

Each of those opens up the perspective you had before you learned that language to show you that there is more under the sun than what you thought was 'normal', and that your way is not always the better one.

In programming languages it is much the same way.

<comment><USER4> Indeed. For some reason, closures never tripped me up, but continuations took a while to wrap my head around. (I think because I tried to learn continuation-passing-style _first_. While also learning OCaml.)

Since you know C, it might help to think of continuations in terms of setjmp/longjmp, but with multiple, persistent stacks. (Same with coroutines, but coroutines and continuations have a lot of overlap.)

<comment><AUTHOR> > in terms of setjmp/longjmp, but with multiple, persistent stacks.

That's exactly the thing I used to help me visualize it :) Funny you came up with the exact same model.

Setjmp and longjmp are by the way probably two of the most abused calls in the C runtime package. But when you need them, you need them badly.

</comment></comment></comment></comment></comment></comment></comment><comment><USER13> Towards the end of his entry he mentioned something about readability. I believe postfix notation is superior in both read & write-ability for FP.

Take: (reduce (lambda (x y) ...) (map (lambda (x) ...) data-set))

When you actually read this what do you do? You work inside-out to understand it. You figure out what 'data-set' is, then you figure out what '(lambda (x) ...) does to it, and so on.

You (or me at least) also write the code inside-out. You start with the data, and an idea of how to transform it, and you work your way towards that transformation.

Compare to:

((data-set (lambda (x)...) map) (lambda (x y) ...) reduce)

Of course, this brings up a lot of edge-cases. Ex.: Where does 'define' fit into this? You really want define and the variable name at the beginning.

<comment><USER12> This, in my opinion, is one of the greatest strengths that OOP has over FP: data.map(...).reduce(...). It doesn't really have anything to do with OOP, you could just as well have such a syntax for calling functions. In F# you do have the |> operator that does something like this.

This may seem superficial, but it helps readability a lot. The human mind (or mine at least) is just not well suited to unraveling nested structures.

<comment><USER14> Whoa! The UNIX shell's pipelines!

<comment><USER15> The odd thing is that the semantics of the Unix pipeline model is more similar to lazy sequences in Haskell or Clojure.

It is common to have one function generating a lazy sequence, another taking the output of that function and generating another lazy sequence, and so on until you get your final results out at the other end. The nice thing is that at no point in time is it necessary to have the entire sequence in memory.

A Unix pipeline is similar, in that one process consumes the output of another process as it becomes available, as opposed to having to wait for the first process to complete its task before the next process in the pipeline can start.

</comment></comment></comment></comment><comment><USER16> Stuart Halloway has a great explanation of anonymous functions in "Programming Clojure." He identifies the specific conditions where you might choose to use an anonymous function given that, for readability reasons, naming functions is usually a good idea.

</comment><comment><USER17> I tried wrapping my head around Clojure but I just couldn't. I'm currently diving into Scala and finding it much easier to get into coming from an OOP background (I'm a Java developer by day and a Rails/Objective-C developer by night).

</comment><comment><USER9> Interesting read.

From the article: "You have to train yourself to start the understanding of code you're looking at from the innermost expressions, which are the first to be evaluated."

The author is in for some even more mind bending, when he eventually has a look at lazy languages.

<comment><AUTHOR> Lazy evaluation: evaluate an expression only when you are actually going to do something with the result. For instance, in a generator you can generate 'infinitely long lists' because only those values that are consumed are actually generated.

Is that what you mean ?

Or do you mean when that principle is expanded to the whole language ?

<comment><USER9> To the whole language. Then you can't tell what's evaluated when, easily.

</comment></comment></comment><comment><USER18> Welcome to the party, Jacques! I think you and I started about the same time.

FP seems much richer than IP, but maybe that's just me. I know that once you get all the basic set operations, then you move on to continuations and Monads and it's like wow! A whole _other_ world opens up. Then you can move on to all sorts of other cool stuff like super-scaling which kind of just "falls out" of FP. So it seems like there is more depth here for geekiness.

As far as bugs, I guess that the vast majority of bugs are related to either "state leakage" -- somebody tickling your variables while you're not looking -- or off-by-one errors. FP eliminates both of those. I know I try to stay as immutable as possible and my code feels a lot more solid than it used to.</comment>


Ask HN: Why choose a dynamically typed language? - <AUTHOR> A few years back, mainstream statically typed languages were more verbose than Python or Ruby. But today, I find that I can make F# or even C# code (insert other lang here) as concise as any dynamically typed language.
And on the plus side, you get all the benefits of compiler type checking, better IDE support, and great refactoring support.
What are your reasons for choosing a dynamic language? <comment><USER3> For exploratory programming, I like the ability to trial-run code that is clearly incomplete or even wrong--- maybe I'm trying out a change in one part to see if it works there first and haven't updated the rest of the code, or I haven't even written a bunch of the cases yet. At least with my approach to exploratory programming, it's common for me to have large parts of the code at any given time that are broken as I try out things. If the things I try out work, I go back and fix the rest.

In statically typed languages, at least the ones I've used, doing that requires a lot of overhead before the language will even let you run the damn thing. Yes I know lots of stuff is broken, but let me try out this one code path that I'm pretty sure works! Or if it doesn't work, fail at runtime so I know where it breaks! Instead, it won't compile at all, unless I go through an exercise of moving broken code out of the way (lots of block-commenting), supplying stub functions to take its place and the place of unimplemented stuff, keeping both an old and a new version of a function around so I don't break code that's looking for the interface with the old version (even though I'm not testing that code right now anyway), etc.

In Lisp, I don't have any of that commenting/stubbing/shutting-up-the-compiler hassle. If I want to try out one particular code path amidst an in-transition code base, Lisp will happily execute that code path. To me at least, it feels a lot easier to try out new ideas that way, because it doesn't feel like the code base is this ball and chain I'm dragging with me every time I try to make a change; I can choose to temporarily leave it behind for a bit.

<comment><USER4> While that's definitely a practical benefit, it's not limited to dynamically typed languages. It's completely possible for IDEs and/or JIT frameworks to offer this same functionality.

<comment><USER5> no not really, its not just about starting out fast - more importantly its that you aren't dependent on other types and don't have to hook into the existing code base to pull of something.

</comment></comment></comment><comment><USER6> Your claim that F# or even C# are as concise as a dynamically typed language is the crux of your argument, and is the weakest part of your post.

I haven't worked with F#, but I have read a share of C# code. A non-trivial program is likely to need some methods to respond to many types; in this circumstance C# lets you write many methods, use generics, or (now I believe) use dynamically typed variables. Writing many methods is hard to maintain, and not at all concise. Using generics is theoretically great, but the syntax in C++/C# is just awkward and writing type-agnostic code with generics is nigh unreadable.

In Ruby or Python you have duck-typing, and you can easily be type-agnostic and concise; in fact if you are writing code in one of these languages, you /should/ be both of these things.

Duck typing is fantastic for true object orientation: "If it walks like and duck and it quacks like a duck, we can safely treat it like a duck." This reliance upon support for response to messages instead of reliance upon types is often the key to being concise and readable.

In ruby, for example, I can use object.responds_to?(:method_name) and be assured that the object will support this piece of the interface before I attempt use. This is an elegant solution to keeping code type-agnostic, and it emphasizes the best sort of object oriented methodology.

This is why I love Ruby.

<comment><USER7> But statically typed languages have duck typing too. Except it's called type inference. And F# has it.

<comment><USER6> This is patently false.

Duck typing: <http://en.wikipedia.org/wiki/Duck_typing> Type inference: <http://en.wikipedia.org/wiki/Type_inference>

Type inference relies upon known, preset interfaces and inheritance from other types. Duck typing relies solely upon the methods being used.

In duck typing, this means that the user finds out at the time of use whether or not a method is supported by an object. Here, the "interface" to a type is not set in stone. It is inherently dynamic and as long as the message you pass is supported, (duck->quack), there isn't a problem.

The mental jump which many people fail to make is to understand that Object Orientation is about message passing, not types. The key questions are, "what message are you sending", and "does the receiver have a response" - it got dogmatized somewhere in small-memory static-land long ago that the best or perhaps only way to tell if an object will respond is through static definitions of complete interfaces, which came to be very strongly associated with our conception of a "type". Once the compiler has used it to check interface constraints are unbroken, this information becomes useless and unchangeable.

Ruby is an example of a language that does not use that means of answering the questions. Instead, an object has dynamic metadata about what messages it supports (specifically a hash of the method names), and uses that (malleable) data to generate an answer. It is fundamentally different than type inference in a statically typed language.

<comment><USER8> Duck typing is a problem when it's done by message _name_ and those names aren't distinguished by namespaces. We're already starting to hear horror stories of Ruby libraries that want the same name to mean different things, especially with monkey-patching.

<comment><USER9> Monkey patching has nothing to do with duck typing. Monkey patching is both incredibly powerful and exceedingly dangerous at the same time but, there is nothing about monkey patching that says you need duck typing. You do static typing AND have open classes. To pretend that problems related to open classes is somehow connected to duck typing is simply false.

<comment><USER10> I wouldn't say that it has _nothing_ to do with monkey patching. Monkey patching is the ability to update classes members dynamically. Duck typing is the ability to update an object's members dynamically. Since the overall point is to dynamically create a new member of some object, I think the previous poster can be forgiven.

<comment><USER9> Duck typing isn't the ability to update an object's members dynamically. There is nothing inherent in the meaning of duck typing that says anything about updating. All it says if i ask:

walk and talk of it and can walk and talk then as far as i'm concerned, its a duck because that is what a duck was expected to do.

duck typing is polymorphism w/o inheritance.

<comment><USER10> > walk and talk of it and can walk and talk then as far as i'm concerned, its > a duck because that is what a duck was expected to do.

This doesn't even parse.

Duck-typing is the idea that an object's type at a particular time is made up of the set of fields and methods it has _at that time_. I suppose that doesn't strictly require updating, but it would be a pretty lame duck with it.

Polymorphism w/o inheritance is a fine description. How do you think that can be accomplished without dynamic updating?

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER11> The reason most people choose dynamic languages is because the most popular static languages have fairly weak and unhelpful static type systems. The benefit of confirming that a variable is an int isn't worth the effort needed to support that analysis in most static languages, and where it is we can shove the trouble into unit tests.

C# is a little better than the big 3 (C, C++ and Java), but you still trade off between helpfulness and verbosity. F# is a lot better IMO, but it's still fairly obscure, so of course not many people are going to be using it.

<comment><USER12> Whether it's worth the effort is debatable. When you (not you specifically, in general) design a database, do you use types, do you mark a field as int or let everything be a string? Yes, when you code you can make sure to only put "integers" (as string) in that field and everything will work. Maybe it's not the perfect analogy, but I think it touches an important point. From a statically-typed point of view it "feels" dirty. When I look at a method declaration, I want to know that it only works with integers, the same way I look at a field in the database I want to be sure to expect only integers, and nothing else.

<comment><USER13> > When I look at a method declaration, I want to know that it only works with > integers, the same way I look at a field in the database I want to be sure > to expect only integers, and nothing else.

That's fine, but it doesn't help me with the errors that I make.

I don't make representation errors. I make kind errors. The difference is that the number of apples and the number of bananas are both non-negative integers, but a check for non-negative integers doesn't keep me from adding apples to my bananas inventory. Remember that I do want to add both apples and bananas to my fruit inventory.

Yes, I care about representation, but things shouldn't go south if I happen to have half an apple.

<comment><USER14> In some statically typed languages, it is possible to have an "Apples" and a "Bananas" type. And it's good to hear that you don't make "representation errors", because I do make these errors - which then blow up precisely after 3 hours of running the Python program.

</comment></comment></comment></comment><comment><USER15> If you're a new programmer, remember that most programmers aren't trying to figure this out. They're already substantially invested in the language they chose years ago, with a large base of knowledge and already written code.

Static vs. dynamic typing is nearly orthogonal to my programming language choice. Much more important to me are functional features. And all other things being equal, I'd rather have the flexibility of the dynamic languages than the performance and compiler-checking of static ones.

Haskell has some killer features that make me want to use it more. Static types are not on the list.

Maybe it's because all of my projects are small and I don't have to program defensively, but I've never been bitten by a type error that took anywhere near as long to fix than I would have spent using a static type system.

I'm sure in some circumstances there are dynamic language projects that are plagued by type errors, but in my case static typing is a solution looking for a problem.

<comment><USER16> > _Maybe it's because all of my projects are small and I don't have to program > defensively, but I've never been bitten by a type error that took anywhere > near as long to fix than I would have spent using a static type system._

One of my projects for school turned into a 9k LOC Ruby project. I had precisely _zero_ errors during the entire development cycle that static typing would've detected. Meanwhile, attempting a bit of dynamic code in VB.Net recently resulted in easily a couple hours worth of total waste dodging types while not going totally type-less. And then there's the crappy lambdas and total lack of anonymous or inner functions, so you end up polluting your namespace _massively_ in many cases. (stuck in 3.5 + VS 2008, 2010 adds those) Gah!

I do occasionally miss IDE hinting, which is drop-dead easy in statically- typed languages. But dynamically typed languages allow such ridiculously simple APIs I find it's rarely necessary.

<comment><USER17> Not to argue. 9K is comparatively small.

<comment><USER16> As compared to a lot of commercial products, absolutely. But it was still a significantly larger project than I'd attempted before, and I probably ended up writing a good 30k or 40k through the whole time (attempting lots of new things).

It's also still over 10x larger than the .Net project with which I've been fighting. And given my patterns of code, I see no reason why making my previous project 10x larger would have _any_ more difficulties with typing than I had before. In a few years of Ruby coding, I can only recall a few immediately-identified type problems. Static typing seems to me to cost _significantly_ more than its value.

</comment></comment></comment></comment><comment><USER18> Dynamic languages win in the worse-is-better department. They're easy to implement and easy to learn. You can get a beginner up to speed in a language like Ruby or Python very quickly. This creates a grassroots effect that builds libraries and community around the language because many of those beginners gradually become experts. Dynamic languages are also generally more expressive.

There are definitely some downsides too though, and static languages have gotten a lot better in the last ten years. After many years of working almost exclusively in dynamic langs I'm enjoying having the help of the compiler again in the Scala hacking I've been doing.

<comment><USER4> Hopefully more concise statically-typed languages will have the benefits of being easy to learn and build up their own grassroots communities.

<comment><USER18> Maybe so but the kind of type system that it takes to make a static language as expressive as a dynamic language has some inherent complexity you're not going to be able to eliminate. Static languages can be a bit of a harder sell too because the benefits of static typing aren't as apparent on smaller codebases.

<comment><USER4> While the type system might be more complicated, programs are simpler. Dynamic languages often need runtime checks dealing with types, and /that/ complexity is there in either case. Static languages just make a pretty interface for it.

</comment></comment></comment></comment><comment><USER19> Short Answer: Python idioms are intuitive to me, whereas many statically typed idioms are not -- so it is easier for me to learn new concepts using Python.

Long Answer: For me, part of it is syntax. I have found that using Python has enabled me to learn some programming concepts that I struggled with in .Net. .Net supported them just fine, but somehow the Python approach was intuitive for me, so once I learned it, I could abstract it to a different language. Polymorphism being the primary example with Python.

More recently, I've gravitated toward languages that provide support with both dynamic types and static types (and arguably C# has heavily moved in that direction, but still I find the syntax not intuitive). The hybrid is nice, as you can worry about the higher level algorithm more easily with the dynamic feature, and then shift over to static to take advantage of the features you cite for static.

Earlier this year, I discovered the Cobra language (<http://www.cobra- language.com>), which boasts a python-like syntax on top of .Net (and supports both dynamic/static typing), and is optionally more strict than standard static typed languages in that it adds the benefits of contracts, nil- checking, and embedded unit tests.

</comment><comment><USER9> I'm going to speak in generalities here... If you do a lot of work with polymorphism then dynamic languages tend to be a much better fit. With polymorphic designs, you dont care what the type of your instance is, you don't care about its entire interface, you just care, does it respond to this message ( or set of messages ).

I have used and continue to use both dynamically and statically typed languages and I find value in both. I do find little value in static type system that can't do type inference.

As to a couple of your generalities, a tour through smalltalk would do you well if you think that excellent IDE support and great refactoring are something that springs from static typing.

EDIT:

People talk a good deal about the + of compile time type checking. I have done tons of coding in statically typed languages like C, C++ and more and I think the compile has caught less than a dozen type errors for me ever and those were usually because I got lost in pointer hell. Most errors that a compiler would catch because of type has been in my experience something that there should be a unit test for and the unit test would have caught.

<comment><USER4> C and C++'s type systems aren't nearly as useful as they could be. Haskell's type system, for instance, makes nullable types non-default, and forces you to catch any nulls while still being easy to read- the Maybe monad.

This kind of thing - a complete absence of NullPointerExceptions and segfaults - is what's great about static type checking.

<comment><USER9> I agree that haskell's type system is far more useful than c/c++. No argument there. I don't find the type system from C# or Java to be anywhere near as useful as haskell's.

That is part of the problem with the question... there are many different type systems out there that people would call 'static'.

</comment></comment></comment><comment><USER20> I do both C# and Ruby on a regular basis, and well even with all the sugar, for most of the job, C# is nowhere as concise as Ruby.

I started using C# in 2001 and Ruby in 2004, and even after several years, I find I'm a _lot_ more productive using Ruby.

This is my main reason - I can tackle projects with 2x or 3x less people on the team (which means I can also tackle alone projects vs. building a team of 2 or 3).

As well, I find dynamic languages more "fluid" to use.

</comment><comment><USER21> As of _right now_ , Python, Perl, Ruby and Tcl have larger and more relevant to everyday work libraries, documentation, sample code, etc, than Haskell, Ocaml et al.

This is changing. We'll see Haskell and Ocaml in the early 2010s, where Python and Ruby where in the early 00s. Still a little off the beaten track (as per the Python Paradox) but definitely usable. And if you're deploying compiled code, you don't even need any runtime on your target...

<comment><USER9> So your answer to why you choose dynamic languages has nothing to do with the type system? IE, the question isn't revalent to you?

Question, what does compiled code have to do with dynamic vs static typing? You can compile dynamic code, you can interpret static code. The typing system or lack thereof, has nothing to do with compilation.

<comment><USER21> No I _love_ type inference.

I remember those days when Python was yet to be accepted as a mainstream language. I wanted to use it, but I was writing software for our clients, who would deploy my code on 10,000 Unix boxes. This is back when an estate like that was a huge and unwieldy thing to manage. There was simply no way that our customers were going to roll out and commit to maintaining a whole new runtime across their estate just for me (where "me" is "my project"). So our realistic choices were Perl or compiled code. Nowadays Python has become a "normal" language and no-one bats an eyelid when I list it as a prereq. Took, all told, maybe 7-8 years from when I first thought "Python can give me a serious productivity boost relative to C" to that point.

I have used Ocaml "for real" and I am still getting up to speed on Haskell (I love it!), but this time, I can skip all the struggle for acceptance. I can just ship 'em a binary. Is the type system going to give me as big a boost in real productivity (incl. debugging and support overheads) as Python did over C? Well we shall see...

<comment><USER9> I still dont see how much of this has anything to do with dynamic vs. static. You seem to primarily be addressing off topic points which have nothing to do with why do you choose dynamic over static.

<comment><USER21> Your question was:

 _What are your reasons for choosing a dynamic language?_

And my answer was, to get a productivity boost over C. At the time, there was no strongly-typed language that it was feasible to use that offered as much leverage. Now there is, and one of the reasons for that is the new crop of functional type-inferred languages that "play nicely" with existing estates by deploying as compiled code (native, or .NET, or JVM).

Very few people have the luxury of coding in a vacuum. Language choice is very rarely a purely technical one.

<comment><USER9> It wasn't my question. My question could be boiled down to... so as you spent most of your time talking about things that have nothing to do with dynamic vs. static, i take it that they aren't really relevant to you. You said no. But you answer still seems to have little do with static vs dynamic but about more concrete comparisons that seem to be, at best, orthogonal to the question at hand.

<comment><USER21> Ermm, it was, it's right there on the page! I answered in great depth, explaining that "dynamic vs static" (again your words) is in fact a question with many variables.

Perhaps you meant to ask about "weakly vs strongly" typed?

</comment></comment></comment></comment></comment></comment></comment><comment><USER4> I only use dynamic languages for reasons other than their dynamism. Lua is good because it's extremely small and easy to embed, ActionScript because it's the language of the Flash platform, etc.

Static typing can be just as concise as dynamic typing, and sometimes more. For example, Haskell's Maybe monad combined with do-notation lets you write code that has null checks where required without uglifying the code.

The benefits of static type checking haven't really been fully realized in popular languages. Type inference is almost mainstream, but you can go a lot farther with non-nullable types, structural typing, dependent typing, etc.

</comment><comment><USER22> I think dynamically typed languages represent a kind of history of thought about programming, while statically typed languages have developed largely along their own path. Dynamically typed languages declared victory over "types" decades ago. That hardly signaled the end of language development, it was just one of many decisions made by a group of practitioners. Purely along the axis of dynamic-or-not you can make a bunch of arguments, speculate that a statically typed language can meet any particular feature or benefit a dynamic language has, etc.; but those statically typed languages have had an opportunity cost, and the opportunity they missed wasn't one of types but of all the other aspects of software development -- because in any community of practitioners people will hit a wall, it's just _what_ wall, and how they get past it. I personally think people using dynamically typed languages have spent their time banging their head against more interesting walls.

<comment><USER18> _I personally think people using dynamically typed languages have spent their time banging their head against more interesting walls._

I'd agree but I think that's because designing a static typing system rigid enough to be useful but flexible enough to be expressive is a _lot_ harder than building a dynamic language. That doesn't mean though that there's nothing to be gained from that hard work. It took a long time to design operating systems that allowed truly robust, compartmentalized multitasking too, but they clearly turned out to be superior for most things in the end.

My instinct is that we're going to see a return of static typing at the cutting edge of production coding but I'm not sure if this current crop of options is going to effect this. Scala seems to me to be the only one with a shot at the mainstream for this round.

</comment></comment><comment><USER23> I used to use Python for its flexibility during experimentation, interactive prompt (REPL), and conciseness.

Nowadays I use Haskell for the same reasons, and Haskell is as statically typed as they come.

The one single thing that really made dynamic typing obsolete for me was _type inference_.

</comment><comment><USER24> It's not a purely technical issue. Some languages are more popular than others, popularity means more libraries, frameworks and examples. Languages also attract different audiences, those who code C++, Java and ActionScript 3.0 just love piling on boilerplate code and long names like FactoryBuilderFacadeInterface, ApplicationFacadeDependencyHandler.

Other languages, like Ruby or JavaScript, attract people who shorten document.querySelector(id) to jQuery(id), come up with things like Processing (JVM but short syntax school), CoffeeScript, Rails, NodeJS, etc..

AS 3.0 is an interesting example. It's the language of the Flash plugin, which used to be popular among non-programmers as it allowed them to hack things together concisely, without having to learn about types or classes, since old AS 2.0 looked like JS. This was an audience the makers of Flash wanted to keep, but when AS 3.0 came out it chased them away. Online examples became polluted with design patterns, commands, factories, optimizations, complex best practices, long names. Libraries were targeted at advanced coders, there was nothing like jQuery for AS 3.0. When non-programmers see obj.addEventListener(MouseEvent.CLICK, clickHandler) they start shaking. JS frameworks do obj.on("click", onClick) or obj.click(onClick), few irrelevant details.

The language attracted serious developers who were used to big projects. Adobe released Flex, a gigantic framework reminiscent of the Java world, 300-600KB zipped for web deployment. Years later efforts like <http://www.hypeframework.org/> tried to rekindle some of the old flame but the non-programmers are still using AS 2.0 or switched to JS.

Did AS 3.0 have to be as verbose? Did it need giant frameworks and Java developers? Did it need types? No. The performance improvements from AS 3.0 types were negligible, they can be left out in a non-strict mode and the difference is 2 FPS, maybe. For typical Flash projects, debugging with types isn't necessary. Supposedly the situation improved performance wise for types, but that's the wrong priority.

JS/HTML5 picked the smarter approach. There will be typed arrays for WebGL, they're ugly, which discourages their use unless actually necessary. Type strict mode applied to an entire app means example and open source code will have it, it pushes everyone to use it.

When subtle psychological differences are applied to large groups, they create obvious effects. The current division between typed verbose and dynamic concise emerged from social forces more than technical issues. There are efforts like Google's Go, typed Ruby, dynamic C# 4.0, typed arrays in JS, but they're all recent and it will take time for developers to discover new preferences.

<comment><USER25>
      > those who code C++, Java and ActionScript 3.0 just love piling on
      > boilerplate code and long names like FactoryBuilderFacadeInterface

boilerplate code is not caused by the language, but by the programmer, I know more than few examples of compact/clean/well-named code in C++, Java, AS3, etc.

      > since old AS 2.0 looked like JS

no, that was AS 1.0 AS 2.0 was statically checked at compilation time

      > [...] but the non-programmers are still using AS 2.0 or switched to JS.

it's not a problem of being a non-programmer vs being a programmer, it's a problem of a group of people learning a certain way to program with AS 2.0, and when an update occurs to the language are too lazy to change their habits

      > Did AS 3.0 have to be as verbose? Did it need giant frameworks and
      > Java developers? Did it need types? No.

You're mixing a bit of everything there AS 3.0 is not verbose, you can still compile it "AS 1.0 style", just use the compiler MXMLC -ES and yes by doing that nothing is statically checked and all built-in classes default to "prototype" mode. (for ex: [http://hg.mozilla.org/tamarin- central/file/fbecf6c8a86f/core...](http://hg.mozilla.org/tamarin- central/file/fbecf6c8a86f/core/Array.as))

For the giant framework part, yes the Flex framework is big, but it does not define what I would call an official AS 3.0 framework, in fact AS 3.0 at the language level is pretty compact, the "real" framework is the Flash Platform API (or if you prefer the native classes available in the Flash Player or AIR).

So, again a problem of understanding with types, let be clear about something here, you seem to think that because JavaScript or AS 1.0 does not need to assign types to variables and because they are not statically type checked at compilation or interpretation, that there is no types, sorry they have types.

Read those articles from Eric Lippert The JScript Type System, Part One [http://blogs.msdn.com/b/ericlippert/archive/2003/11/05/53336...](http://blogs.msdn.com/b/ericlippert/archive/2003/11/05/53336.aspx)

"JScript Classic is a weakly typed language. This means that any value of any type may be assigned to any variable without restriction. It is often said -- inaccurately -- that "JScript has only one type". This is true only in the sense that JScript has no restrictions on what data may be assigned to any variable, and in that sense every variable is "the same type" – namely, the "any possible value" type. However, the statement is misleading because it implies that JScript supports no types at all, when in fact it supports six built-in types. The "weak" in "weakly typed" refers to the weak restrictions on variables, not on the type system per se."

There are 8 parts of "The JScript Type System" and mho it is a must read if your language of choice is based on ECMAScript.

      > The performance improvements from AS 3.0 types were negligible, they can be left out in
      > a non-strict mode and the difference is 2 FPS, maybe. For typical Flash projects,
      > debugging with types isn't necessary. Supposedly the situation improved performance
      > wise for types, but that's the wrong priority.

negligible ?

OK, first thing first, when you compile AS 1.0/2.0 code, the generated bytecode (in the SWF) is run by the AVM1 (ActionScript Virtual Machine).

The Flash Player support 2 VM: AVM1 and AVM2, AVM2 is the Tamarin VM (<http://www.mozilla.org/projects/tamarin/>).

So when you compile AS 3.0 code, the generated bytecode is run by the AVM2, which support runtime type annotations and is much much much faster because of that.

But let's see hard data

[http://www.masonchang.com/blog/2008/4/28/tamarin- benchmarks-...](http://www.masonchang.com/blog/2008/4/28/tamarin-benchmarks- part-3.html)

[http://www.masonchang.com/blog/2008/4/28/tamarin- benchmarks-...](http://www.masonchang.com/blog/2008/4/28/tamarin-benchmarks- now-featuring-type-annotations.html)

see the difference with and without type annotation ?

now if you want all the greedy details of why this AVM2 is much faster you can look at [http://www.adobe.com/devnet/actionscript/articles/avm2overvi...](http://www.adobe.com/devnet/actionscript/articles/avm2overview.pdf)

<comment><USER24> "boilerplate code is not caused by the language, but by the programmer, I know more than few examples of compact/clean/well-named code in C++, Java, AS3, etc."

That's right, I said the language attracts a certain type of programmer, who codes with boilerplate. There are quick and dirty AS 3.0 libraries, but there is an abundance of frameworks that help you organize code like PureMVC and Robotlegs which add a healthy amount of complexity. JS world has a higher proportion of simple libraries like JQuery than big and heavy ones like Google's Closure, a visitor from Java land.

Flex framework is what Adobe thought would help developers. They spent some effort promoting it and integrating it into their IDE. This means they're not focused on graphics heavy projects that Flash is famous for, but are expanding into the big utilitarian app territory. Such moves attract verbose programmers, who write complex example code etc..

The standard API in AS 3.0 is also more verbose than the AS 1.0, 2.0 or canvas equivalents. This gives advanced programmers better control, while neglecting the needs of novice coders. Adobe is pretty worried about the situation actually, very few novice coders bother with AS 3.0 because they judge syntax visually and AS 3.0 looks longer.

"you can still compile it "AS 1.0 style", just use the compiler MXMLC -ES"

I mentioned that online examples and libraries would use types, which pushes everyone to use them. Using non-strict mode when everyone is using strict is less convenient than just using strict.

I don't know what VM non-strict mode in AS3.0 uses, I thought it uses AVM2, but I shouldn't need to know. I've tried 2D AS 3.0 physics simulations with types and without and the difference was difficult to measure. Most of the time was spent on rendering visuals, not on calculations, so there was no real world speed advantage in that situation. The cases where there would be, like encoding images, need threading anyway.

For a language that isn't a speed demon in the first place, it makes no sense to worry about silly optimizations that are noticeable only in unrealistic benchmarks. Knowing that you need to use int instead of uint to access indexed arrays slightly faster is distracting.

"it's not a problem of being a non-programmer vs being a programmer, it's a problem of a group of people learning a certain way to program with AS 2.0, and when an update occurs to the language are too lazy to change their habits"

I picked up programming a few years ago so I still remember how painful it was to switch languages when I was a novice. Now that I'm not a novice, switching to similar languages is barely noticeable because I understand the fundamentals. Keep in mind, lots of these novices code a simple thing here and there, they don't write large programs so they don't really learn programming. When things change drastically, it makes more sense for these people to stick to AS 2.0 if they can or let a developer handle it.

This is not so much a problem for novices, because they have options, this is a problem for Adobe since novices have options and are choosing Processing and HTML5.

"let be clear about something here, you seem to think that because JavaScript or AS 1.0 does not need to assign types to variables and because they are not statically type checked at compilation or interpretation, that there is no types, sorry they have types."

Yes there are types, but I'm talking about perceived language complexity and boilerplate code psychology. There are few instances where you have to worry about types in JS, but it's a constant time drain in AS 3.0.

</comment></comment></comment><comment><USER26> I see no reason to use a language that eliminates run-time types. Having type information available at run-time means that I can develop, debug, and analyze at a living system. The IDE and refactoring support you can gain from this is in no way inferior to what you can do with a dead, static blueprint system.

My preferred language has dynamic typing, but its common implementations also do type inference at compile time, in order to optimize generic operations, and to warn about things that cannot work. Since during development I only recompile the snippet I am working on, while the rest of the system is running on, the compiler can use all the type information available from the running system.

<comment><USER11> Maybe I'm missing something, but it seems like having type information available at runtime is orthogonal to static type checking.

</comment></comment><comment><USER27> For me, it's all about the interactive prompt. If I can't experiment with my code interactively my productivity falls through the floor. That doesn't rule out statically typed languages - Scala has a reasonable interactive prompt for example - but in my experience such tools are more common (and more mature) with dynamic languages such as Python and JavaScript.

<comment><USER14> That's probably just a historic accident. Most modern languages have an interactive prompt now. For example Scala, as you mention.

Another factor might be the availability of type inferencing, which makes interactive prompts perhaps more viable, as you can for example type "1 + 1" into the prompt, and its type is automatically deduced.

</comment></comment><comment><USER28> When it comes to prototyping nothing beats Ruby or Python. The initial solution won't be pretty or maybe even correct and it will contain tons of bugs but it will give you an indication of the viability of your solution. Nobody starts with a ready made program in their head ready to be coded and dynamic languages usually help you get started with a solution much faster than static ones. At least that's been my experience.

<comment><USER29> > When it comes to prototyping nothing beats Ruby or Python.

Have you ever tried Prolog? While it has a lot of quirks* , it's an _excellent_ prototyping language. (It's also usually dynamically typed, though some implementations have type annotations.)

Instead of a usual function(arguments) -> result model, it treats everything like a search query, incrementally suggesting every possible variable instances that fit known rules. Since search, backtracking, and unification are built in, a lot of code becomes implicit, and you can prototype things quite rapidly.

* Briefly: I think it would be better as an embedded library (like, say, SQLite or Lua) rather than a standalone language. It's excellent for some things, but IO / side-effects are awkward in its model.

</comment></comment><comment><USER30> Seeing statically typed variants of Python such as ShedSkin or PyPy's RPython, I think that one major annoyance is gone.

You still need polymorphism for some things, and having the possibility to have "implicit interfaces" (you just write x.foo() without declaring that x implements the foo interface, or that y and z also implement it - this is also useful when y or z are library classes you cannot change).

Often, the type inference that is needed slows down the compile times quite a bit; and (both with Haskell and with C++) you get incomprehensible error messages when something is wrong but it could have gone wrong in half a dozen places. (C++: 6 lines with "in ...", then "no such method: foo", Haskell: expected type bla->foo->Z x, found a->B c->d)

IMO, static type analysis on top of a dynamic language (e.g. PyDev) gives you most of the benefits of IDE and refactoring support - with the additional coolness that it can just skip the places that are not type-able. (Optional type declarations to put PyDev back on track in the most obvious cases would be great, though).

<comment><USER31> I can get away with simple dynamic typing in small Erlang projects. But building a large project in Erlang/OTP without static type analysis is hard. You will debug for hours some stupid bugs, which C++/C#/Java compilers usually find for you.

I started using type specs and dialyzer - it finds typing errors, and make building complex systems in Erlang much easier. The only problem that dialyzer requires intermediate step of building PLT, which sometimes can takes 20 minutes and more, but only once per project.

</comment></comment><comment><USER32> Having to think about types sometimes slows you down (because you have to think about them), sometimes speeds you up (for the reasons you mention).

Sometimes the type system won't type check a perfectly valid program. One thing that I bump into with nearly every program I write in C# or F# is that I want to add a method to a generic type when the type supports some method. Suppose you have a type Bag<T>. Now if T supports an interface IValue with method ComputeValue() I want to add a ComputeValue method to Bag<T> that computes the sum of the values of the things in the Bag. Of course the method would only be available when T supports IValue. This can be done in languages with more expressive type systems, but there are (provably) other perfectly valid programs that they will reject.

Another reason against statically typed languages is that the compilers are often slow. Compile+Run takes several seconds (if you're lucky).

<comment><USER8> Compiling in a language with static typing is a lot faster than running (not to mention writing!) unit tests to achieve 100% path coverage in a language without static typing.

It's also fast enough that I stopped caring years ago. Don't get me wrong, Eclipse is agonizing when it locks up while "helping" me, but it's not due to compiling (it happens just as often when I haven't made any changes).

</comment></comment><comment><USER33> Working with static types feels like wrestling the code around. Why should the programmer have to care about internal dynamics of a language that are the difference between double, long, int, Integer, Long, short, etc. The compiler or run-time environment should figure it out. That's one more thing that can break, that I'll have to fix.

It gets really irritating when it's an attribute of an object that's returned by a getter that's wrong and cannot be cast, then I need to figure out if this thing is used anywhere other then the place I'm at and if it is, create a new method or... at this point the code is just getting in my way.

<comment><USER21> Yeah, that type (heh) of typing is boring. What is really, really useful, tho', is a type system that can stop you doing things that make no sense in your problem domain. This was the original idea behind Hungarian notation btw: the C compiler can trap things like multiplying a char by a double; it can't trap you adding a weight to a height.

<comment><USER33> Would be nice to have a mixed dynamic/static typing system. So you can static type when you need the solidity and dynamic type when you want ease of use.

</comment></comment></comment><comment><USER34> In my experience, no matter how sophisticated a static type system is, at some point it ends up getting in my way. This goes double for languages with very simplistic type systems, such as C#, as they have all of the disadvantages of a static type system with few of its advantages.

Statically typed languages tend to lack good REPLs, a tool I consider indispensable. I'm unaware of any statically typed language that has something as complete and integrated as SLIME, for instance. Even a properly setup IRB or IPython don't seem to have anything that matches them in the statically typed world.

Another problem is that statically typed languages can have long compile cycles. One C# project I worked on made heavy use of PostSharp, the use of which slowed the compile time to nearly a minute. Additionally, whilst Visual Studio updated the ASP templates in real time, there didn't seem to be a way to reload new DLLs without restarting the development server.

Conversely, when I'm hacking in Clojure, updating the entire system can be done without restarting the server, and takes a fraction of a second.

Macros, too, I guess are easier with dynamic typing. When I write a macro in Clojure, it seems a lot easier than when I was using Template Haskell a few years back. Perhaps there's a better system for macros in a statically typed language, but I haven't run across anything like that yet.

<comment><USER35> _Another problem is that statically typed languages can have long compile cycles._

That only applies if you compile all classes at once. Netbeans (and probably others as well) compile Java classes instantly because they only compile what's changed.

 _there didn't seem to be a way to reload new DLLs without restarting the development server._

I have seen environments for Java that could reload JAR-files. Perhaps DLLs are different, but that has little to do with a statically typed language.

<comment><USER34> _That only applies if you compile all classes at once._

Unfortunately, a lot of post-processors like PostSharp aren't smart enough to do that. Even though Visual Studio was only compiling once, PostSharp seemed to require a lot of time to do its thing.

 _I have seen environments for Java that could reload JAR-files. Perhaps DLLs are different, but that has little to do with a statically typed language._

I'd be interested if anyone knows of an environment for a statically typed language that could do this quickly and without losing run-time data.

In a dynamically typed language, altering the server environment at runtime incurs only the cost of evaluating the code. I can inject code at any point, redefine functions, query the state of the current data structures, and so forth. The entire environment is mutable; something that seems like it would be difficult to do with static types.

<comment><USER36> For Java reloading, I'd recommend you check out <http://www.zeroturnaround.com/jrebel/>

</comment></comment></comment></comment><comment><USER25> to sum it up very quickly

      statically typed: is-a, has-a
      dynamically typed: is-like-a, has-like-a

Read the introduction from Dynamic Typing in a Statically Typed Language <http://lucacardelli.name/Papers/Dyn.ps> "Even in a statically typed language there is often the need to deal with data whose type cannot be determined at compile time"

much more other interesting papers <http://lucacardelli.name/indexPapers.html#Types> and Semantics

If you find that today's C# can be more concise, it's simply because since C# 1.0 to C# 4.0 they added a lot of extensions that can make the language more dynamic (see <http://en.wikipedia.org/wiki/C_Sharp_4.0> with the use of 'dynamic').

In comparaison, if you look at the ActionScript language which have its roots based on ECMA-262(ECMAScript), from AS 1.0 to AS 3.0 they evolved the language to make it statically typed, but you still keep dynamic functionalities like the * (any) type or the option to declare a class dynamic and add members to the prototype.

After it can be a long debate to try to prove which one is "better".

For example, combine unit tests and a dynamic language and you don;t really feel you're missing anything with type checking. Counter example, you can have a statically type checked language that compile and can still throw errors at runtime.

</comment><comment><USER37> You've assumed that statically typed languages are somehow "better" than dynamically typed languages and then asked "Why doesn't everyone use the better languages?" Dynamically typed vs. statically typed is still an open question and is a lot more complicated than "which is better?"

> And on the plus side, you get all the benefits of compiler type checking, > better IDE support, and great refactoring support.

Since when? Compile time type checking is only a benefit if you're worried about type errors and in my experience the people that are most concerned with type errors are the proponents of statically typed languages. With respect to IDEs and refactoring support, my experience has been more along the lines of "C# and Java have good IDEs and refactoring tools, everything else not so much." I personally find Scala and Haskell's tool support to be far behind Python's, just for example. Also, Smalltalk has, arguably, far better tools available than any statically typed language (or any other language for that matter).

Nobody has proven that statically typed languages are better than dynamically typed ones, nor that applications built with them are less error pronen. I would argue that the amazingly widespread use of Ruby and Python and the average quality of projects written in those languages is evidence to the contrary.

<comment><USER38> Regarding tooling, Java has been massive investment in this area compared to ruby/python etc which is one of the reasons for it good IDEs.

<comment><USER39> This is not the only reason. Sometimes you just can't do it with a dynamic language. For example it is impossible for the IDE to help you with auto complete int this case:

def some_function(arg1, arg2) arg1.

The IDE won't show you a list with possible functions because arg1 can be everything.

</comment></comment></comment><comment><AUTHOR> After reading through this thread I still haven't seen convincing arguments why statically typed languages are not "better" (EDIT: "better" for typical web/business applications).

I have been programming Python for many years now, along with a mix of C#, Scala and some F#. I find that the programming idioms that I care about are supported in all of them.

There are some valid problems, but IMHO they are not major:

1\. Compilation Time (But do we have to compile that often? Although I find myself doing this more often with Python, to make sure I did not make a spelling mistake!)

2\. Duck-Typing (Yes good to have. In future we might see more Structural Subtyping)

But what tipped the scale is my experience with refactoring large projects. In dynamically typed languages, it is scary to make a even simple changes in code you haven't touched in a while. Unless you have full test coverage, plus insurance. In statically typed langs, this is much easier.

We run software services company. We have a policy of refactoring suboptimal code on sight. We try to do it in all projects, but I always see worried looks when refactoring dynamically typed code. And not so much when we are modifying, say C#.

</comment><comment><USER40> I think that the dynamic vs static debate also depends a lot on how you program. For example, there are people who like to write a few lines, then test, write a few more lines, test again, and so on. For them dynamic languages are prefect.

On the other hand, I am the complete opposite. I often work for hours or days, sometimes even weeks, on a program without ever running it. This is only possible when 99.9% of all errors immediately caught by the compiler (or IDE). Also, I document everything that I do extensively with Javadocs or similar mechanisms. When I write in dynamic languages, I usually start writing the static type annotations ("//array of string") as comments, without having the benefit of using code completion and refactoring. So effectively, for me, dynamic languages mean more typing rather than less.

</comment><comment><USER41> A big advantage of Python versus C# is not having to think about types unless you have to, and if the code is less verbose that's a side benefit. (And honestly, I'd be surprised to find a whole lot of C# code that couldn't be written to be more concise in Python, if performance wasn't an issue)

        def foo(lst):
            if type(lst) is str:
                 #return do_string_stuff_to(lst)
            else:
                 #handle do_list_stuff_to(lst)

And I'm done. There's a good chance I'll throw the function away or re-write it before I ever care about the sort of edge cases that would get caught by a static compiler. If the algorithm works on a dictionary or set just as well as the list I had in mind, so much the better. In the meantime it's doing its work and helping me get other things done.

<comment><USER42> I believe you meant

        if isinstance(lst, str):

<comment><USER43> If you really want to be pedantic, it should be:

        if isinstance(obj, basestring):

So that it works with unicode in Python >= 2.3

</comment></comment></comment><comment><USER44> As a non-programmer, in that I use programming for math/eng problems, the main advantage for a dynamic language like python is that you do not have to compile it.

I'm not a good programmer so sometimes I have tiny errors and such and being able to vim exec.py fix ./exec.py can help tons.

I do a good amount of things in matlab and must say that I use the cmd line (REPL?) infinitely along with my programs, it is just so easy for me to find solutions that way compared to something like C# and for someone that doesn't always know how a function works using it on the command line with documentation is great.

<comment><USER14> You are confusing dynamic typing with dynamic code interpretation.

So there ARE statically typed languages with a REPL, for example Haskell.

And there are dynamically typed languages without a REPL - for example Perl (in the core distribution).

Static typing means that for example, a list can only contain one type of element. And because of these constraints, the compiler can find some errors that are not found otherwise.

<comment><USER44> And there is the bad programmer part :), thanks for the clarification.

</comment></comment></comment><comment><USER45> I choose Python, it just happens to be dynamically typed.

Not having used static typed Python I can't say for sure but I believe significant indentation, std lib, and how language generally follows "the zen of python" are at least as if not more important than static typing.

</comment><comment><USER46> Because you can iterate, and you always have an REPL. Also you can change on the fly function definitions, reevaluate vars, and even more stuff - <USER2> example change the classes on the fly for Common Lisp (and I'm sure for others).

</comment><comment><USER47> I'm confused by your statement that statically typed languages are concise. Every time I program in Java, the code size ends up blowing up exponentially. However, a good 30-40% of the code is boilerplate rather than having to do with the task at hand. Now, this isn't a direct consequence of static typing BUT it looks like a very high portion of statically typed languages lean towards having a low content to code ratio.

<comment><USER14> Java is not the only statically typed language, and some statically typed languages are almost phenomenally concise.

<comment><USER47> If you're referring to Haskell and the likes, sadly they're not nearly as prevalent.</comment></comment></comment>


Barometric light - <AUTHOR> https://en.wikipedia.org/wiki/Barometric_light <comment><USER2> We have a small sealed uranium glass tube with a drop of mercury in it at the Makerspace I run. It was Part of a donation of scientific equipment. If anyone is in Utah and wants to see this effect firsthand, head over to ProVolt on an open night (Tuesday or Thursday).</comment>