views:

1538

answers:

18

I've been programming C++ for about 5 years now, and I now realize the value of knowing how to think "differently."

This question is for C++ programmers who tried out other programming languages and came across moments like:

  • "Whaoo..this is sooo cool! I didnt know I can program like that."
  • "Wow, I never thought a design problem could be solved that way!"

So, which language did that to you? I'm looking for maximum effect, so I dont think Java would fit the bill. =p I'm open to any suggestions, though!

Disclaimer: I ask this question primarily because I want to expand my mind. There is no intention to start any programming language war here!

+11  A: 

For something truly different, try Lisp or Scheme.

Eli Bendersky
+1 I agree. Once I learned Scheme, a lot of stuff in STL started to make sense to me. Learning any functional language will make you a better C++ programmer for sure.
AraK
Yup. Anything functional, really. But Lisp/Scheme have a certain added cool factor. :)
jalf
Scheme is great because the language itself is so simple, almost toylike, but with its few simple forms you can build the most complex things.
Crashworks
+1  A: 

I've programmed in Pascal, Delphi, Assembly, C, C++, Scheme, Lisp, Java, C# and CUDA.

C# is the answer - you can write extremely dynamic programs using reflection, and WPF really places C# at the edge.

Danny Varod
I totally agree.
Dave Van den Eynde
Voting down because you like C++ or Java better is lame.
Danny Varod
+1 from me, anyway. For a C++ programmer, C# is the neatest way to get access to modern language/platform capabilities. The syntax is not distractingly different, but most of the things that are cool about other modern statically-typed languages (type inference, closures, generics, reflection, meta-programming, lazy evaluation/lists, GC) have very good implementations in C#, and interop with your existing C++ code is very easy. So it's perfect.
Daniel Earwicker
@Earwicker: do you have suggestions on a good book or resource that teaches how to interop C# with existing C++ code?
ShaChris23
ShaChris23, there are two methods for doing this, wrapping with a C# class with DllImport, wrapping with a C++ CLI class. DllImport has simpler code and only required the C++/C dlls, but error can only be detected in unit-tests and during run-time. C++ CLI has requires the C++/C headers and libs to compile, has C++ compile-time checks, but has an annoying syntax. I personally have used and still use both and slightly prefer the DllImport method.
Danny Varod
+15  A: 

Python gave me the "so cool" reaction

Stephen Doyle
is there any that stands out that you could give as an example?
ShaChris23
Lots of things did it for me. Generator functions (and generator expressions) were particularly cool.
swillden
The dynamic nature of lists and objects removed a lot of restrictions that I was used to from C++. I continually am amazed by the expressiveness of Python and what can be accomplished with so few lines of code.
Stephen Doyle
The developers of Python regularly review other languages and when they see something that is way cool, they incorporate it into the language if they can. Although Python at its core, is a dynamic object oriented language, it has incorporated a lot of elements of functional programming which you see in stuff like LISP/SCHEME, Erlang, and so on.
Michael Dillon
+2  A: 

Prolog is a must. Any other language of a different paradigm would be a good start. Prolog is of a logical paradigm. Another great yet very different language is Scheme. It is of the functional language family.

Here a few sample of a Palindrome validator.

EDIT: Someone mentionned that the code I wrote is unimpressive and discouraging. Here's a few simplified examples:

Scheme factorial


 (define (fact n)
    (if (= n 0)
        1
        (* n (fact (- n 1)))))
Prolog factorial

factorial(0,1). 

factorial(N,F) :-  
   N>0, 
   N1 is N-1, 
   factorial(N1,F1), 
   F is N * F1.
And my original examples: Prolog sample:

:- set_prolog_flag(toplevel_print_options, [quoted(true), portray(true), max_depth(0), attributes(portray)]).


readline(Line) :-
 get0(Ch),
 readline(Ch, Line),
 !.

readline(10, []).

readline(Ch, [LowerCasedCh | RestOfLine]) :-
 is_alpha(Ch),
 name(N, [Ch]),
 downcase_atom(N, LowerCasedN),    
        %Drops element down to lowercase
 name( LowerCasedN, [LowerCasedCh]),
 get0(NextCh ),
 readline(NextCh, RestOfLine).

%Character Trimming

readline(Ch, RestOfLine) :-
 \+is_alpha(Ch),
 get0(NextCh ),
 readline(NextCh, RestOfLine).



palindrome:-
 readline(List),
 sarahPalindrome(List).


sarahPalindrome(List):-
 reverse( List, ReversedList),
 List = ReversedList.
 
Here's a solution in scheme for the same problem!

(define palindrome
  (lambda (x)
     (equal? (filter-non-char-alpha (reverse (string->list x))) (filter-non-char-alpha (string->list x))
    )
  )
)
(define filter-non-char-alpha
  (lambda (x)  
        (if (equal? x '()) #t 
                    (if (char-alphabetic? (car x)) 
                        (cons (char-downcase (car x)) (filter-non-char-alpha (cdr x)))
                        (filter-non-char-alpha (cdr x)) 
                    )
        )
   )
)

ManicMailman
yes, sarahPalindrome is a helper method, as well as a very bad pun :P
ManicMailman
Prolog made me understand that not all programming is same-ey. The language's intended purpose is so far removed from the main line of day-to-day coding that writing anything in it is a revelation. Even "Hello, World!" holds a lesson about the construction of a declarative program.
Mike Burton
Agreed. I like to see different languages as different set of tools. You can smash a nail with a screwdriver, but knowing how to use a hammer would make the task easier.
ManicMailman
wow...that was definitely cool!
ShaChris23
I learnt Scheme a few years ago and forgot it soon after, it is very unimpressive. I have never written in Prolog, but reading your Prolog code could convince potential future programmers to disregard any attempt to program.
Danny Varod
To be fair, that's a very narrow approach to programming. For example, have you seen the implementation of a parser generator? Write it in C++, it would take a few pages. Write it in Scheme, it would take you a few blocks of code. Write it in prolog, it's one block of code.Also, why is Scheme 'unimpressive'? I cannot replace C++ or Java, that I agree. But have you ever tried to compute 1000! (factorial) in C++? See the example in Scheme above I added. Try it yourself. Now try to do something equivalent in a 'impressive' language.
ManicMailman
+6  A: 

I'll second Lisp/Scheme, and also suggest Haskell as a language that will challenge the way you think about programming. The O'Reilly book "Real World Haskell" is a pragmatic introduction, well illustrated with concrete use cases.

itowlson
+1 for Haskell - i find it syntactically much clearer for academic and quests of self-challenge then e.g. lisp.
Georg Fritzsche
+4  A: 

Assembly (which I learned before C++, and used to write TSR interrupt handlers under DOS): I enjoyed having the illusion of knowing what the machine is actually doing.

C# is neat too: C++ pointer-to-member syntax is so convoluted, C#'s anonymous delegates are comparatively fun (we'll be getting something like them in the next version of C++).

ChrisW
Assembly is a must, to really understand what is going on in the CPU, however you should learn computer architecture and operating systems along with that to get the full grasp. I do NOT recommend that as the next step though.
Danny Varod
+5  A: 

The whole "Whaoo..this is sooo cool! I didnt know I can program like that." revelation came to me when I first learned functional programming. In my case, this came through my studies in Tcl/Tk, which is multi-paradigm, but I imagine you can get the same effect from any of the strongly functional languages (such as Lisp or Scheme).

goldPseudo
+10  A: 

Of course Haskell, but really all of the following really changed my perspectives:

I started in GWBasic years ago as a kid, so I gravitated naturally to procedural languages.

My career started in C++, and that is the foundation I build from.

  • JavaScript - Introduced me to first class functions, closures, dynamic typing.
  • Python - Introduced me to simpler syntax, and dynamic languages in general.
  • SQL - introduced me to languages that 'are' vs. languages that 'do', the code 'is' the answer.
  • Lua - minimalism and using simple data structures (tables) for the basis of all data structures.
  • C# is my new bread & butter... The advantages of garbage collection, built in libraries, etc.
  • C - I've got the power!
John Weldon
+1 for having the courage and insight to name something as old-fashioned as SQL. Still the only truly commercially successful example of real paradigm-shifting language (except for C++)!
RBarryYoung
thank, i personally like your answer.
ShaChris23
Thanks! I appreciate it. :)
John Weldon
+3  A: 

Python may be the answer.
It can improve your C++ way of thinking and design and teach you some new ideas and methodologies such as functional programming.
Duck typing may seem strange and problematic, at first, but it has its own benefits.
And you may end up using it even for productive purposes

Another option is to try to write "hello world" in brain fu_k. Maybe it's not the best use for your time, but after that you will never try that "broaden perspective" stuff :)

Oren S
heh [And you may end up using it even for productive purposes] - I personally enjoy Python so much I go out of my way to use python wherever I can.
Tom Leys
+1  A: 

Firstly, good on you for looking to do something different! If you're up to it, this is a great opportunity to try something which works in a completely different way, if only to broaden your understanding of how things work. I'd echo ManicMailman's comments about Prolog, which is very different indeed from the Pascal/C/Java approach. I would also suggest two other ideas.

Firstly, one of my all-time favourite languages is PostScript, generally known as a page-description language, but a fully-fledged language in its own right. It work almost entirely on stacks, so calling operators take arguments off the stack and push results back on it. Of course, it also tends to have a high-quality output device associated with it, which can be useful. :-)

Also, if you're ready for something very different from what you're used to, you'd do well to consider a functional programming language. I'm not personally very experienced in these, but I understand that Lisp and Haskell have their admirers.

Lastly, you've assumed that going for a new programming language is the way forward. If you're even moderately academically-minded, you might find that reading up on data and algorithms might seriously improve the way in which you understand and solve computer-based problems. One of the standard texts is Sedgewick's Algorithms in C, although in my opinion Knuth's The Art of Computer Programming is the best in the field.

Good luck! :-)

Tim
A: 

C++ does the 'whaoo' all the time.. and every few years or so in incredible applications.

If I had to chose something else that is as misunderstood and easily obused but incredible in expression, sure easy: JavaScript.

The next leading and useful indicator is again obviously Google favourite, Python, but they are moving into the above two at a faster pace than any time before.. Go figure..

rama-jka toti
+2  A: 

I would try both Scheme (or Lisp) and Python, in that order. Scheme will warp your mind in a positive way (it did for me), and then move on to Python, where you'll be (quasi-) able to put together your C++ and new functional knowledge. You'll get a big kick out of both, I promise.

Eddie Welker
+2  A: 

A recent "This is so cool!" for me was Scala. It combines functional programming, objects and threads in a great way, and it all runs in the JVM.

For me it was the first really cool thing I'd seen that was Java related. :)

Oh, okay, it was the second. The first was a reversible debugger which I forget the name of, but it let you run the virtual machine "backwards" in order to find a bug.

Zan Lynx
+2  A: 

I second Python, and Ruby too.

Re-read Design Patterns... then learn Python, and realize quite a lot of design patterns are actually stopgaps trying to patch a defective language like C++.

When classes are first-class objects, for instance, the Factory pattern becomes obsolete. Just pass the class, it is after all an instance factory. Python classmethods are also an extremely powerful tool, and the inheritance works.

Many design patterns are workaround for languages that lack closures, builtin delegates, etc...

For instance, in Javascript :

button.onclick = function(){ some code }

Simple, elegant, and powerful... in C++ you'd have a lot more work !

peufeu
that button.onclick example was definitely cool. and it looks very intuitive too. thanks!
ShaChris23
+1 I encounter the "patterns are just workarounds" myself all the time. Its hard to explain to a C++ programmer who hasn't embraced a high level language
Tom Leys
+36  A: 

I am probably at heart, mostly a C++ programmer, because I have used it so much, so you may find my experiences interesting.

In chronological order, here are the languages I learned, and my epiphanies. I've highlighted the big ones for me. Of course there are many different languages that can provide the same insights, I am just sharing my own personal experiences.

  1. Atari Basic - Cool I can make my computer do almost anything, but I keep running up into my 8k memory limit (or I run out of line numbers)!
  2. Logo - No line numbers. I can incrementally build and run my programs (later I saw this in Lisp, Scheme, and Forth)
  3. Pascal - It's just like Basic but with more functionality (and no line numbers).
  4. C - So that's what pointers are (now I understand peek and poke).
  5. Assembly - Ah, that's why C is designed the way it is. I might as well just use C instead of assembly.
  6. C++ - Objects are a great way to structure my program into logical chunks
  7. BASH - Programming with stream (filters, sources, and sinks) can be very powerful
  8. PostScript - Fonts are programs! Stack-based programming is a very powerful paradigm.
  9. Prolog - So you can just write a bunch of constraints, and get the computer to work out the answer itself. But, gosh, its hard to know what constraints to get it to do what I want!
  10. Perl - It doesn't matter if people don't know all the rules. I guess some languages are designed to be easier to write than read.
  11. SQL - What a convenient way to query data. It reminds me of Prolog. (later it reminds me of functional programming).
  12. Lisp - So you don't need manual memory management, to make linked lists! (Note I didn't spend enough time on Lisp. Many later lessons could have been learned with it.)
  13. Object Pascal - Cool, Pascal can have objects too.
  14. Modula-2 - Strange, this looks like Pascal.
  15. Simula-67 - Hmmm... so this is where object-oriented languages came from?
  16. Java - Everything can be an object (I later learned that even more things can be objects, see Smalltalk below) and code can be compiled-once and run on different platforms. Other epiphanies I had were interfaces are a great way to construct software and garbage collection is really powerful.
  17. Delphi - Wow, GUI libraries can be easy to use. Events are an awesome abstraction.
  18. C++ templates - Writing code at compile-time is extremely powerful (see Scheme and Lisp).
  19. C++ functors and binders - Passing functions to functions is powerful, but the syntax is awful. (This was actually my first real experiences with functional programming, most languages obviously do it better).
  20. JavaScript - Prototypes and eval functions are really powerful.
  21. XSLT - I can't believe that this is Turing complete. This must be what happens when academics go bad.
  22. Eiffel - Contracts are a great way of expressing design assumptions and requirements.
  23. AspectJ - Cross-cutting concerns make perfect sense, and it's true that they are hard to express in other OOPLs. But identifying them by the name of a function seems like a hack?
  24. Scala - Fields and methods are the same. Higher-order functions can be simple to write. The compiler can guess the type of simple expressions (but not templates). Object code can be much simpler. Pattern matching is neat, but when do I use them? Traits and mix-ins are even better than interfaces.
  25. C# - This is like Delphi mixed with C++ and Scala. I can reflect over everything at runtime, and even emit code easily.
  26. D - So that is what it looks like to combine unit-testing with design-by-contract, and a bunch of other things, while maintaining a C++ mentality.
  27. Smalltalk - Didn't really learn it, but Smalltalk programmers pointed out to me around this time that in Smalltalk everything really was an object (no boxing/unboxing necessary), including code blocks.
  28. LINQ - SQL is basically just functional programming.
  29. Lua - Everything can be a table! Sounds like JavaScript, but it is easier to embed.
  30. ML - When you only use patterns, you can write a lot of code much simpler.
  31. Lambda calculus - So this is where Lisp and functional programming came from.
  32. Scheme - Generating code at compile-time can be really easy. This is really easy to extend. Numerical handling can be done really well. Functions holding state is powerful. Continuations are neat, but I don't care.
  33. Frink - I never realized that units of measurement could be so sophisticated.
  34. Joy - That is the shortest code I have ever seen. This is the most under-rated language out there.
  35. Combinatory Logic (SKI-Calculus) - You don't need arguments, but can use combinators instead. This is to Joy what Lambda-calculus is to Lisp.
  36. Haskell - I wish I could make my code compile. The Haskell standard prelude, has got to be one of the most elegant libraries I have ever seen.
  37. Factor - There is so much cool stuff in there, I just wish I could be bothered to learn the syntax.
  38. K - Array (vector) based primitive operations are extremely powerful.
  39. Forth - This is like a super-powered high-level assembly. There is so much to learn though.
  40. Python - This is really readable stuff. It's like a combination of a bunch other languages.
  41. Erlang - Expressing programs as actors is a great way to express parallelism.
  42. Executable UML - Asynchronous message passing is a great way to express concurrent algorithms without having to think about threads.
  43. Ruby - Build systems (Rake) can be written in a real programming language. Code blocks can be data too (well technically I learned that with Scala).

So of course this list is far longer than you (or anyone else) would probably want. For maximum effect my short list would be: Scheme (or Lisp), Joy (or PostScript), Erlang, Eiffel, AspectJ, Erlang, ML, and Haskell. If you only want to focus on a couple of languages, and are willing to go into them in great depth, then you could get a lot out of mastering Scala or C#. There is of course probably still a thing or two you could learn from C++ 0x, especially if you push and prod it a bit.

cdiggins
wow, an even better answer.
ShaChris23
Amazing list. Surprised you haven't tried Ruby on Rails yet.
lkessler
I was going to say I haven't used Ruby, but then I remembered I did some hacking around with the Rake build system. So I went and added it to the list.
cdiggins
I would add C to the short list. The OP already knows C++, but that doesn't necessarily mean they know the C subset of C++, which is a rather important (IMHO) subset to learn. It's easy to "know" C++ and never have to use the C subset.
Chris Lutz
I would argue that if you don't fully know the C subset of C++, then you don't full know C++.
cdiggins
This is a nice list. Only one quibble: "Java - Everything can be an object". Not a very accurate description of Java. The built-in numeric types are very different from objects.
Daniel Earwicker
Earwicker: with autoboxing, the built-in numerics can act as objects.
jmucchiello
Well I kind of agree with Earwicker, that numerics act like objects (or get promoted to objects), but aren't actually objects themselves. I didn't learn that until afterwards (which seems to me that it was from Smalltalk programmers). When I first learned Java though it definitely looked like objects all the way down (esp. compared to C++).
cdiggins
I added some more comments regarding Java and Smalltalk. I think it is important to realize that when I learned Java my programming experience and understanding was relatively undeveloped. I also never really looked very closely at Smalltalk, but had a bunch of Smalltalk programmers try to teach me how great it was. :-)
cdiggins
@cdiggins: a followup question. Given that you have experimented (or used) that many languages, do you find that it actually helps you think of programming in C++ in a different way?
ShaChris23
Yes, but not as much as I had hoped. A long lesson I hard to learn was to not try and outsmart the language: writing simple idiomatic code is usually the best thing. A concrete example is functional programming in C++. While possible, it ends up being complex and hard for other programmers to maintain. However, I did learn to start writing simpler C++ code because of my experience with Python and Java. In the end I just got frustrated with the limitations of C++, and avoid it when possible (unless I need speed + platform independence).
cdiggins
+1  A: 

Ruby must be the one that makes me say "Cool look how you can do that" the most. But I have a new found fondness for JavaScript again.

Guy van den Berg
A: 

I'd recommend J (jsoftware.com), as I always do. It differs from most other languages in that it is symbolic (though the symbols are all rendered in plain ASCII) and functional. More importantly, it is dynamic, interactive, and it has a lot of high-level concepts built-in.

For instance, taking a cue from one of the other posts here, factorial in J is:

   !10
3628800

for, e.g. factorial 10. Extending this, to evaluate the number of 10 things taken 5 at a time:

   5!10
252

Arrays are first class objects, so factorial of 5, 10, and 15 is:

   !5 10 15
120 3628800 1.3076744e12

and the number of ways to take 3 things from 6, 8, and 10 things:

   3!6 8 10
20 56 120

A palindrome checker could be written

   palincheck=: 3 : '(]-:|.)tolower y-.'' '''

This matches (-:) against the "flip" (|.) the lower-cased argument without (-.) any spaces. Applying this to three arguments and returning "1" for true and "0" for false:

   palincheck&>'Able was I ere I saw Elba';'Step on no pets';'Not palindrome'
1 1 0

It's initially hard to get used to programming so succinctly at such an advanced level but you may find that it grows on you, especially if you like to try out ideas quickly.

DevonMcC
+1  A: 

I posted, above :

For instance, in Javascript :
button.onclick = function(){ some code }

And got this comment :

that button.onclick example was definitely cool. and it looks very intuitive too. thanks! – ShaChris23

I find this very interesting.

When you work in a low-level language like C++, you don't think about the things that are possible to do in a higher-level language.

ShaChris23 thinks like a C programmer discovering JavaScript : this is "cool". Which is true ! But a JavaScript programmer discovering C++ will think the reverse, like "how crude a language, I can't even add a method to a class at runtime !" and he'll be right, too.

For instance you'd use a Factory pattern, when a Python programmer will just put the class in a variable and pass it. Someone who never learnt anything besides C++ will not dream of that !

For instance, in Python I wrote a time-based scheduler, which was called like :

task_handle = scheduler.execute_at( time, function )

Using a closure for "function" makes this extremely powerful. Those that don't know the concept of "closure" can't think about this.

Learning new languages, even only learning the basic concepts, will make you a better programmer in all languages, because it will expand your perspective.

Even if you never use it, learn Lisp...

JavaScript is good too, it has strong functional prog genes !

I wish EVERYONE learnt at least Python.

Then no-one would ever write bug-ridden text manipulation in C, lol.

peufeu
thanks for the perspective peufeu. even the Factory pattern discussion you provided, to me, is thought-provoking. Lol, passing a class as a variable! man...that's awesome.
ShaChris23