[math-fun] languages & what is wrong with them continued....
The fact you can, with great effort, in C++ define a Vector type which checks array bounds, and you can with more-than-usual effort then use it, is WORTHLESS, because just one co-author, just once, in your entire zillion-line 500-file program, uses the obvious default array mechanism, and game over. (JA has drunk the kool-aid to such a great extent, he does not even see the stupidity anymore, & actually thinks this is the way it ought to be.) News flash: safety should not be "achievable with effort." It should be "the default." Unsafety should be what requires excess effort. The fact that so many people, including JA himself, are trying so so so hard for so so long -- years and years of their life expended -- to try to paper over such flaws in the C++ language, is not a sign that it is a great language. It is a sign that it was done wrong. Let us admit the obvious. And what I find even more incredibly astounding, is that he himself does not find this obvious. And yes, a <---> operator for swapping. RW Floyd suggested this in his Turing lecture about how bad languages were. Then the language guys proceeded to ignore him like usual, until we have now reached the point where people like JA actually think this must have been a joke. But I am serious. Commonly used important constructs, should be compact. It is a very simple principle. Language like PASCAL decided to write BEGIN and END everywhere that C just used { }. Very simple and obvious violation of very simple principle. Why? For what possible reason? I mean, were they just sadists? Because I can see absolutely no other reason for it.
How can a language reasonably include "machine language stuff"??? A (the?) point of C was to get CPU _independent_!
--Arggh. The point is: machines do things, and/or should. Some HLLs then try to prevent you from doing that. This is stupid. Correct move: Essentially every operation, which any current or future machine does or likely will/should provide in hardware, should be accessible in the HLL. If your machine does not have it, then that is what HLLs are for -- to emulate it via compilation to a suitable code fragment! If they do not, they they are handicapping not helping you, and they are handicapping not helping future progress because then the hardware designers will see no incentive to actually provide said hardware since "nobody uses it." Does any HLL take this correct attitude? Or does every single HLL take the wrong attitude? This is a huge disaster, and those who've drunk the kool-aid actually think this is the way it ought to be, they've become so wedged. It is so insane. On the bright side, I totally agree with some of the stuff math-funners have said, like Rokicki re SIMD, parallel, and memory/threads issues. Re some other stuff, like C++ templates, in fact my compile-time ideas would do that better. For example, suppose you wrote a SORT routine for int32's. You now want same sort routine but for int64's, int8's etc. OK just do #for( T in {int8, int32, int64} ){ SORT routine defined here using type T } and voila. Here #for is a for loop executed at compile time. You want a compile time language very much like the actual language albeit restricted in power (do not allow it to be turing undecidable whether it compiles... incidentally C++ fails that test and hence should have been dismissed right there; it actually is Turing undecidable whether your C++ program is valid C++, which is just a mind-boggling level of language-design incompetence and incredible testament to how crufty it is).
* Warren D Smith <warren.wds@gmail.com> [Apr 21. 2014 06:49]:
[...]
Re some other stuff, like C++ templates, in fact my compile-time ideas would do that better. For example, suppose you wrote a SORT routine for int32's. You now want same sort routine but for int64's, int8's etc. OK just do
#for( T in {int8, int32, int64} ){ SORT routine defined here using type T }
and voila. Here #for is a for loop executed at compile time. You want a compile time language very much like the actual language albeit restricted in power (do not allow it to be turing undecidable whether it compiles... incidentally C++ fails that test and hence should have been dismissed right there; it actually is Turing undecidable whether your C++ program is valid C++, which is just a mind-boggling level of language-design incompetence and incredible testament to how crufty it is).
template <typename Type> void sort_whatever(Type *x, int n) { ... } will sort any Type if all operations in the routine are defined for Type. And templates are not functions, the corresponding functions are generated at compile time. And then, it's all there, ready to go (again!): http://www.cplusplus.com/reference/algorithm/sort/ Best, jj
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
This is precisely the trouble with templates: you need to learn yet another language for what can be templated & what cannot. Adding in the C preprocessor, you now need to know 3 completely different languages in order to write these C++ programs. While there is a distinction between Lisp macros and Lisp functions, at least you can construct Lisp macros with standard Lisp functions. A huge fraction of templating could be eliminated with proper function closures and proper "inlining". For example, most modern Lisps are capable of inlining mapping functions which apply functions given as arguments to sequences of various kinds. The lambda calculus tells us how to do these things correctly, if we will only listen. At 10:24 PM 4/20/2014, Joerg Arndt wrote:
template <typename Type> void sort_whatever(Type *x, int n) { ... }
will sort any Type if all operations in the routine are defined for Type.
And templates are not functions, the corresponding functions are generated at compile time.
* Henry Baker <hbaker1@pipeline.com> [Apr 21. 2014 17:28]:
This is precisely the trouble with templates:
you need to learn yet another language for what can be templated & what cannot. Adding in the C preprocessor, you now need to know 3 completely different languages in order to write these C++ programs.
The basic concept is very easy to grasp: // A template function: template <typename Type> Type max(Type a, Type b) { if ( a>b ) return a; else return b; } // A template class: template <typename Type> struct two_things { Type a, b; /* ... */ }; See? Of course one can use templates to dispatch more than just "types", for example, allocators and algorithms. Programming this tends to be more interesting. However, _using_ the those things from the STL (standard template library) is not that hard. So "need to learn yet another language" may only be true when you do template meta programming. But anyone doing this should have a very good pain tolerance anyway.
While there is a distinction between Lisp macros and Lisp functions, at least you can construct Lisp macros with standard Lisp functions.
A huge fraction of templating could be eliminated with proper function closures and proper "inlining". For example, most modern Lisps are capable of inlining mapping functions which apply functions given as arguments to sequences of various kinds. The lambda calculus tells us how to do these things correctly, if we will only listen.
C++ now has lambdas 8^) Best, jj
[...]
C++ now has lambdas [where the closed variables must be properly identified, types may have to be identified, and one has to explicitly say for the closed variables whether they are captured by reference or by value]. Very elegant! Robert On Mon, Apr 21, 2014 at 7:45 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Henry Baker <hbaker1@pipeline.com> [Apr 21. 2014 17:28]:
This is precisely the trouble with templates:
you need to learn yet another language for what can be templated & what cannot. Adding in the C preprocessor, you now need to know 3 completely different languages in order to write these C++ programs.
The basic concept is very easy to grasp:
// A template function: template <typename Type> Type max(Type a, Type b) { if ( a>b ) return a; else return b; }
// A template class: template <typename Type> struct two_things { Type a, b; /* ... */ };
See?
Of course one can use templates to dispatch more than just "types", for example, allocators and algorithms. Programming this tends to be more interesting. However, _using_ the those things from the STL (standard template library) is not that hard.
So "need to learn yet another language" may only be true when you do template meta programming. But anyone doing this should have a very good pain tolerance anyway.
While there is a distinction between Lisp macros and Lisp functions, at least you can construct Lisp macros with standard Lisp functions.
A huge fraction of templating could be eliminated with proper function closures and proper "inlining". For example, most modern Lisps are capable of inlining mapping functions which apply functions given as arguments to sequences of various kinds. The lambda calculus tells us how to do these things correctly, if we will only listen.
C++ now has lambdas 8^)
Best, jj
[...]
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
* Marc LeBrun <mlb@well.com> [Apr 23. 2014 14:57]:
="Robert Smith" <quad@symbo1ics.com> C++ now has lambdas [...]. Very elegant!
Cool! Could you please show how to write Y-combinator?!
http://rosettacode.org/wiki/Y_combinator#C.2B.2B ... not that I have the faintest idea what this is even about.
[...]
The googles, they do nothing! Robert On Wed, Apr 23, 2014 at 6:57 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Marc LeBrun <mlb@well.com> [Apr 23. 2014 14:57]:
="Robert Smith" <quad@symbo1ics.com> C++ now has lambdas [...]. Very elegant!
Cool! Could you please show how to write Y-combinator?!
http://rosettacode.org/wiki/Y_combinator#C.2B.2B
... not that I have the faintest idea what this is even about.
[...]
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
On Wed, Apr 23, 2014 at 7:57 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Marc LeBrun <mlb@well.com> [Apr 23. 2014 14:57]:
="Robert Smith" <quad@symbo1ics.com> C++ now has lambdas [...]. Very elegant!
Cool! Could you please show how to write Y-combinator?!
http://rosettacode.org/wiki/Y_combinator#C.2B.2B
... not that I have the faintest idea what this is even about.
The Y combinator is one way to let you write recursive lambdas. -- Mike Stay - metaweta@gmail.com http://www.cs.auckland.ac.nz/~mike http://reperiendi.wordpress.com
I think he was referring to the C++, not the combinator. :) Robert On Wednesday, April 23, 2014, Mike Stay <metaweta@gmail.com> wrote:
On Wed, Apr 23, 2014 at 7:57 AM, Joerg Arndt <arndt@jjj.de <javascript:;>> wrote:
* Marc LeBrun <mlb@well.com <javascript:;>> [Apr 23. 2014 14:57]:
="Robert Smith" <quad@symbo1ics.com <javascript:;>> C++ now has lambdas [...]. Very elegant!
Cool! Could you please show how to write Y-combinator?!
http://rosettacode.org/wiki/Y_combinator#C.2B.2B
... not that I have the faintest idea what this is even about.
The Y combinator is one way to let you write recursive lambdas. -- Mike Stay - metaweta@gmail.com <javascript:;> http://www.cs.auckland.ac.nz/~mike http://reperiendi.wordpress.com
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com <javascript:;> http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
* Robert Smith <quad@symbo1ics.com> [Apr 24. 2014 14:09]:
I think he was referring to the C++, not the combinator. :)
Actually both, but foremost the combinator. I tried to get the gist of the things in the past and consistently failed. Best, jj
Robert
[...]
On Thu, Apr 24, 2014 at 6:21 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Robert Smith <quad@symbo1ics.com> [Apr 24. 2014 14:09]:
I think he was referring to the C++, not the combinator. :)
Actually both, but foremost the combinator. I tried to get the gist of the things in the past and consistently failed.
Lambdas are sometimes called "anonymous" functions because they don't have names. Without a name, it becomes tricky to do recursion. One idea is to write your code twice (what follows is javascript): ((f) => (n) => { if (n === 0) return 1 else return n * f(f)(n-1) }) ((f) => (n) => { if (n === 0) return 1 else return n * f(f)(n-1) }) This takes the first code block and applies it to the second one, and since f is bound to one of these code blocks, f(f) is the same as the code above. The Y combinator handles the duplication for you so you only have to write the code once. Of course, any modern language allows names for functions, so it's pretty much useless unless you're trying to explain some of the finer points of the Curry-Howard isomorphism. -- Mike Stay - metaweta@gmail.com http://www.cs.auckland.ac.nz/~mike http://reperiendi.wordpress.com
* Mike Stay <metaweta@gmail.com> [Apr 24. 2014 18:44]:
On Thu, Apr 24, 2014 at 6:21 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Robert Smith <quad@symbo1ics.com> [Apr 24. 2014 14:09]:
I think he was referring to the C++, not the combinator. :)
Actually both, but foremost the combinator. I tried to get the gist of the things in the past and consistently failed.
Lambdas are sometimes called "anonymous" functions because they don't have names. Without a name, it becomes tricky to do recursion. One idea is to write your code twice (what follows is javascript):
((f) => (n) => { if (n === 0) return 1 else return n * f(f)(n-1) }) ((f) => (n) => { if (n === 0) return 1 else return n * f(f)(n-1) })
This takes the first code block and applies it to the second one, and since f is bound to one of these code blocks, f(f) is the same as the code above.
Thanks! I do understand what you said and feel less dumb now. I wish the Wiki page would say something to that effect.
The Y combinator handles the duplication for you so you only have to write the code once. Of course, any modern language allows names for functions, so it's pretty much useless unless you're trying to explain some of the finer points of the Curry-Howard isomorphism.
The *what*? (don't try, I will not understand). Best regards, Joerg
-- Mike Stay - metaweta@gmail.com http://www.cs.auckland.ac.nz/~mike http://reperiendi.wordpress.com
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
On Thu, Apr 24, 2014 at 10:52 AM, Joerg Arndt <arndt@jjj.de> wrote:
* Mike Stay <metaweta@gmail.com> [Apr 24. 2014 18:44]:
The Y combinator handles the duplication for you so you only have to write the code once. Of course, any modern language allows names for functions, so it's pretty much useless unless you're trying to explain some of the finer points of the Curry-Howard isomorphism.
The *what*? (don't try, I will not understand).
Don't worry: it's a fancy name for an easy concept (though one with deep implications): logic has an interpretation in terms of types and programs. Let F denote the empty set, T denote the 1-element set, X -> Y denote the set of functions from the set X to the set Y, and ~= denote isomorphism. Then F -> F ~= T F -> T ~= T T -> F ~= F T -> T ~= T Boolean implication is a special case of the arrow type. It's why they both use the same symbol. Now think of a sets X and Y as being the set of values satisfying some propositions P and Q, respectively. A total program from X to Y is a constructive intuitionistic proof that P implies Q. The law of the excluded middle says P OR NOT(P) is TRUE. In intuitionistic logic, that translates to "either you have a proof of P or you have a proof of NOT(P)". That's clearly false: we have neither a proof nor disproof of Riemann's hypothesis, and Gödel showed there's no algorithm, in general, for supplying such a proof or disproof. So in intuitionistic logic, the law of the excluded middle doesn't hold. -- Mike Stay - metaweta@gmail.com http://www.cs.auckland.ac.nz/~mike http://reperiendi.wordpress.com
Well, Adam solved the recent surface puzzle with what is probably a "book proof" à la Erdős. (As well as a follow-up puzzle in a similar vein.) Here's one in a different vein. Puzzle: ------- It's well known that if you identify a (2D) the opposite edges of the square [0,1]x[0,1] by (x,0 ~ (x,1), and (0,y) ~ (1,y), 0 <= x,y <= 1, the result is a torus. Suppose instead you use the identification (x,0 ~ (x+.5,1), and (0,y) ~ (1,y+.5), 0 <= x,y <= 1, where addition is mod 1. QUESTION: Which surface does this result in? --Dan
participants (7)
-
Dan Asimov -
Henry Baker -
Joerg Arndt -
Marc LeBrun -
Mike Stay -
Robert Smith -
Warren D Smith