I couldn't believe all the junk Java required of me when I took a stab at it. It's like being confronted with some unhelpful bureaucrat: I know what I mean, they know what I mean, but they're damn well going to make me trudge through all the nonsense so that what I mean is turned into something the bureaucracy understands. The linked NLP examples are great for illustrating this.
A language that needs you, the client programmer, to define getFoo () and setFoo () methods manually can't be right.
what do you think of ooc-lang syntax? http://ooc-lang.org/
Just an opinion, though.
another example: functions should be virtual by default.
No no no!
C++ got this one right, and then C# did better ('virtual' to declare a virtual/overridable function in the base class, and 'override' to replace it in the subclass).
http://www.artima.com/intv/nonvirtual.html
Every time you say virtual in an API, you are creating a call back hook. As an OS or API framework designer, you've got to be real careful about that. You don't want users overriding and hooking at any arbitrary point in an API, because you cannot necessarily make those promises. And people may not fully understand the promises they are making when they make something virtual.
It seems like Java wasn't defined in order to be an efficient for a three-person shop to hack in. It was meant to be efficient for a 40 person shop to build code as a team that they can maintain.
That said, I dread going back to my Java projects and updating them, even though I tried to maintain best practices in order that updating be as simple as possible. I've been immersed in php and javascript lately, so we'll see what it's like to go back.
I also tried to stay close to the OO paradigms (of course, I was just learning them), as I built this 50000 line beast called "Egorg." Now, I get to maintain and update it, so we'll see if it paid off.
On a side note, I have a real distaste for objects in Javascript. They seem clunky, almost like they were stuck on as an afterthought (I get a similar feel about Generics in Java). But the design of Javascript makes it quite easily to hammer out a script to do something cool. I'm worried about maintenance, though, because I feel like I'm evolving my own design patterns, so retracing my steps will likely be painful.
You are correct about the IDE thing. That does ease a large burden in Java.
I think that this is happening to many people who are doing a lot of 'non-trivial' JavaScript. The language is still very young and because the concepts that were chosen when creating the language are powerful and flexible (prototypal inheritance, objects can be accessed like hashes, first-class functions etc) there's always a million ways to code something.
OO-wise i think you can divide into those who use the `new` keyword and build objects that are more or less Java-like classes and those who create objects and prototypes on the fly, and probably use a lot more ideas from the functional and LISPy side of things.
My worst crime by far (that I am aware of) is that I have no hesitation to use a global variable if it saves me from bending over backwards to get around it. I'm doing animations, and sometimes the algorithm just comes to me a lot faster if I let a var keep a global value and be used by lots of functions between calls to my animate() function (using window.setInterval() ).
JavaScript is language that is very different from anything else. Depending on how you look at it it has either unconventional semantics (majority view) or unconventional syntax (my view). It's object model is strong and often useful (you can emulate class-based inheritance with it, not the other way around), but I agree that it is to some extent afterthought (although I have strong feeling that our reasons are very different). What is probably largest problem of whole JS is the "Java" part of it's name and weird syntax deliberately designed to "look-like-Java" or "look-normal", which simply does not match underlying semantics.
Coming from C/Unix background I actually consider the IDE thing burden in itself. I expect that there are some easily editable source that is transformed by series of some steps into final program, but all changes happen only in the original input. Which is simply not case in Java/ST world, where you essentially need pretty complex IDE (on the side note: few years ago some Java IDE I was using for quick experiment forbade me from saving source file with syntax error with it... WTF?).
What I find really cool about your comment is that you appear to have a deeper view of it all (meaning a deeper understanding of the underlying semantics), and I'm wondering how my view will change as I continue to work with it.
*I realise that pro Java coders use Eclipse to generate their getters and setters, but I have also drank deeply of the vim kool-aid and find myself going to ridiculous lengths sometimes to avoid other editors or IDEs. I keep trying to navigate with the wrong keys and trying to save with :w and using :sp to open other files when I use them.
public Customer(String name, int custId)
do public Customer(CustomerData cd)
where CustomerData is an object. In Customer you would have getters and setters for CustomerData rather than each item that identifies your customer. This is for extensibility: As your app grows, some part of it may need other ways to identify the customer. Adding these ways won't break your Customer interface. That's the purpose of the rigor of the design standard.Now what I do, which goes against stated policy, is keep the CustomerData variables (String name, int custId, and so on) public so I can set them easily. The only time I require getters and setters for primitive types (for example, name) is if I were to read in data from a user generated form that needed to be sanitized.
My apps are full of these customized data objects, and it's a technique which has saved my ass as I added features etc.
If you encapsulate all the data about a customer in a "CustomerData" object, do you really need a separate "Customer" object? Or do you mean, not the whole customer but larger bundles of information like addresses etc. that don't need any business logic or abstraction but are nice to have as one single bunch of data?
(I mean, there's a reason why C++ still has "struct"s even though OO zealots will tell you they come from the devil).
Edit: I didn't parse the "ouch" the first time I read this. Sorry, I'm not trying to be an ass about it. But when I first started trying to figure out the "right" way to do it, I came across something (probably by Allen Holub) that confirmed something I was suspicious about: There is no sense in having a private variable if you are just going to expose it with public getters and setters (except for sanitation purposes). The real point was to pass in the data through data objects, and keep the private members unexposed. This also means (typically, at least for me) a lot fewer getters and setters. It's completely against the Java Beans "way," I think, but it works well in real life. I use Java Beans only for persistence, because I like the automatic JB-xml conversion. That is, I make data objects out of the data that I want to store into a Java Bean, and do the automatic xml storage and read thing. It took me a while to figure that out. My first app, I hand-coded the xml. Ugh.
It's funny, too - though this type of thing goes against best practices, the primary argument for always using getters/setters (some day you might need to validate input or do other sorts of logic, and it's a pain in the ass to put that in after the fact) is pretty much 100% shattered these days, because any IDE worth a damn makes it possible to switch from public field access to getters/setters in a couple of keystrokes ("Encapsulate field" and "Inline method" are typically all you need).
Though it's worth keeping in mind, most of the Java best practices tend to assume that you're writing code that other people will have to use, people whose codebases you won't have access to after you release your code, and that's a much more difficult context to program in. It requires a lot more bureaucratic nonsense to leave your API flexible when you have to worry about breaking other people's code with each edit you make, and extreme paranoia is more than justified when that's what you're worrying about.
If you want Java without the unwieldiness, try Groovy. It's Java with a ton of syntactic goodness added; for instance, the default variable scope is "create a getter and setter which I can optionally override." Groovy interoperates well with Java libraries. The downside is that it's a dynamic language, so there is a significant performance penalty.
"Secondly I don't mean to criticize Java. By calling it a toy language, I was simply referring to the fact that Java tends to make writing bad code difficult, and in doing this takes away some of the flexibility and power that you tend to associate with other languages."
Judging from the general reaction it seems I should not have used the term "toy language". My apologies if I ended up implying that Java has little practical use.
I've known people who could write bad code in Java with the utmost ease!
It'd probably be more accurate to say that Java deliberately limits its expressiveness, in order to make it harder for people to shoot themselves in the foot, and to make it easier for one programmer to understand what another has written.
That is exactly what I meant.
Bad programmers exist. They will write bad code, no matter what language they're made to use.
If this were actually the case, it would be a bonus point for Java. It isn't, however. Nor is it the case for Python, Ruby or even BSDM languages like Ada.
How many times have you come (when searching for a used car or trying to reserve a table at a restaurant) to a slow, ugly, non-functional URL that creates an error message if you press the wrong button at the wrong time? Usually those URL ended in ".jsp", ".asp[x]" or ".cgi" or ".php".
I'd argue, that the largest amount of bad code that exists is in Cobol, followed by Java, C# and then C/C+, PHP and various BASIC dialects. That has nothing to do with how good those languages are but rather with the facts that most code out there:
a) is created by IT departments or outsourcing firms staffed by mediocre or completely disinterested programmers (I've never been in such an environment, but my hair stands up every time I read horror stories on dailywtf or on progit)
b) shouldn't have been created in the first place (there are commercial and open source packages that do this) if it weren't for the NIH symptoms. There are tons of restaurants with their own order/registration forms despite the fact that OpenTable is widely known and available. There are tons of non-technology companies writing their own accounting systems even though there's a multi-billion/year industry around that type of software (that employs programmers who understand not just J2EE but accounting itself as well).
c) is forced upon its users (due to the sunken costs fallacy) and thus isn't exposed to market forces
d) is written in those languages as they're most common and are either easy to learn (PHP, BASICs) or are widely taught in colleges or trade schools (Java, C#, C++)
Truth is, there is no magic language bullet. Some languages are more expressive, more pleasant to program in. Some produce faster code. Others are more scalable in the sense of making it possible to write whole systems in one language. Some are more "safe" in the sense of being less prone to garden variety security attacks, less likely to crash the entire machine when there's a bug (at the cost of imposing restrictive abstractions on the programmer).
No language, however, is a substitute for a team of competent and interested developers solving a relevant problem.
The following code is readable and I have required a variation of it in a program before:
sorted([ord(c) for c in
set('letters in this sentence') & set('and this one')], reverse=True)
Doing it in Java would be a chore now. (use 'clojure.set)
(reverse (sort (map int
(intersection (set "letters in this sentence")
(set "and this one")))))
Edit: Take two... (use 'clojure.set)
(->> (intersection (set "letters in this sentence")
(set "and this one"))
(map int) sort reverse)
(experienced lispers, feel free to make this more idiomatic) (require ['clojure.set :as 's])
(-> (for [c (s/intersection (set "letters in this sentence")
(set "and this one"))] (int c))
sort
reverse)(Set("letters in this sentence":_* ) & Set("and this one":_* )).toSeq.sorted.reverse
Or you, can take advantage of Scala's rich choice of collections.
import scala.collection.immutable.TreeSet
import scala.math.Ordering._
TreeSet("letters in this sentence":_* )(Char.reverse) & Set("and this one":_* ) toSeq
The machinery Scala has in place to make the second example work is quite impressive, and I was pleased to see that it worked. Even though the intersection method returns a brand new set, using implicit arguments it correctly creates a set of the correct type (TreeSet) with the correct ordering function (Char.reverse), without any duplication of code in the standard library (like overriding '&' in every sub-class).
("letters in this sentence" + "and this one").chars.sort.reverse
I can just as easily write ("letters in this sentence" + "and this one").toSeq.sorted.reverse in scala. You could tag the end of your ruby statement with .uniq and you would be fine. Alternatively, you could wrap the above scala statement in TreeSet(). These solutions process things in a significantly different way than was done by the OP, though.
I'm just learning, but I think this performs it correctly with sets.
1. I love python.
2. The OP was being a troll.
3. People need to be more honest about themselves and their favorite pet languages. I can write a sorted set in assembler too, if I wanted. However, there's been several times that I've wanted a sorted set data type while coding in Python but found that none was easily available. I hate the, "you can write your own!" counterpoint, because it is essentially meaningless unless you can prove that writing your own is as trivial as importing someone else's implementation.
By the way, in case anybody was wondering, here is a (relatively inefficient) way of making a sorted set in python:
from random import choice
choice(list(myset))
(I'm guessing you'd want to do it without having to convert it to a list first?)Scala isn't as succinct, of course, but it gets much closer!
I think it's fairly clear from context that he/she means, "not a lot of red tape", rather than a reference to specific language features.
Counter-edit: My response was in jest. I deliberately misinterpreted the term for humorous purposes.
Python for me is the imperative language (with some functional features) closest to pseudocode.
I've done some Django programming in the past. A view gets a request object (pardon me if I'm wrong or if this has changed recently) and is supposed to then render the response (or something similar, I don't remember exactly). Now what is a request? If Django were in C, I would know what a request object really was, grep for it, and look up the header file. If request has a GHashTable named post_data, I don't think I need two guesses about what it exactly is. Same goes for C++ and C#.
Then you've inconsistencies. The same method may return a string object or an integer on different calls. And this happens in practice - I remember when I was (trying to) model a relational database in Django, I found a ManyToMany field returning (when invoking values ()) a list of dictionaries instead of a list of Model objects (which I was expecting).
Of course, if I was not dumb enough to not read the documentation I might not have stumbled; but the point is that Python allows this to happen. And since I don't have the benefits of a compiler, anything other than basic syntax errors (the ones I can catch by calling py.compile) explode at runtime.
The thing I've begun to notice that scripting languages tend to require you to hold the entire structure of the program in your head as you code. In C++ you know that unless you've gone out of your way to do some casting magic, a string get_foo () will always return a string. And you can always do get_foo ().c_str (). In python you're never sure.
The idea that the OCaml community is dying is purely subjective. OCaml, having been around longer than F#, may just be going through a perceived lull.
Either way generalizing that F# will replace OCaml as the goto language in the ML family from a perceived decline in the OCaml community is probably not the right call.
http://norvig.com/21-days.html
From your comments, I kind of get that you want to be a real good programmer, and part of being a good programmer is to understand the different way you can wire bit and pieces together in the many different languages. I had a similar experience as you in that I went from C->C++->Java->Javascript->Scheme->SML->Python. I can definitely tell you that learning Scheme and SML first helped me tremendously in understanding dynamic languages in general. In more concrete terms, understand typing rules has helped me how to debug a program when I mess up in Python. For example, in SML, I can completely omit type annotations and the interpreter will infer the right type for me at parse-time, and that each function or statement must only return 1 type.
In dynamic languages such as Python, you can still do what you can do in SML or Haskell, but the runtime system makes no guarantee that your program as it is written is type-safe when the interpreter parses all your source files. Type checking is done at execution, when the code path in question is exercised. However, if you THINK about how the types are infered in SML when you write in Python, you generally will not run into TypeErrors.
The same goes for functions that return different types. To prevent tripping up with these functions, just apply what you've learned in Haskell or SML when you are debugging library functions that do this, and avoid writing functions that return different types.
def foo (self, stream): What is stream here?
void foo (std::ostream &out) { out << "bar" << endl; }
Hope you get the point.
The inconsistencies you mention are (in a well written code base) very rare. If you call a method get_name() odds are you are going to get back a string. If you seem to randomly get back an int or a dictionary or a datetime object it's a pretty good sign the code is foobar'd. Good Python programmers don't abuse the dynamic nature of the language. Methods should return predictable types (documentation is important), it might return different types depending on the input but this should be documented and obvious (say a parse date method that returns a datatime object if you pass it a string containing a date and time). The values() example you use is very clearly documented as returning a ValuesQuerySet that supplies dictionaries not models (http://docs.djangoproject.com/en/dev/ref/models/querysets/#v...).
In a number of years using python, the standard library and 3rd party libraries I've never been left wondering "If I pass X to this method what the hell type am I going to get back". Just like in C/C++ I need to remember it returns a list or a string or a dictionary but that's usually where the mental overhead stops.
Python is dynamic which means it's flexible. Flexibility is usually reached by sacrificing simplicity so Python encourages testing and good documentation. I would argue that these are both necessary features of any good code base, Python is just more upfront about this than a number of languages.
The purpose of this thread was merely to gauge what kind of paradigm shift people who were used to programming in C or C++ generally experience when they move to Python. Some people seem to find making the jump easier than others - I personally have found it difficult and have made little progress so far. Since I generally consider myself good with computers, I find this a little unnerving.
I really like using a dynamic language for some tasks. I almost never use C, C++, or Java for any task I hope to start and complete within a day. Those jobs are small enough it's easy to keep track of what you are passing around.
I spent 6 months writing all of my utilities in Python. I tried very hard to like it, but it just didn't tickle my fancy. I do like perl and ruby for a dynamic language. I think perhaps the issue is, if you are like me and you don't like using dynamic languages for large programs, the extra clarity of python isn't enough of a added bonus.
If Django were in python, you wouldn't even have to grep
>>> import django.http, inspect >>> print inspect.getsource(django.http.HttpRequest)
Django in particular has several additional advantages:
• it has an "interact" mode that pops you into a Python REPL so you can poke at all of this stuff interactively instead of having to save a source file and hop over to your browser;
• it has really first-class documentation;
• if you raise an exception in debug mode, the traceback includes dumps of all of the objects mentioned on all the levels of the traceback stack, along with a few lines of source code from the stack frame;
In short, Python offers much more power to undertake the kind of analysis you were wanting to do than C or C++, but you have to do it dynamically, instead of statically.
import pdb; pdb.set_trace()
which makes it enter the debugger at that point, and I simply inspect the object that I'm really getting, looking at what it supports, the documentation on its methods, etc.Doing it this way is not always feasible, since sometimes there's a prohibitive amount of setup code that needs running before you can get a real object. For short code paths though, like Django apps, it works really well.
$stdin.read.split.each do |w|
puts w if w.match(/ing$/)
end
or as a single 57 column line: $stdin.read.split.each { |w| puts w if w.match(/ing$/) }
we can also use the match operator: $stdin.read.split.each { |w| puts w if w =~ /ing$/ }
I'm inclined to assume that the other language examples are also suspect.foreach line [read stdin] { foreach word [split $line] { if [string match *ing $word] { puts $word } } }
The one thing that gets me is the "it's already been done" mentality. If you love Tcl then you want to create things in Tcl for the world to use. I have thrown out a couple ideas like "mailman in Tcl" or "nagios in Tcl"...but I always get "it's already been done". Sure, I could have done it anyway, but it gets your spirit down when you hit that wall. I know they have been done with other languages. Let's do it in Tcl to see if it can be done better!
The whole scripting language issue is a complicated one imo.. People want to either use 100% scripting or 100% system (i.e., C), which is not alright. Combine scripting & system according to your needs. This is why I like Tcl the most: It prevents you from using it where there might be computational bottlenecks (e.g., in algorithms). It is meant to complement C, not replace it. Anyway this is a separate thread.
[read stdin] returns a string (not a list of strings), which is parsed as a list when you try to loop over it. The parsing breaks the string into a list of words, so the second loop is redundant. The parsing could fail if the input file isn't valid list syntax (unmatching {}'s). [split _] makes it safe.
foreach word [split [read stdin]] {
if [string match *ing $word] { puts $word }}
I love Tcl too! Tcl is a scripting language for C, Python is less-powerful version of Lisp.ARGF.lines.each { |line| line.split.each { |word| word.match(/ing$/) and puts word } }