digitalmars.D - Is D a cult?
- Jane Doe (1/1) Mar 05 2010 Is D a cult?
- Nick Sabalausky (4/5) Mar 05 2010 Yes. Send us all your worldly possesions. And try the kool-aid (I'll ref...
- Justin Johansson (3/4) Mar 06 2010 Did you mean occult?
- FeepingCreature (2/10) Mar 06 2010 The Power of Bright compels you! The Power of Bright compels you!
- Bane (2/5) Mar 06 2010 Compile Phobos backward to get the true message.
- div0 (14/21) Mar 06 2010 -----BEGIN PGP SIGNED MESSAGE-----
- Steve Teale (2/3) Mar 06 2010 No but seriously ...
- Chad J (2/5) Mar 06 2010 I think the word you are looking for is "hivemind" ;)
- BCS (6/8) Mar 06 2010 No, not yet. Walter hasn't figured out how to brain wash people over a n...
- Bane (3/20) Mar 07 2010 Blasphemy! Heretic!
- Lutger (7/24) Mar 07 2010 That's weird, I don't see this at all. Maybe you focus too much on one o...
- retard (48/97) Mar 07 2010 Uh, majority of the features? From http://www.digitalmars.com/d/2.0/
- Lutger (16/66) Mar 07 2010 Isn't this THE cornerstone of functional programming style???
- Walter Bright (22/37) Mar 07 2010 Andrei and Sean have shown how to do that nicely with existing language
- bearophile (26/36) Mar 07 2010 In this post I am *not* asking for new features in D, I just try to give...
- retard (61/106) Mar 07 2010 Really? I'd really like to see how this is done. Especially the nested
- BCS (7/40) Mar 07 2010 I'd rather the following over either:
- Nick Sabalausky (17/33) Mar 09 2010 Expanding on that:
- retard (16/55) Mar 09 2010 Your examples more or less suggest that you haven't used lists much. The...
- Nick Sabalausky (14/69) Mar 09 2010 Well, I wasn't really thinking about lists specifically. I realize I was...
- BCS (10/14) Mar 09 2010 The points you bring up I think support NOT adding this to D because the...
- Walter Bright (7/11) Mar 07 2010 I'll reply to your other points later, but this one bothers me. Neither
- retard (25/39) Mar 07 2010 guid=3D5755BF-43CF-4D47-A7EC-B60F6B536702
- Walter Bright (10/22) Mar 07 2010 My experience with shallow const (in C++) is that it's nearly useless.
- Simen kjaeraas (5/12) Mar 08 2010 I still remember my first reading about D const, and thinking
- Walter Bright (4/12) Mar 08 2010 I'm interested in what will happen with all these new languages adopting...
- James Iry (8/22) Mar 10 2010 I'm going to assume you meant "enforce" rather than "support" because bo...
- Andrei Alexandrescu (14/20) Mar 10 2010 Functional programming means (a) first-order functions, and (b)
- Henrik Huttunen (2/4) Mar 10 2010 Really? Maybe you meant higher-order functions or functions as first-cla...
- Andrei Alexandrescu (3/7) Mar 10 2010 Damn. "First class".
- James Iry (3/21) Mar 10 2010 Andrei Alexandrescu Wrote:
- Bernard Helyer (9/10) Mar 10 2010 I know nothing about FP, but isn't the statement 'does a language have
- Andrei Alexandrescu (13/23) Mar 10 2010 Mutation has always been seen as an awkward concession to efficiency by
- grauzone (6/11) Mar 10 2010 Language support is not strictly necessary to get the same effects as
- Andrei Alexandrescu (3/14) Mar 10 2010 That'll never work. The OS granularity is 4KB increments.
- grauzone (5/21) Mar 10 2010 Data this small you would simply copy. Because it's so small, copying
- Andrei Alexandrescu (4/24) Mar 10 2010 Trust me, that will never work anywhere close to satisfactory. It's even...
- grauzone (3/29) Mar 10 2010 Just saying "it won't work" is a bit empty. Do you happen to have any
- Andrei Alexandrescu (3/32) Mar 10 2010 I'd need to build a fair amount of background, which I don't have time f...
- grauzone (4/44) Mar 10 2010 I don't think you'd need large amounts of "background" for a short and
- Andrei Alexandrescu (3/47) Mar 10 2010 "That does not work."
- grauzone (2/54) Mar 10 2010
- Walter Bright (2/6) Mar 10 2010 You'd also have to transitively copy everything referenced.
- grauzone (12/19) Mar 10 2010 If that becomes a problem depends entirely from how the message passing
- Walter Bright (14/25) Mar 10 2010 If there's anything I've learned about language design, it's that if
- grauzone (2/5) Mar 11 2010 I didn't advocate sharing of mutable state.
- James Iry (7/36) Mar 10 2010 The Lisp and Scheme LANGUAGES don't limit mutability, though. In Scheme...
- Walter Bright (5/9) Mar 10 2010 So does C. The problem is, without compiler support, you have a very
- Walter Bright (11/19) Mar 07 2010 foo( v,
- BCS (5/26) Mar 07 2010 I think (from context in other strands) that the OP was referring to val...
- Walter Bright (2/4) Mar 07 2010 Value pattern matching is just a regular switch statement.
- retard (2/7) Mar 07 2010 So what types does the regular switch accept in D 2 ?
- bearophile (7/8) Mar 07 2010 It accepts all integral values, including all chars and true enums. It a...
- Walter Bright (2/10) Mar 07 2010 I already posted the way to do type pattern matching.
- BCS (17/32) Mar 07 2010 I think what retard was asking was what types are legal as the argument ...
- Walter Bright (7/25) Mar 07 2010 I've thought more than once about adding that, but it just seems
- retard (26/58) Mar 08 2010 I guess the point is just to unify many kinds of cases.
- Walter Bright (8/51) Mar 08 2010 I don't agree, because switching on integer values is commonplace, and
- retard (20/84) Mar 08 2010 The "correct" solution, multimethods or the visitor pattern, is sometime...
- Simen kjaeraas (16/31) Mar 08 2010 Which means that D supports array switches (untested code):
- BCS (4/9) Mar 08 2010 What about allowing switch on FP but only allowing CaseRangeStatements?
- Walter Bright (5/6) Mar 08 2010 Is there really a compelling use case for that?
- retard (48/73) Mar 07 2010 Ok, that's pretty good.
- Walter Bright (3/8) Mar 07 2010 You did mention in another post in this thread that you were concerned
- Nick Sabalausky (5/24) Mar 09 2010 That would also fit in very nicely with non-nullables and/or a system wh...
- retard (4/37) Mar 09 2010 Of course, a nullable type is just a simple sum type and pattern matchin...
- =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= (6/7) Mar 07 2010 ?: combined with some fun delegate thunks would be equivalent to
- Leandro Lucarella (9/12) Mar 07 2010 Is nice to see that at least now you recognize that tuples can use some
- Walter Bright (7/13) Mar 07 2010 There are significant technical problems with having functions return
- bearophile (5/6) Mar 07 2010 A possibly stupid question: isn't it enough to return a custom struct?
- Walter Bright (2/6) Mar 07 2010 No, because of the alignment mismatches with other uses of tuples.
- bearophile (4/5) Mar 07 2010 And I guess all the other uses of tuples can't be changed to this one? :...
- BCS (5/17) Mar 07 2010 What about passing an array of return location pointers as a hidden arg?...
- grauzone (3/11) Mar 08 2010 I don't understand, what does alignment have to do with such a high
- retard (5/17) Mar 08 2010 Indeed, to me the tuple is just an interface. The compiler is free to
- Walter Bright (8/20) Mar 08 2010 You can use a tuple to populate a struct with fields, and it's
- grauzone (8/30) Mar 08 2010 Again, I can't understand. Does the compiler rely that tuples have the
- bearophile (6/10) Mar 08 2010 It isn't.
- grauzone (10/26) Mar 08 2010 D2 is pretty much finalized now. The discussion (i.e. bikeshedding)
- Steven Schveighoffer (7/18) Mar 08 2010 Technically, the book is finalized. Any details of D2 that are not in t...
- Walter Bright (4/8) Mar 08 2010 That's only a small part of the reason why. The main reason is because
- Walter Bright (4/8) Mar 08 2010 A tuple and a struct composed of the same tuple should be interchangeabl...
- retard (7/18) Mar 08 2010 Where does this requirement come from? Is there some existing work on
- Denis Koroskin (2/20) Mar 08 2010 I can't agree more.
- Walter Bright (4/10) Mar 08 2010 The natural and efficient way to align function parameters on the stack
- KennyTM~ (2/12) Mar 09 2010 Since when did C has tuples?
- grauzone (23/33) Mar 08 2010 Sorry for being dense, but again: what does alignment have to do with
- Walter Bright (10/12) Mar 08 2010 alias TypeTuple!(char, int) TT;
- Michel Fortin (29/41) Mar 08 2010 I think a better way to explain it is that a struct having an align(x)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/5) Mar 07 2010 Welcome back! :) Have you started understanding C++ yet?
- Hamish McTavish (2/5) Mar 08 2010 Who you calling a cult?
- Michael Rynn (14/21) Mar 08 2010 http://en.wikipedia.org/wiki/Cult
- Tony Bernold (2/27) Mar 09 2010 I think you missed the English humour - its an old joke based on the the...
- Justin Johansson (5/20) Mar 09 2010 Help save the elephants, hippopotamuses, walruses, mammoths and narwhals
"Jane Doe" <JanisD comcast.net> wrote in message news:hmsvgc$iel$1 digitalmars.com...Is D a cult?Yes. Send us all your worldly possesions. And try the kool-aid (I'll refrain from saying that it's "to die for"...crap, too late).
Mar 05 2010
Jane Doe Wrote:Is D a cult?Did you mean occult? http://answers.yahoo.com/question/index?qid=20080701114449AAxUTtT
Mar 06 2010
On 06.03.2010 13:55, Justin Johansson wrote:Jane Doe Wrote:The Power of Bright compels you! The Power of Bright compels you!Is D a cult?Did you mean occult? http://answers.yahoo.com/question/index?qid=20080701114449AAxUTtT
Mar 06 2010
Jane Doe Wrote:Is D a cult?Compile Phobos backward to get the true message.
Mar 06 2010
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Bane wrote:Jane Doe Wrote:lol. Brilliant. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFLkqkMT9LetA9XoXwRAgQuAKCiuJ5CT5vZfLW6UpynKtIiG5BsSwCeK/kc 87iHo7qqyx4bwWxIbJFdufI= =e9cz -----END PGP SIGNATURE-----Is D a cult?Compile Phobos backward to get the true message.
Mar 06 2010
On Sat, 06 Mar 2010 01:16:12 -0600, Jane Doe wrote:Is D a cult?No but seriously ...
Mar 06 2010
Jane Doe wrote:Is D a cult?I think the word you are looking for is "hivemind" ;)
Mar 06 2010
Hello Jane,Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;b -- ... <IXOYE><
Mar 06 2010
retard Wrote:Sun, 07 Mar 2010 05:05:03 +0000, BCS wrote:Blasphemy! Heretic! Joke aside, you are right from your point of view. On the other hand, I feel there is always risk for a project to became a bloated mess if it tries to satisfy needs of too many people, so some form of authority is needed to trim request here and there. Is that authority flawless? Of course not. Some good features are missing, some bad are still here, I am getting bolder each day and executables are growing bigger with each version. Other thant that, it got it pretty right so far otherwise we wouldn't be here having this chat :DHello Jane,FWIW, I think there is a kernel of truth in the original claim. People tend to agree evey time Walter proposes a new feature such as built-in regexps - yes, they were removed shortly afterwards. But when bearophile or some retard propose some features from functional languages that are natural extensions to existing ones, everyone hates them and tells us to go back to our ivory towers.Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;b
Mar 07 2010
retard wrote:Sun, 07 Mar 2010 05:05:03 +0000, BCS wrote:That's weird, I don't see this at all. Maybe you focus too much on one or two negative comments? I also don't understand that you think D designers have a bias against functional programming, especially since the majority of the features that have been implemented the last years are heavily influenced by that style of programming.Hello Jane,FWIW, I think there is a kernel of truth in the original claim. People tend to agree evey time Walter proposes a new feature such as built-in regexps - yes, they were removed shortly afterwards. But when bearophile or some retard propose some features from functional languages that are natural extensions to existing ones, everyone hates them and tells us to go back to our ivory towers.Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;b
Mar 07 2010
Sun, 07 Mar 2010 14:12:14 +0100, Lutger wrote:retard wrote:Uh, majority of the features? From http://www.digitalmars.com/d/2.0/ features2.html:Sun, 07 Mar 2010 05:05:03 +0000, BCS wrote:That's weird, I don't see this at all. Maybe you focus too much on one or two negative comments? I also don't understand that you think D designers have a bias against functional programming, especially since the majority of the features that have been implemented the last years are heavily influenced by that style of programming.Hello Jane,FWIW, I think there is a kernel of truth in the original claim. People tend to agree evey time Walter proposes a new feature such as built-in regexps - yes, they were removed shortly afterwards. But when bearophile or some retard propose some features from functional languages that are natural extensions to existing ones, everyone hates them and tells us to go back to our ivory towers.Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;bopAssign can no longer be overloaded for class objects.nope Added pure keyword. [1]Extended enums to allow declaration of manifest constants.nopeAdded const/immutable structs, classes and interfaces.[1]Added const and immutable to IsExpressions.nopeAdded typeof(return) type specifier.[2]Added overloadable unary * operation as opStar().nopeFull closure support added.everyone else already has this very basic feature)Transformed all of string, wstring, and dstring into immutabledefinitions [1]Added Overload Sets for functions and templates.nopestd.math.sin, cos, tan are now evaluated at compile time if the argumentis a constant. nopeAdded C++ interface for 'plugins'.nopeChanged result type of IsExpression from int to bool.nopeAdded optional TemplateParameterList to IsExpression.nopeAdded warning when override is omitted.nopeAdded new syntax for string literals (delimited, heredoc, D tokens)nopeAdded __EOF__ tokennopeAdded D_Version2 predefined identifier to indicate this is a D version2.0 compiler nopeAdded .idup property for arrays to create immutable copies.[1]Added transitive const and immutable.in parameter storage class now means scope const. [1]class and struct invariant declarations now must have a ().nopeAdded isSame and compiles to __traits.nopeAdded ForeachRangeStatement(ZF expressions) can be considered a functional construct, but D2 foreach isn't really the same. Let's see what features I had in mind: - Algrebraic data types - Pattern matching (extension to enum/string/integer accepting switch) - Higher kinded types - Tuples (no auto-folding, real product types) - Built-in variants (real sum types) - Currying, lazy evaluation - Fusion optimizations (e.g. list and stream fusion) - Type classes - basic control constructs are expressions, not statements (e.g. unify if- then-else and : ? into a functional if-then-else) - better syntax for lambdas [1] if immutability is considered functional [2] if type inference is considered functional
Mar 07 2010
retard wrote:Sun, 07 Mar 2010 14:12:14 +0100, Lutger wrote:<snip>retard wrote:Uh, majority of the features? From http://www.digitalmars.com/d/2.0/ features2.html:Sun, 07 Mar 2010 05:05:03 +0000, BCS wrote:That's weird, I don't see this at all. Maybe you focus too much on one or two negative comments? I also don't understand that you think D designers have a bias against functional programming, especially since the majority of the features that have been implemented the last years are heavily influenced by that style of programming.Hello Jane,FWIW, I think there is a kernel of truth in the original claim. People tend to agree evey time Walter proposes a new feature such as built-in regexps - yes, they were removed shortly afterwards. But when bearophile or some retard propose some features from functional languages that are natural extensions to existing ones, everyone hates them and tells us to go back to our ivory towers.Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;bLet's see what features I had in mind: - Algrebraic data types - Pattern matching (extension to enum/string/integer accepting switch) - Higher kinded types - Tuples (no auto-folding, real product types) - Built-in variants (real sum types) - Currying, lazy evaluation - Fusion optimizations (e.g. list and stream fusion) - Type classes - basic control constructs are expressions, not statements (e.g. unify if- then-else and : ? into a functional if-then-else) - better syntax for lambdas [1] if immutability is considered functionalIsn't this THE cornerstone of functional programming style???[2] if type inference is considered functionalI don't see why. With 'majority of features' I meant the ones that have most impact or is spend the most effort on. Not just a count of checkboxes. A lot of those features you mention are either small or cleanup of the language. Remember that D is at heart not a functional language, so it's not surprising a lot of improvements are not of that nature. The const/immutable regime however and everything that connected to it (like referential transparency), has been the main focus of design. Furthermore, a lot of phobos is at least heavily inspired by functional programming ideas (map/reduce/curry/compose/variant, etc.). I'm not arguing with you about what feature set is good / bad / special or how it is implemented. Just saying that functional language ideas are being ignored is complete nonsense.
Mar 07 2010
retard wrote:Let's see what features I had in mind: - Algrebraic data typesstd.variant covers this.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.- Higher kinded typesDon't know what that is.- Tuples (no auto-folding, real product types)Tuples can be better, I agree.- Built-in variants (real sum types)std.variant works fine. Don't know how having them be built-in would improve things.- Currying, lazy evaluationAlready supports this.- Fusion optimizations (e.g. list and stream fusion)Andrei demonstrated how to do this neatly with ranges.- Type classesDon't know what this is.- basic control constructs are expressions, not statementsPerhaps, but I still think it's necessary for D do be a { } Algol-style language. Nevertheless, I've demonstrated how this can be simply done using existing features.(e.g. unify if-then-else and : ? into a functional if-then-else)What's the difference between ?: and functional if-then-else?- better syntax for lambdasThe lambda syntax is as good as it's going to get without throwing out a *lot* of syntax compatibility.[1] if immutability is considered functional [2] if type inference is considered functionalSeveral of your points are not, to my mind, fundamental issues of functional programming. To me, the foundations of FP are immutability, purity, and closures, which got a lot of attention. Most of your points are already supported by D, although not quite as conveniently as in many other languages.
Mar 07 2010
In this post I am *not* asking for new features in D, I just try to give few answers :-) I think most of those things are not fit for D, they require a different language, a different compiler, different programmers, and probably a different compiler writer too :-) (I think in D for example list comphrensions fit better). The problem is that I am not an expert on such things, so what I say is not fully reliable (and another smaller problem is that I am not always sure what retard meant). If you don't understand or you don't agree with something I write here please ask. Walter Bright:- Built-in variants (real sum types)<<std.variant works fine. Don't know how having them be built-in would improve things.<I think retard here meant something different from D variant type. I think he meant something like the type int|float or int|float|double. The type system then knows that a variable of such type can contain only an int or a float, and nothing else. So you can think of it as a tagged union. But it's not just a C tagged union, functional languages are able to manage such int|float type very well, for example accepting in the code only operators that are allowed on both types.- Fusion optimizations (e.g. list and stream fusion)<<Andrei demonstrated how to do this neatly with ranges.<I think Andrei was showing something different. You can think of Fusion optimization as a compiler optimization, done by good compilers of lazy functional languages :-) It's useful to remove some useless operations, and turn a certain not effient functional algorithm into something that runs fast. You can find something here: http://stackoverflow.com/questions/578063/what-is-haskells-stream-fusion (In my opinion D language is far from being in need of this optimization.)- Algrebraic data types<<std.variant covers this.<I am sorry, but std.variant has nothing to do with Algrebraic data types :-) (The words retard has used come from computer science still, but it's another dialect, of the functional programmers. So even things that sound similar can be quite different things). I have shown Algrebraic data types a little on this newsgroup once in the past. This page contains some information: http://en.wikipedia.org/wiki/Algebraic_data_type- Type classes<<Don't know what this is.<This page gives some basic information: http://en.wikipedia.org/wiki/Type_classes While you read that, keep in mind the difference between a Nominative type system like the D one, and a structural one like the one of Haskell: http://en.wikipedia.org/wiki/Nominative_type_system- Higher kinded types<<Don't know what that is.<This is quickly going into a mess. There are very few languages with those, maybe only Haskell and Scala. You can find some information here, but it's not easy read: http://en.wikipedia.org/wiki/Kind_%28type_theory%29 http://www.cs.kuleuven.be/~adriaan/files/higher.pdf I'll need few more years to start to start to digest some of this stuff. Bye, bearophile
Mar 07 2010
Sun, 07 Mar 2010 11:17:46 -0800, Walter Bright wrote:retard wrote:Really? I'd really like to see how this is done. Especially the nested matching of algebraic constructs, e.g. my_list match { case 1 :: 2 :: 3 :: tail => 123 :: tail } in D: if (list.getElemAt(0) == 1 && list.getElemAt(1) == 2 && list.getElemAt(2) == 3) { return list.new(123).append(list.range(3, list.length)); }Let's see what features I had in mind: - Algrebraic data typesstd.variant covers this.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.I should have mentioned this http://enfranchisedmind.com/blog/posts/post-functional-scala/ That guy argues that even Scala isn't really functional since it doesn't encourage point-free programming with ugly and verbose partial application & currying. Indeed, both Scala and D support lazy evaluation in various contexts.- Currying, lazy evaluationAlready supports this.I really doubt he optimizes those since it requires serious compile time graph rewriting - possible with e.g. expression templates, though.- Fusion optimizations (e.g. list and stream fusion)Andrei demonstrated how to do this neatly with ranges.This is a bit related to the discussion about collection properties some time ago. And c++0x concept maps..- Type classesDon't know what this is.Having functional core constructs often helps in writing immutable functional code. Instead of first declaring a mutable variable and then assigning it a value later, with functional constructs you can immediately assign the result without requiring a mutable temporary state, e.g. int a = null; switch(b) { case foo: a = something; ... default: a = something_else; } vs const immutable int a = switch(b) { case foo: something; ... default: something_else; } The problem with mutability here is that after the assignment the mutable state doesn't automatically change.- basic control constructs are expressions, not statementsPerhaps, but I still think it's necessary for D do be a { } Algol-style language. Nevertheless, I've demonstrated how this can be simply done using existing features.Nothing. But you don't need both constructs. ?: should be the default as it is more general. I'd like to know why the return value should be discarded in the more common case. I know there's C/C++/Java compatibility arguments, but the original decision was somewhat flawed. I've worked in companies where the review process disallows the use of ?: because it makes the code look amateurish or 'hacky'.(e.g. unify if-then-else and : ? into a functional if-then-else)What's the difference between ?: and functional if-then-else?need an explicit 'return'. The -> and => symbols are not used in D so I suppose it wouldn't be a big problem to extend the syntax with an expression returning lambda. After all, everything else is already there.- better syntax for lambdasThe lambda syntax is as good as it's going to get without throwing out a *lot* of syntax compatibility.There's the idealistic pure core in functional languages. Unfortunately no one really likes it because it's not that good for building practical programs. The features I mentioned above can be implemented with simple lambda expressions. The whole idea in many new functional language features is that they are straightforward to rewrite into lambdas. It's perfectly clear to me that no matter what you do, D won't become a functional language because the core runs on an imperative Turing machine. But the functional constructs can help building more readable[1] if immutability is considered functional [2] if type inference is considered functionalSeveral of your points are not, to my mind, fundamental issues of functional programming. To me, the foundations of FP are immutability, purity, and closures, which got a lot of attention. Most of your points are already supported by D, although not quite as conveniently as in many other languages.
Mar 07 2010
Hello retard,Sun, 07 Mar 2010 11:17:46 -0800, Walter Bright wrote:I'd rather the following over either: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]);retard wrote:Really? I'd really like to see how this is done. Especially the nested matching of algebraic constructs, e.g. my_list match { case 1 :: 2 :: 3 :: tail => 123 :: tail } in D: if (list.getElemAt(0) == 1 && list.getElemAt(1) == 2 && list.getElemAt(2) == 3) { return list.new(123).append(list.range(3, list.length)); }Let's see what features I had in mind: - Algrebraic data typesstd.variant covers this.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.The -> and => symbols are not used in D so I suppose it wouldn't be a big problem to extend the syntax with an expression returning lambda. After all, everything else is already there.While I'm not for it, how much harm would adding yet another form of the delegate expression cause? -- ... <IXOYE><
Mar 07 2010
"BCS" <none anon.com> wrote in message news:a6268ff10f2a8cc8c1b9f4d1252 news.digitalmars.com...Hello retard,Expanding on that: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]); if(list[2..4] == [10,11,12]) return new list(list[0..2], 200, list[4..$]); if(list[0..2] == [9,8]) return new list(100, list[3..$]); // Omit list[3] return list; Hmm. I'd rather something closer to this (purely hypothetical syntax, of course): return match(list) { case [1,2,3]~tail: 123~tail; case [a,b,10,11,12]~tail: [a,b]~200~tail; case [9,8]~tail: 100~tail[1..$]; default: list; }Really? I'd really like to see how this is done. Especially the nested matching of algebraic constructs, e.g. my_list match { case 1 :: 2 :: 3 :: tail => 123 :: tail } in D: if (list.getElemAt(0) == 1 && list.getElemAt(1) == 2 && list.getElemAt(2) == 3) { return list.new(123).append(list.range(3, list.length)); }I'd rather the following over either: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]);
Mar 09 2010
Tue, 09 Mar 2010 13:52:52 -0500, Nick Sabalausky wrote:"BCS" <none anon.com> wrote in message news:a6268ff10f2a8cc8c1b9f4d1252 news.digitalmars.com...Your examples more or less suggest that you haven't used lists much. The reason why list pattern matching usually works the way I showed is that it's a simple linked list with a unbound payload type. Some typical use cases are: - find out whether the list is nil - return the head and tail - return n first elements and the tail Everything else costs a lot. The syntax encourages the thinking that extracting values is rather expensive and you shouldn't re-evaluate them. Indexing is O(n). You also very very very rarely jump over elements on the list. Lists can also be infinite in lazy languages so [1..$] makes little sense. So the example was a bit misleading. But if you see how lists are implemented with algebraic types, you might also see how other structures like trees (list is a degenerated tree) are matched.Hello retard,Expanding on that: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]); if(list[2..4] == [10,11,12]) return new list(list[0..2], 200, list[4..$]); if(list[0..2] == [9,8]) return new list(100, list[3..$]); // Omit list[3] return list; Hmm. I'd rather something closer to this (purely hypothetical syntax, of course): return match(list) { case [1,2,3]~tail: 123~tail; case [a,b,10,11,12]~tail: [a,b]~200~tail; case [9,8]~tail: 100~tail[1..$]; default: list; }Really? I'd really like to see how this is done. Especially the nested matching of algebraic constructs, e.g. my_list match { case 1 :: 2 :: 3 :: tail => 123 :: tail } in D: if (list.getElemAt(0) == 1 && list.getElemAt(1) == 2 && list.getElemAt(2) == 3) { return list.new(123).append(list.range(3, list.length)); }I'd rather the following over either: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]);
Mar 09 2010
"retard" <re tard.com.invalid> wrote in message news:hn6c0p$875$1 digitalmars.com...Tue, 09 Mar 2010 13:52:52 -0500, Nick Sabalausky wrote:Well, I wasn't really thinking about lists specifically. I realize I wasn't clear on that, and probably should have renamed it "array" or something. I was just thinking about a much more general pattern matching construct, not just linked lists. Also, Andrei's pointed out in the past (convincingly, IMO) that a heavily list/head-and-tail type of thinking can lead to incorrect and suboptimal implementations (ie, the quicksort example). But, regardless of any of that, like I said, it was just hypothetical sample syntax. No more than a minute or two of thought put into it (hell, I can think of other problems with it right now). In fact, I was mainly just using it to point out that there's room for something much better than BCS's example."BCS" <none anon.com> wrote in message news:a6268ff10f2a8cc8c1b9f4d1252 news.digitalmars.com...Your examples more or less suggest that you haven't used lists much. The reason why list pattern matching usually works the way I showed is that it's a simple linked list with a unbound payload type. Some typical use cases are: - find out whether the list is nil - return the head and tail - return n first elements and the tail Everything else costs a lot. The syntax encourages the thinking that extracting values is rather expensive and you shouldn't re-evaluate them. Indexing is O(n). You also very very very rarely jump over elements on the list. Lists can also be infinite in lazy languages so [1..$] makes little sense. So the example was a bit misleading. But if you see how lists are implemented with algebraic types, you might also see how other structures like trees (list is a degenerated tree) are matched.Hello retard,Expanding on that: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]); if(list[2..4] == [10,11,12]) return new list(list[0..2], 200, list[4..$]); if(list[0..2] == [9,8]) return new list(100, list[3..$]); // Omit list[3] return list; Hmm. I'd rather something closer to this (purely hypothetical syntax, of course): return match(list) { case [1,2,3]~tail: 123~tail; case [a,b,10,11,12]~tail: [a,b]~200~tail; case [9,8]~tail: 100~tail[1..$]; default: list; }Really? I'd really like to see how this is done. Especially the nested matching of algebraic constructs, e.g. my_list match { case 1 :: 2 :: 3 :: tail => 123 :: tail } in D: if (list.getElemAt(0) == 1 && list.getElemAt(1) == 2 && list.getElemAt(2) == 3) { return list.new(123).append(list.range(3, list.length)); }I'd rather the following over either: if(list[0..3] == [1,2,3]) return new list(123, list[3..$]);
Mar 09 2010
Hello retard,Lists can also be infinite in lazy languages so [1..$] makes little sense. So the example was a bit misleading. But if you see how lists are implemented with algebraic types, you might also see how other structures like trees (list is a degenerated tree) are matched.The points you bring up I think support NOT adding this to D because there are so many cases that supporting them all in the language would get to messy. The most general case I think would work is, when the switch type is a user defined type, to allow any literal as the case labels as long as the switch type defines == for it and then require that the only one case compare as equals. With that requirement, the optimizer might be able to inline and fold a LOT of code in some cases. -- ... <IXOYE><
Mar 09 2010
retard wrote:It's perfectly clear to me that no matter what you do, D won't become a functional language because the core runs on an imperative Turing machine. But the functional constructs can help building more readableI'll reply to your other points later, but this one bothers me. Neither are fundamental to FP. I don't see how they can be considered as supporting functional programming. http://en.wikipedia.org/wiki/Scala_(programming_language)#Functional_programming http://www.25hoursaday.com/weblog/CommentView.aspx?guid=3D5755BF-43CF-4D47-A7EC-B60F6B536702
Mar 07 2010
Sun, 07 Mar 2010 14:52:09 -0800, Walter Bright wrote:retard wrote:#Functional_programmingIt's perfectly clear to me that no matter what you do, D won't become a functional language because the core runs on an imperative Turing machine. But the functional constructs can help building more readableI'll reply to your other points later, but this one bothers me. Neither are fundamental to FP. I don't see how they can be considered as supporting functional programming. http://en.wikipedia.org/wiki/Scala_(programming_language)http://www.25hoursaday.com/weblog/CommentView.aspx?guid=3D5755BF-43CF-4D47-A7EC-B60F6B536702 Agreed, D 2 is rather unique among imperative languages. I guess no other imperative language provides such a transitive const system. The lack of strong const types sometimes bites you. On the other hand Scala does provide a shallow form of immutability and some immutable data structures in the standard library. I don't know if D2 provides any built-in immutable data structures. I guess just wrapping a data structure in immutable() won't suffice since there are probably some state changing functions in the mutable implementation that need to copy when dealing with immutable values. expressing functional problems without too much verbosity. When the const system in D works, I guess it solves the other part of the problem. Too bad you can't have them all without resorting to pure functional languages. In the functional language community they have been spending much time on the opposite, to find ways to add mutability into referentially transparent programs. Some examples: http://www.haskell.org/haskellwiki/DDC http://cs.anu.edu.au/~Ben.Lippmeier/project/thesis/thesis-lippmeier- sub.pdf https://www.cs.tcd.ie/Edsko.de.Vries/pub/ MakingUniquenessTypingLessUnique.pdf
Mar 07 2010
retard wrote:On the other hand Scala does provide a shallow form of immutability and some immutable data structures in the standard library.My experience with shallow const (in C++) is that it's nearly useless. Most C++ code I've seen seems to rely on an implicit assumption of transitive const, but it isn't in the documentation and of course you don't know if it is upheld or not. This is not conducive to reliable FP.I don't know if D2 provides any built-in immutable data structures. I guess just wrapping a data structure in immutable() won't suffice since there are probably some state changing functions in the mutable implementation that need to copy when dealing with immutable values.Certainly, the D standard collection classes can improve, and they are being worked on.expressing functional problems without too much verbosity. When the const system in D works, I guess it solves the other part of the problem. Too bad you can't have them all without resorting to pure functional languages.Without transitive immutability and purity, it's like putting a frock on Schwarzenegger. That's why I've been so adamant about having transitive immutability in D. I don't agree with calling a language FP without it.
Mar 07 2010
Walter Bright <newshound1 digitalmars.com> wrote:retard wrote:I still remember my first reading about D const, and thinking 'What? Other const regimes aren't transitive? That's madness!' -- SimenOn the other hand Scala does provide a shallow form of immutability and some immutable data structures in the standard library.My experience with shallow const (in C++) is that it's nearly useless. Most C++ code I've seen seems to rely on an implicit assumption of transitive const, but it isn't in the documentation and of course you don't know if it is upheld or not. This is not conducive to reliable FP.
Mar 08 2010
Simen kjaeraas wrote:Walter Bright <newshound1 digitalmars.com> wrote:I'm interested in what will happen with all these new languages adopting FP window dressing and concurrent programming features, but with no immutability and no purity. They're building a house on sand.My experience with shallow const (in C++) is that it's nearly useless. Most C++ code I've seen seems to rely on an implicit assumption of transitive const, but it isn't in the documentation and of course you don't know if it is upheld or not. This is not conducive to reliable FP.I still remember my first reading about D const, and thinking 'What? Other const regimes aren't transitive? That's madness!'
Mar 08 2010
I'm going to assume you meant "enforce" rather than "support" because both languages support immutability and purity precisely to the extent that the programmers want to use them (although, of the two, Scala's standard library has far more support). But even if you mean "enforce", you've still got a strange point of view. Common Lisp and Scheme do not enforce purity or immutability. In fact, in both languages, ALL data structures are mutable whether you want them to be or not. Yet the Scheme crowd in particular is deeply aware of the downsides of side effects. SML and OCaml do not enforce purity or immutability except in a shallow sense that unlike (most) Lisps you can write data structures which are immutable. Scala sits firmly in that same camp. For instance, like SML, the Scala standard library List type is immutable (and persistent - meaning some operations, like prepend and tail, share structure with previous versions). To insist that functional programming must be done in a language that enforces purity is to say that nobody ever did functional programming in a Lisp or ML derived language. That's historically false and many of the core concepts found in Haskell (1999) and Miranda (1985) were clearly already worked out in ML(1973) and LISP(1958). It also ignores the fact that the current Scheme, OCaml, and, yes, Scala communities work hard to create and use high performance immutable, persistent data structures. What the purely functional languages really have brought to the table is a) clean ways to separate IO using things like linear types (Clean), monads(Haskell), or effect systems(Disciple) and b) a deep awareness of the power of laziness that can be found, to some extent, in the impure functional languages but which is pervasive in the pure lazy ones. Also, GHC Haskell, the current reigning king of purity includes "unsafePerformIO" precisely because there is such a thing as too much purity. Besides doing traditional IO it allows the programmer to mutate shared variables and do other, nasty, imperative things. Walter Bright Wrote:retard wrote:It's perfectly clear to me that no matter what you do, D won't become a functional language because the core runs on an imperative Turing machine. But the functional constructs can help building more readableI'll reply to your other points later, but this one bothers me. Neither are fundamental to FP. I don't see how they can be considered as supporting functional programming. http://en.wikipedia.org/wiki/Scala_(programming_language)#Functional_programming http://www.25hoursaday.com/weblog/CommentView.aspx?guid=3D5755BF-43CF-4D47-A7EC-B60F6B536702
Mar 10 2010
On 03/10/2010 10:09 AM, James Iry wrote:I'm going to assume you meant "enforce" rather than "support" because both languages support immutability and purity precisely to the extent that the programmers want to use them (although, of the two, Scala's standard library has far more support). But even if you mean "enforce", you've still got a strange point of view.Functional programming means (a) first-order functions, and (b) immutability. There are no ifs and buts about it. Every text on functional programming says as much. Even Wikipedia :o), but I'd recommend this classic: https://docs.google.com/viewer?url=http://www.cs.chalmers.se/~rjmh/Papers/whyfp.pdf The rest (lambdas, extensive use of recursion, pattern matching, let and letrec, monads, system(at)ic laziness) is aftermath, i.e. mechanisms that make it convenient to program given (a) and (b). There are no ifs and buts about that either. Giving FP lip service by adopting FP's window dressing and syntactic sugar while at the same time not giving due consideration to FP's two fundamental tenets is, in my opinion, an ungainly move in the long term. Andrei
Mar 10 2010
Andrei Alexandrescu Wrote:Functional programming means (a) first-order functions, and (b) immutability. There are no ifs and buts about it.Really? Maybe you meant higher-order functions or functions as first-class citizens?
Mar 10 2010
On 03/10/2010 11:48 AM, Henrik Huttunen wrote:Andrei Alexandrescu Wrote:Damn. "First class". AndreiFunctional programming means (a) first-order functions, and (b) immutability. There are no ifs and buts about it.Really? Maybe you meant higher-order functions or functions as first-class citizens?
Mar 10 2010
Andrei Alexandrescu Wrote: I don't disagree with you (except that you probably meant "first class" rather than "first order"). But that wasn't the question. The question was "does a language have to enforce purity in order to be a functional language" and the answer is that historically that has not been the case. The Lisp family (especially Scheme) and the ML family both have a rich tradition of purely functional programming without ever having the purity enforced. They did not "adopt the functional window dressing"; they invented it.Functional programming means (a) first-order functions, and (b) immutability. There are no ifs and buts about it. Every text on functional programming says as much. Even Wikipedia :o), but I'd recommend this classic: https://docs.google.com/viewer?url=http://www.cs.chalmers.se/~rjmh/Papers/whyfp.pdf The rest (lambdas, extensive use of recursion, pattern matching, let and letrec, monads, system(at)ic laziness) is aftermath, i.e. mechanisms that make it convenient to program given (a) and (b). There are no ifs and buts about that either. Giving FP lip service by adopting FP's window dressing and syntactic sugar while at the same time not giving due consideration to FP's two fundamental tenets is, in my opinion, an ungainly move in the long term. Andrei
Mar 10 2010
On 11/03/10 09:42, James Iry wrote:But that wasn't the question. The question was "does a language have to enforce purity in order to be a functional language" and the answer is that historically that has not been the case.I know nothing about FP, but isn't the statement 'does a language have to enforce $(PRECONDITION_X) in order to be a $(PARADIGM_LANGUAGE)' a fairly broad one? Can't most languages be programmed in such a way as to fulfill most paradigms through strict coding practices? I guess the question then becomes a question of degrees (Logical Programming in x86 assembly?), and as I said, I know nothing about FP, so I will deftly run away. Brave, brave Sir Robin...
Mar 10 2010
On 03/10/2010 02:42 PM, James Iry wrote:Andrei Alexandrescu Wrote: I don't disagree with you (except that you probably meant "first class" rather than "first order"). But that wasn't the question. The question was "does a language have to enforce purity in order to be a functional language" and the answer is that historically that has not been the case. The Lisp family (especially Scheme) and the ML family both have a rich tradition of purely functional programming without ever having the purity enforced. They did not "adopt the functional window dressing"; they invented it.Mutation has always been seen as an awkward concession to efficiency by functional languages, and limited to the maximum extent possible. LISP has commonly used a pure subset (see e.g. http://www-formal.stanford.edu/jmc/history/lisp/node3.html) for proving essentially everything there is to be proven regarding functional programming. There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on. Andrei
Mar 10 2010
Andrei Alexandrescu wrote:There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)
Mar 10 2010
On 03/10/2010 05:01 PM, grauzone wrote:Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments. AndreiThere's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)
Mar 10 2010
Andrei Alexandrescu wrote:On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)Andrei
Mar 10 2010
On 03/10/2010 06:06 PM, grauzone wrote:Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it. AndreiOn 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)
Mar 10 2010
Andrei Alexandrescu wrote:On 03/10/2010 06:06 PM, grauzone wrote:Just saying "it won't work" is a bit empty. Do you happen to have any arguments?Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it.On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)Andrei
Mar 10 2010
On 03/10/2010 06:47 PM, grauzone wrote:Andrei Alexandrescu wrote:I'd need to build a fair amount of background, which I don't have time for. AndreiOn 03/10/2010 06:06 PM, grauzone wrote:Just saying "it won't work" is a bit empty. Do you happen to have any arguments?Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it.On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)
Mar 10 2010
Andrei Alexandrescu wrote:On 03/10/2010 06:47 PM, grauzone wrote:I don't think you'd need large amounts of "background" for a short and precise answer. It's not rocket science either. Though you could simply say "I don't want to answer now".Andrei Alexandrescu wrote:I'd need to build a fair amount of background, which I don't have time for.On 03/10/2010 06:06 PM, grauzone wrote:Just saying "it won't work" is a bit empty. Do you happen to have any arguments?Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it.On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)Andrei
Mar 10 2010
On 03/10/2010 07:07 PM, grauzone wrote:Andrei Alexandrescu wrote:"That does not work." AndreiOn 03/10/2010 06:47 PM, grauzone wrote:I don't think you'd need large amounts of "background" for a short and precise answer.Andrei Alexandrescu wrote:I'd need to build a fair amount of background, which I don't have time for.On 03/10/2010 06:06 PM, grauzone wrote:Just saying "it won't work" is a bit empty. Do you happen to have any arguments?Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it.On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)
Mar 10 2010
Andrei Alexandrescu wrote:On 03/10/2010 07:07 PM, grauzone wrote:But it does!Andrei Alexandrescu wrote:"That does not work."On 03/10/2010 06:47 PM, grauzone wrote:I don't think you'd need large amounts of "background" for a short and precise answer.Andrei Alexandrescu wrote:I'd need to build a fair amount of background, which I don't have time for.On 03/10/2010 06:06 PM, grauzone wrote:Just saying "it won't work" is a bit empty. Do you happen to have any arguments?Andrei Alexandrescu wrote:Trust me, that will never work anywhere close to satisfactory. It's even useless to talk about it.On 03/10/2010 05:01 PM, grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.Andrei Alexandrescu wrote:That'll never work. The OS granularity is 4KB increments.There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on.Language support is not strictly necessary to get the same effects as immutable types, as far as multithreading is concerned: small data can be copied, and large data can be made read-only by OS syscalls. This just had to be in the message passing library. (As a bonus, it isn't possible to subvert these mechanisms just by casting.)Andrei
Mar 10 2010
grauzone wrote:Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.You'd also have to transitively copy everything referenced.
Mar 10 2010
Walter Bright wrote:grauzone wrote:If that becomes a problem depends entirely from how the message passing API (or whatever) is used*. And the only common case where this works really elegantly are strings. (But most strings are short and could be copied effortlessly.) On the contrary, frequently allocating immutable data on a shared heap just to transfer it to another thread isn't going to be very efficient either. You won't be able to go with a shared GC forever, because it SO doesn't scale with multiprocessing. * This stuff probably depends a lot on actual use cases. Did you or Andrei envision anything in this direction? I figure you thought about this much more than e.g. me, but I never hear any concrete things.Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.You'd also have to transitively copy everything referenced.
Mar 10 2010
grauzone wrote:Walter Bright wrote:If there's anything I've learned about language design, it's that if there is a capability, it will be used, and if there's a major problem with it, that will generate major complaints. The fact is, people *do* have major problems with concurrent programming. Sharing of mutable state is a large generator of these problems, and I don't think we can wish it away or blame the programmer. What transitive immutability offers is a guarantee. As programs become ever larger and more complicated, relying on individual programmer diligence and uncheckable conventions is less and less acceptable. For example, we're at the stage now where mainstream languages offer guarantees against buffer overflows. This is a huge win - just witness the $$$$$ the C shops spend on Coverity to desperately try and squeeze them out of their code.grauzone wrote:If that becomes a problem depends entirely from how the message passing API (or whatever) is used*.Data this small you would simply copy. Because it's so small, copying won't have negative performance impact. The OS approach can be used for large data (at least in the order of hundreds of KB) and immutable parts of the data segment.You'd also have to transitively copy everything referenced.
Mar 10 2010
Walter Bright wrote:The fact is, people *do* have major problems with concurrent programming. Sharing of mutable state is a large generator of these problems, and I don't think we can wish it away or blame the programmer.I didn't advocate sharing of mutable state.
Mar 11 2010
The Lisp and Scheme LANGUAGES don't limit mutability, though. In Scheme you can literally mutate any cons cell, for instance. It's the communities that have limited the mutation in their programs in part because the language makes it easy to do so. In ML you can define any data structure to be based on mutable Refs, yet SMLers are especially keen on maintaining as much purity as they can, and OCamlers are mostly so (not entirely though, OCamlers frequently care more about efficiency than their SML brethren). The article you link only talks about LISP up to 1.5 or so. It doesn't cover Common Lisp, which is the 800 pound gorilla of the Lisp family. I bring it up because a huge amount of Common Lisp code is deeply imperative: for some reason CLispers are less interested in the value of purity than Schemer's are, even thought their language is just about as suitable (ignoring the fact that the CL spec doesn't require tail call optmization since most CL implementations support it). You may be right that it's concerns about efficiency, but I'm not entirely sure that's true since even at the small scale CLers tend to use loops where Schemers use (just as efficient) tail call recursion (yes, CL doesn't mandate TCO, but all the major implementations that I know of support it). Look, I'm not arguing that uncontrolled side effects are "good." What I am arguing is very simple: the definition of functional language, as applied to the vast majority of functional programming languages, does not imply any form of proof of purity. Redefining it that way is just retronyming with no good purpose when there's already a perfectly useful phrase, "purely functional programming language," to cover the Mirandas, Haskells, Cleans, Agdas, and Epigrams of the world. As for your comment about concurrency, it's a funny image, but it's false, or at least overstated. Erlang, for instance, does not put limits on effects except in the narrow sense that mutation is more awkward to express than in typical imperative languages. Some people think that Erlang does not permit the sharing of mutable state, but that's not true at all. Erlang prevents the sharing of direct access to memory, but actors are (or at least can be) stateful and can be shared concurrently, and you can get exactly the same kinds of race conditions you get in more traditional "shared state" concurrency. The difference in the Erlang model and locks/variables model is really more a matter of granularity and the programmers thought process. I talk about the state model in Erlang here (http://james-iry.blogspot.com/2009/04/erlang-style-actors-are-all-about.html). The article even ends with an implementation of sharable mutable "variables" with get and set operations, and I follow up in another article with an implementation of a mutex lock. If Erlang did not permit sharing of mutable entities then it would be too limited to be useful - concurrency (as opposed to simple parallelism) is a side effect. There's a reason Haskell pushes all of its concurrency primitives (forkIO, MVars, STM commits) into the IO Monad while the less pernicious data-parallel extensions don't require effect tracking. Now, again, limiting the scope of impurity and mutation in a concurrent setting is probably more win than not. But that does not mean we need to change the definitions of "concurrent language" or "functional programming language" to preclude Erlang just because it has no such limitations. Andrei Alexandrescu Wrote:On 03/10/2010 02:42 PM, James Iry wrote:Andrei Alexandrescu Wrote: I don't disagree with you (except that you probably meant "first class" rather than "first order"). But that wasn't the question. The question was "does a language have to enforce purity in order to be a functional language" and the answer is that historically that has not been the case. The Lisp family (especially Scheme) and the ML family both have a rich tradition of purely functional programming without ever having the purity enforced. They did not "adopt the functional window dressing"; they invented it.Mutation has always been seen as an awkward concession to efficiency by functional languages, and limited to the maximum extent possible. LISP has commonly used a pure subset (see e.g. http://www-formal.stanford.edu/jmc/history/lisp/node3.html) for proving essentially everything there is to be proven regarding functional programming. There's one final nail in the coffin. In wake of concurrency, de jure immutability becomes a necessity, not a useful and desirable de facto convention. Adopting the window dressing but not the essence of FP by a concurrent language evokes to me a scene in the Marx Brothers: an otherwise impeccably-dressed gentleman who forgot to put his pants on. Andrei
Mar 10 2010
James Iry wrote:I'm going to assume you meant "enforce" rather than "support" because both languages support immutability and purity precisely to the extent that the programmers want to use them (although, of the two, Scala's standard library has far more support).So does C. The problem is, without compiler support, you have a very difficult time telling by visual inspection if code is functional or not. It's like turning off type checking in your C compiler. It still works, but it's really bug prone.
Mar 10 2010
retard wrote:Sun, 07 Mar 2010 11:17:46 -0800, Walter Bright wrote:foo( v, (int i) { writeln("I saw an int ", i); }, (string s) { writeln("I saw a string ", s); ), (Variant any) { writeln("I saw the default case ", any); } ); foo is a variadic template which takes its first argument, v, and attempts to match it with each delegate in turn. The first one that matches is executed. The matching is all done at compile time, of course, and the delegate can be inlined.retard wrote:Really? I'd really like to see how this is done.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.
Mar 07 2010
Hello Walter,retard wrote:I think (from context in other strands) that the OP was referring to value, not type, pattern matching.Sun, 07 Mar 2010 11:17:46 -0800, Walter Bright wrote:foo is a variadic template which takes its first argument, v, and attempts to match it with each delegate in turn. The first one that matches is executed. The matching is all done at compile time, of course, and the delegate can be inlined.retard wrote:Really? I'd really like to see how this is done.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.-- ... <IXOYE><
Mar 07 2010
BCS wrote:I think (from context in other strands) that the OP was referring to value, not type, pattern matching.Value pattern matching is just a regular switch statement.
Mar 07 2010
Sun, 07 Mar 2010 15:59:37 -0800, Walter Bright wrote:BCS wrote:So what types does the regular switch accept in D 2 ?I think (from context in other strands) that the OP was referring to value, not type, pattern matching.Value pattern matching is just a regular switch statement.
Mar 07 2010
retard:So what types does the regular switch accept in D 2 ?It accepts all integral values, including all chars and true enums. It accepts strings but not arrays. It doesn't accept floating point values, complex numbers (that are FP), structs, objects and associative arrays. Eventually support for arrays and structs too can be added, someone in the D Wish list has asked for those two things, but so far I haven't found a need for this. If D adds tagged structs, then switch can read their tag. Time ago I have thought about an opSwitch operator for structs/classes, that gets called by switch, but I haven had not enough need for something like this so far. So I have never asked for it. Bye, bearophile
Mar 07 2010
retard wrote:Sun, 07 Mar 2010 15:59:37 -0800, Walter Bright wrote:I already posted the way to do type pattern matching.BCS wrote:So what types does the regular switch accept in D 2 ?I think (from context in other strands) that the OP was referring to value, not type, pattern matching.Value pattern matching is just a regular switch statement.
Mar 07 2010
Hello Walter,retard wrote:I think what retard was asking was what types are legal as the argument for a switch? IIRC the list is: all the arithmetic types and the string types. The value pattern matching that is being asked for would allow just about anything that has a compile time literal syntax: void fn(int[] ar) { switch(ar) { case [1,2,3]: ... break; case [1,2,4]: ... break; case [1,3,2]: ... break; } } -- ... <IXOYE><Sun, 07 Mar 2010 15:59:37 -0800, Walter Bright wrote:I already posted the way to do type pattern matching.BCS wrote:So what types does the regular switch accept in D 2 ?I think (from context in other strands) that the OP was referring to value, not type, pattern matching.Value pattern matching is just a regular switch statement.
Mar 07 2010
BCS wrote:I think what retard was asking was what types are legal as the argument for a switch? IIRC the list is: all the arithmetic types and the string types. The value pattern matching that is being asked for would allow just about anything that has a compile time literal syntax: void fn(int[] ar) { switch(ar) { case [1,2,3]: ... break; case [1,2,4]: ... break; case [1,3,2]: ... break; } }I've thought more than once about adding that, but it just seems pointless. I've never run into a use case for it. If you do run into one, if (ar == [1,2,3]) ... else if (ar == [1,2,4]) ... else if (ar == [1,3,2]) ... will work just fine.
Mar 07 2010
Sun, 07 Mar 2010 22:05:19 -0800, Walter Bright wrote:BCS wrote:The same can be said about matching integer values:I think what retard was asking was what types are legal as the argument for a switch? IIRC the list is: all the arithmetic types and the string types. The value pattern matching that is being asked for would allow just about anything that has a compile time literal syntax: void fn(int[] ar) { switch(ar) { case [1,2,3]: ... break; case [1,2,4]: ... break; case [1,3,2]: ... break; } }I've thought more than once about adding that, but it just seems pointless. I've never run into a use case for it. If you do run into one, if (ar == [1,2,3]) ... else if (ar == [1,2,4]) ... else if (ar == [1,3,2]) ... will work just fine.if (ar == 1) ... else if (ar == 2) ... else if (ar == 3) ...I guess the point is just to unify many kinds of cases. class Foo class Bar : Foo { void doBarMethod() {} } class Bar2 : Foo { void doBar2Method() {} } if (cast(Bar)foo) (cast(Bar)foo).doBarMethod(); else if (cast(Bar2)foo) (cast(Bar2)foo).doBar2Method(); else writefln("Oh no!") foo match { case b: Bar => b.doBarMethod case b: Bar2 => b.doBar2Method case _ => println("Oh no!") } (1, (1,2)) match { case (1, (1, _)) => println("nice tuple") case _ => } def main(args: Array[Byte]) = args(0) match { case "-help" => println("Usage: ...") case "-moo" => println("moo") }
Mar 08 2010
retard wrote:I don't agree, because switching on integer values is commonplace, and switching on array literals pretty much never happens. (Note: switching on floating point values is worse than useless, as floating point computations rarely produce exact results, and supporting such a capability will give a false sense that it should work.)I've thought more than once about adding that, but it just seems pointless. I've never run into a use case for it. If you do run into one, if (ar == [1,2,3]) ... else if (ar == [1,2,4]) ... else if (ar == [1,3,2]) ... will work just fine.The same can be said about matching integer values:if (ar == 1) ... else if (ar == 2) ... else if (ar == 3) ...I guess the point is just to unify many kinds of cases. class Foo class Bar : Foo { void doBarMethod() {} } class Bar2 : Foo { void doBar2Method() {} } if (cast(Bar)foo) (cast(Bar)foo).doBarMethod(); else if (cast(Bar2)foo) (cast(Bar2)foo).doBar2Method(); else writefln("Oh no!")I have to say, if you find code written that way, you're doing OOP wrong.foo match { case b: Bar => b.doBarMethod case b: Bar2 => b.doBar2Method case _ => println("Oh no!") } (1, (1,2)) match { case (1, (1, _)) => println("nice tuple") case _ => } def main(args: Array[Byte]) = args(0) match { case "-help" => println("Usage: ...") case "-moo" => println("moo") }D already supports string switches.
Mar 08 2010
Mon, 08 Mar 2010 03:35:56 -0800, Walter Bright wrote:retard wrote:The "correct" solution, multimethods or the visitor pattern, is sometimes very expensive. They become very verbose when compared to simple pattern matching:I don't agree, because switching on integer values is commonplace, and switching on array literals pretty much never happens. (Note: switching on floating point values is worse than useless, as floating point computations rarely produce exact results, and supporting such a capability will give a false sense that it should work.)I've thought more than once about adding that, but it just seems pointless. I've never run into a use case for it. If you do run into one, if (ar == [1,2,3]) ... else if (ar == [1,2,4]) ... else if (ar == [1,3,2]) ... will work just fine.The same can be said about matching integer values:if (ar == 1) ... else if (ar == 2) ... else if (ar == 3) ...I guess the point is just to unify many kinds of cases. class Foo class Bar : Foo { void doBarMethod() {} } class Bar2 : Foo { void doBar2Method() {} } if (cast(Bar)foo) (cast(Bar)foo).doBarMethod(); else if (cast(Bar2)foo) (cast(Bar2)foo).doBar2Method(); else writefln("Oh no!")I have to say, if you find code written that way, you're doing OOP wrong.The OOP argument is false here. Sometimes OOP isn't the best way to describe declarative data. It surely allows you to implement this, but the cost is a much larger verbosity. The data type might be just a simple tagged union (in which case powerful optimizations can be used). Instead of writingfoo match { case b: Bar => b.doBarMethod case b: Bar2 => b.doBar2Method case _ => println("Oh no!") }enum node_type { sum_node, mul_node, ... } struct tree { node_type type; union { // bla bla } }you can automatically eliminate the boilerplate code with this higher level construct. It's also much safer - unions are known to be a security loophole when used carelessly. Also with instanceof/cast() you may need to cast twice unlike in the match expression above.I know that. The idea was to show how general pattern matching unifies the instanceof construct, integer switches, string switches and various kinds of algebraic data type manipulation such as tree/graph rewriting. It's a much more generalized construct in all possible ways - and very intuitive to use. Some of the beauty is lost when you read the example written in Scala, but e.g. in Haskell the pattern matching closely reflects the structure of the algebraic data type.(1, (1,2)) match { case (1, (1, _)) => println("nice tuple") case _ => } def main(args: Array[Byte]) = args(0) match { case "-help" => println("Usage: ...") case "-moo" => println("moo") }D already supports string switches.
Mar 08 2010
Walter Bright <newshound1 digitalmars.com> wrote:Which means that D supports array switches (untested code): switch( (string)foo ) { case (string)[1,2,3]: doSomething( ); case (string)[3,2,1]: doSomethingElse( ); } Might require some tweaking, but I believe this would work. Not saying it's a good idea, though. As for structs: switch ( foo.toHash( ) ) { case S(1,2,3).toHash( ): doSomething( ); case S(3,2,1).toHash( ): doSomethingElse( ); } If toHash is CTFE-able. Just as untested, and might not work at all. -- Simenfoo match { case b: Bar => b.doBarMethod case b: Bar2 => b.doBar2Method case _ => println("Oh no!") } (1, (1,2)) match { case (1, (1, _)) => println("nice tuple") case _ => } def main(args: Array[Byte]) = args(0) match { case "-help" => println("Usage: ...") case "-moo" => println("moo") }D already supports string switches.
Mar 08 2010
Hello Walter,(Note: switching on floating point values is worse than useless, as floating point computations rarely produce exact results, and supporting such a capability will give a false sense that it should work.)What about allowing switch on FP but only allowing CaseRangeStatements? -- ... <IXOYE><
Mar 08 2010
BCS wrote:What about allowing switch on FP but only allowing CaseRangeStatements?Is there really a compelling use case for that? I really think we need to focus on what is needed to be done, not what can be done. Otherwise we wind up with a huge boatload of features yet have an unuseful language.
Mar 08 2010
Sun, 07 Mar 2010 15:38:07 -0800, Walter Bright wrote:retard wrote:Ok, that's pretty good. Now let's see how the pattern matching in Scala works: val a = 42 val b = 123 // basic matching of values a match { case 1 => println("You gave 1") case 2 => // functionality for 2 case _ => println("The default case") } // matching & refs to symbols a match { case `b` => println("You gave 123-1=122") case b => println("You gave " + b) } trait Spiny class Animal class Rabbit extends Animal class Hedgehog extends Animal with Spiny class Bear extends Animal object Roger extends Rabbit object Yogi extends Bear // matching & subtyping def foo(a:Animal) = a match { case Roger => "guess who framed you?" case Yogi => "o hai" case h: Animal with Spiny => "Possibly a hedgehog" case _ => "Giving up" } // nested matches { case a :: b :: c => 1 }: (List[Int] => Int) class Expr case class Value[T](v: T) extends Expr case class SumExpr(l: Expr, r: Expr) extends Expr case class MulExpr(l: Expr, r: Expr) extends Expr case class NegExpr(e: Expr) extends Expr def foo(e:Expr) = e match { case MulExpr(SumExpr(NegExpr(Value(1)), NegExpr(Value(5))), Value(2)) => println("Imagine, this could be used for AST processing") case _ => // do nothing } { case <html><a>some link</a></html> => println("found a link inside the DOM") }: (scala.xml.Elem => Unit) I left out some of the more complex functionality, e.g. extractors and more complex higher kinded stuff..Sun, 07 Mar 2010 11:17:46 -0800, Walter Bright wrote:foo( v, (int i) { writeln("I saw an int ", i); }, (string s) { writeln("I saw a string ", s); ), (Variant any) { writeln("I saw the default case ", any); } ); foo is a variadic template which takes its first argument, v, and attempts to match it with each delegate in turn. The first one that matches is executed.retard wrote:Really? I'd really like to see how this is done.- Pattern matching (extension to enum/string/integer accepting switch)Andrei and Sean have shown how to do that nicely with existing language features.The matching is all done at compile time, of course, and the delegate can be inlined.I guess this tells a lot. No feature is added to D unless it can do something statically with zero runtime cost.
Mar 07 2010
retard wrote:You did mention in another post in this thread that you were concerned about optimization?The matching is all done at compile time, of course, and the delegate can be inlined.I guess this tells a lot. No feature is added to D unless it can do something statically with zero runtime cost.
Mar 07 2010
"retard" <re tard.com.invalid> wrote in message news:hn1717$24to$1 digitalmars.com...Having functional core constructs often helps in writing immutable functional code. Instead of first declaring a mutable variable and then assigning it a value later, with functional constructs you can immediately assign the result without requiring a mutable temporary state, e.g. int a = null; switch(b) { case foo: a = something; ... default: a = something_else; } vs const immutable int a = switch(b) { case foo: something; ... default: something_else; } The problem with mutability here is that after the assignment the mutable state doesn't automatically change.That would also fit in very nicely with non-nullables and/or a system where it's an error to read a var before it's statically known to have be written to (instead of default init values).
Mar 09 2010
Tue, 09 Mar 2010 13:58:45 -0500, Nick Sabalausky wrote:"retard" <re tard.com.invalid> wrote in message news:hn1717$24to$1 digitalmars.com...Of course, a nullable type is just a simple sum type and pattern matching works perfectly with algebraic types.Having functional core constructs often helps in writing immutable functional code. Instead of first declaring a mutable variable and then assigning it a value later, with functional constructs you can immediately assign the result without requiring a mutable temporary state, e.g. int a = null; switch(b) { case foo: a = something; ... default: a = something_else; } vs const immutable int a = switch(b) { case foo: something; ... default: something_else; } The problem with mutability here is that after the assignment the mutable state doesn't automatically change.That would also fit in very nicely with non-nullablesand/or a system where it's an error to read a var before it's statically known to have be written to (instead of default init values).They're better known as dataflow variables.
Mar 09 2010
On 03/07/2010 08:17 PM, Walter Bright wrote:What's the difference between ?: and functional if-then-else??: combined with some fun delegate thunks would be equivalent to functional if-then-else. like this: return x > y ? ({writeln(); return 6;})() : ({frobnicate_the_freezer; return 2;})();
Mar 07 2010
Walter Bright, el 7 de marzo a las 11:17 me escribiste:Is nice to see that at least now you recognize that tuples can use some improvement. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Just because you're paranoid, don't mean they're not after you.- Tuples (no auto-folding, real product types)Tuples can be better, I agree.
Mar 07 2010
Leandro Lucarella wrote:Walter Bright, el 7 de marzo a las 11:17 me escribiste:There are significant technical problems with having functions return tuples. The problem is that alignment for arguments passed as parameters is fundamentally different from that for struct fields. Having tuple returns, tuples as fields, and tuples as function arguments all conflict with each other over this.Is nice to see that at least now you recognize that tuples can use some improvement.- Tuples (no auto-folding, real product types)Tuples can be better, I agree.
Mar 07 2010
Walter Bright:There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct? D Tuples have another problem, that they don't nest, as Perl arrays. Can this be fixed? Bye, bearophile
Mar 07 2010
bearophile wrote:Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 07 2010
Walter Bright Wrote:No, because of the alignment mismatches with other uses of tuples.And I guess all the other uses of tuples can't be changed to this one? :-) Bye, a hopeless bearophile
Mar 07 2010
Hello Walter,bearophile wrote:What about passing an array of return location pointers as a hidden arg? That would allow the called function to do the assignment. -- ... <IXOYE><Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 07 2010
Walter Bright wrote:bearophile wrote:I don't understand, what does alignment have to do with such a high level construct?Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 08 2010
Mon, 08 Mar 2010 09:27:34 +0100, grauzone wrote:Walter Bright wrote:Indeed, to me the tuple is just an interface. The compiler is free to optimize as much as it wants. The operational semantics are quite natural. I hadn't really thought about the systems programming context, but it sounds bad if it breaks the low level bit order in some cases.bearophile wrote:I don't understand, what does alignment have to do with such a high level construct?Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 08 2010
grauzone wrote:Walter Bright wrote:You can use a tuple to populate a struct with fields, and it's interchangeable with manually populating the fields. You can also use a tuple to pass args to a function, and it's interchangeable with manually listing the args. But if you populate a struct with a tuple, then pass the struct as an arg, it is *not* interchangeable with manually listing the args, as the alignment is different.bearophile wrote:I don't understand, what does alignment have to do with such a high level construct?Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 08 2010
Walter Bright wrote:grauzone wrote:Again, I can't understand. Does the compiler rely that tuples have the same byte layout as structs or function arguments? I thought the compiler could just copy all fields. And the backend can already return multiple values, since it can return structs and static arrays. That aside, I'm also glad that you acknowledge that current tuples are not perfect and need improvement. It's probably already too late to fix them, but you could always introduce a second, proper tuple type.Walter Bright wrote:You can use a tuple to populate a struct with fields, and it's interchangeable with manually populating the fields. You can also use a tuple to pass args to a function, and it's interchangeable with manually listing the args. But if you populate a struct with a tuple, then pass the struct as an arg, it is *not* interchangeable with manually listing the args, as the alignment is different.bearophile wrote:I don't understand, what does alignment have to do with such a high level construct?Walter Bright:No, because of the alignment mismatches with other uses of tuples.There are significant technical problems with having functions return tuples.<A possibly stupid question: isn't it enough to return a custom struct?
Mar 08 2010
grauzone:That aside, I'm also glad that you acknowledge that current tuples are not perfect and need improvement.I agree.It's probably already too late to fix them,<It isn't.but you could always introduce a second, proper tuple type.<NO. Not even think about that. Two kinds of tuples in a language is beyond ugly. Bye, bearophile
Mar 08 2010
bearophile wrote:grauzone:D2 is pretty much finalized now. The discussion (i.e. bikeshedding) alone to determine how tuples are done right would take much longer than this.That aside, I'm also glad that you acknowledge that current tuples are not perfect and need improvement.I agree.It's probably already too late to fix them,<It isn't.The older kind of tuples would be deprecated. In 10 or 20 years, they could be removed from D completely. It is only needed for compatibility with older code and because it is in TDPL (which apparently is considered the specification of D2). In case TDPL has no dependencies on the "wrong" aspects of the current tuples, then this historic accident could be avoided.but you could always introduce a second, proper tuple type.<NO. Not even think about that. Two kinds of tuples in a language is beyond ugly.Bye, bearophile
Mar 08 2010
On Mon, 08 Mar 2010 07:51:31 -0500, grauzone <none example.net> wrote:bearophile wrote:Technically, the book is finalized. Any details of D2 that are not in the book are allowed to be changed. That is, as long as it doesn't conflict with what the book says, it can be changed. This is why a complete documentation of phobos is not in the book (parts are referenced, and those parts must remain frozen). -Stevegrauzone:D2 is pretty much finalized now. The discussion (i.e. bikeshedding) alone to determine how tuples are done right would take much longer than this.That aside, I'm also glad that you acknowledge that current tuples are not perfect and need improvement.I agree.It's probably already too late to fix them,<It isn't.
Mar 08 2010
Steven Schveighoffer wrote:That is, as long as it doesn't conflict with what the book says, it can be changed. This is why a complete documentation of phobos is not in the book (parts are referenced, and those parts must remain frozen).That's only a small part of the reason why. The main reason is because the book is huge. To do the standard library justice, it needs to be its own full size book.
Mar 08 2010
grauzone wrote:Again, I can't understand. Does the compiler rely that tuples have the same byte layout as structs or function arguments? I thought the compiler could just copy all fields. And the backend can already return multiple values, since it can return structs and static arrays.A tuple and a struct composed of the same tuple should be interchangeable. This doesn't work, because the alignment is different for different circumstances.
Mar 08 2010
Mon, 08 Mar 2010 04:42:48 -0800, Walter Bright wrote:grauzone wrote:Where does this requirement come from? Is there some existing work on some other language that tells one to implement it this way? A struct can have all kinds of aligments. The developer is able to choose this in a systems programming language. Implicit conversion from a tuple type to a arbitrary struct sounds like a flaw. Why are so many implicit conversions needed?Again, I can't understand. Does the compiler rely that tuples have the same byte layout as structs or function arguments? I thought the compiler could just copy all fields. And the backend can already return multiple values, since it can return structs and static arrays.A tuple and a struct composed of the same tuple should be interchangeable. This doesn't work, because the alignment is different for different circumstances.
Mar 08 2010
On Mon, 08 Mar 2010 15:49:01 +0300, retard <re tard.com.invalid> wrote:Mon, 08 Mar 2010 04:42:48 -0800, Walter Bright wrote:I can't agree more.grauzone wrote:Where does this requirement come from? Is there some existing work on some other language that tells one to implement it this way? A struct can have all kinds of aligments. The developer is able to choose this in a systems programming language. Implicit conversion from a tuple type to a arbitrary struct sounds like a flaw. Why are so many implicit conversions needed?Again, I can't understand. Does the compiler rely that tuples have the same byte layout as structs or function arguments? I thought the compiler could just copy all fields. And the backend can already return multiple values, since it can return structs and static arrays.A tuple and a struct composed of the same tuple should be interchangeable. This doesn't work, because the alignment is different for different circumstances.
Mar 08 2010
retard wrote:The natural and efficient way to align function parameters on the stack is different from aligning them for struct fields.This doesn't work, because the alignment is different for different circumstances.Where does this requirement come from?Is there some existing work on some other language that tells one to implement it this way?Yes, C.
Mar 08 2010
On Mar 9, 10 04:16, Walter Bright wrote:retard wrote:Since when did C has tuples?The natural and efficient way to align function parameters on the stack is different from aligning them for struct fields.This doesn't work, because the alignment is different for different circumstances.Where does this requirement come from?Is there some existing work on some other language that tells one to implement it this way?Yes, C.
Mar 09 2010
Walter Bright wrote:grauzone wrote:Sorry for being dense, but again: what does alignment have to do with this? This works flawlessly, although there are different alignments involved: import std.stdio; struct A { align(1): short a; int b; } struct B { short a; int b; } void main() { A x = A(1, 2); B y; y.tupleof = x.tupleof; writefln("%s", y); //printf B(1, 2) writefln("%s %s", A.b.offsetof, B.b.offsetof); //prints 2 4 } You can assign the tuple from type A to B, even though the fields have different alignments. Obviously, the actual tuple type has to be the same.Again, I can't understand. Does the compiler rely that tuples have the same byte layout as structs or function arguments? I thought the compiler could just copy all fields. And the backend can already return multiple values, since it can return structs and static arrays.A tuple and a struct composed of the same tuple should be interchangeable. This doesn't work, because the alignment is different for different circumstances.
Mar 08 2010
grauzone wrote:Sorry for being dense, but again: what does alignment have to do with this?alias TypeTuple!(char, int) TT; These declarations must be IDENTICAL: void foo(TT); void foo(char, int); struct S { TT t; } struct S { char t1; int t2; } This means that if you have an aggregate that is a tuple (and tuples are, of course, aggregates) you have an aggregate that needs one alignment in one context, and another alignment in another. It doesn't work.
Mar 08 2010
On 2010-03-08 06:37:55 -0500, Walter Bright <newshound1 digitalmars.com> said:grauzone wrote:I think a better way to explain it is that a struct having an align(x) instruction will have different alignment than a struct with no explicit alignment, so you can't easily pass the tuple without creating a different copy with a standard alignment. For instance: struct CustomAligned { align(2): byte a; short b; } struct DefaultAligned { byte a; short b; } tuple(byte, short) foo(); CustomAligned a; a.tupleof = foo(); // how does this work under the hood? DefaultAligned b; b.tupleof = foo(); // how does this work under the hood? I think a nice ABI for this would be to pass small tuples like the one above in registers. Bigger tuples would be returned the same way as a struct having default alignment. If you're copying the tuple to a struct with non-default alignment, like in the example above, then it's the caller's responsibility to allocate temporary space on the stack and move the values as needed afterward. This would make the non-default alignment case slower, but using non-default alignment is already bound to be slower for many things. Another option is to pass a hidden pointer to each member as BCS suggested. Though I suspect this would be slower when assigning to default-aligned structs. It's not an impossible problem, but indeed it's not as simple as returning a struct. Is there some other issues I missed? -- Michel Fortin michel.fortin michelf.com http://michelf.com/I don't understand, what does alignment have to do with such a high level construct?You can use a tuple to populate a struct with fields, and it's interchangeable with manually populating the fields. You can also use a tuple to pass args to a function, and it's interchangeable with manually listing the args. But if you populate a struct with a tuple, then pass the struct as an arg, it is *not* interchangeable with manually listing the args, as the alignment is different.
Mar 08 2010
Jane Doe wrote:Is D a cult?Welcome back! :) Have you started understanding C++ yet? Ali "real"
Mar 07 2010
Jane Doe Wrote:Is D a cult?Who you calling a cult?
Mar 08 2010
On Mon, 08 Mar 2010 06:57:00 -0500, Hamish McTavish wrote:Jane Doe Wrote:http://en.wikipedia.org/wiki/Cult Cult pejoratively refers to a group whose beliefs or practices could be, reasonably or unreasonably, considered strange. The term was originally used to denote a system of ritual practices. The narrower, derogatory sense of the word is a product of the 20th century, especially since the 1980s, and is a result of the anti-cult movement, which uses the term in reference to groups seen as authoritarian, exploitative and possibly dangerous. From this I would fairly safely conclude a group of Nerds interested in a programming language are incapable of being or becoming a cult. It would be so nice to be dangerous, but there appears to be no chance of that, apart from how we could have saved the world if only we were not so engrossed in this little part of it.Is D a cult?Who you calling a cult?
Mar 08 2010
Michael Rynn Wrote:On Mon, 08 Mar 2010 06:57:00 -0500, Hamish McTavish wrote:I think you missed the English humour - its an old joke based on the the miss-spelling of cult - just change one letter :-)Jane Doe Wrote:http://en.wikipedia.org/wiki/Cult Cult pejoratively refers to a group whose beliefs or practices could be, reasonably or unreasonably, considered strange. The term was originally used to denote a system of ritual practices. The narrower, derogatory sense of the word is a product of the 20th century, especially since the 1980s, and is a result of the anti-cult movement, which uses the term in reference to groups seen as authoritarian, exploitative and possibly dangerous. From this I would fairly safely conclude a group of Nerds interested in a programming language are incapable of being or becoming a cult. It would be so nice to be dangerous, but there appears to be no chance of that, apart from how we could have saved the world if only we were not so engrossed in this little part of it.Is D a cult?Who you calling a cult?
Mar 09 2010
retard Wrote:Sun, 07 Mar 2010 05:05:03 +0000, BCS wrote:Help save the elephants, hippopotamuses, walruses, mammoths and narwhals and say NO to ivory towers. Build them no more, live in them no more and please don't tell anybody to go back to them. Justin JohanssonHello Jane,FWIW, I think there is a kernel of truth in the original claim. People tend to agree evey time Walter proposes a new feature such as built-in regexps - yes, they were removed shortly afterwards. But when bearophile or some retard propose some features from functional languages that are natural extensions to existing ones, everyone hates them and tells us to go back to our ivory towers.Is D a cult?No, not yet. Walter hasn't figured out how to brain wash people over a newsgroup yet. However I think Andrei's working on it and Don should have a patch in time for TDPL going out ;b
Mar 09 2010