开发者

C++ programmer looking to broaden perspective

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 ca开发者_Python百科n 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!


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.


Python gave me the "so cool" reaction


For something truly different, try Lisp or Scheme.


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!


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.


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).


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++).


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 :)


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.


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.


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 !


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)) 
                    )
        )
   )
)


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.


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! :-)


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.


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.


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..


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜