digitalmars.D - Ceylon language
- bearophile (135/135) Apr 13 2011 The first description of the Ceylon language, designed for business comp...
- Kagamin (7/38) Apr 13 2011 How will it work on this code?
-
bearophile
(6/20)
Apr 13 2011
Those Ordinal and Comparable
seem interfaces, and each of the... - Nick Sabalausky (10/40) Apr 13 2011 Eewww. Haxe is like that and it's nothing but a royal pain in the ass.
- Andrei Alexandrescu (14/40) Apr 13 2011 I think you'd be hasty. As Kagamin mentioned, this ad-hoc guarding works...
- bearophile (66/69) Apr 13 2011 There is no Ceylon implementation yet, and even its authors probably wil...
- bearophile (3/8) Apr 13 2011 And by the way, this is similar to the "manual" partial application of C...
- Walter Bright (5/9) Apr 13 2011 I don't know about Rust, but as we've discovered and discussed before, S...
- spir (69/127) Apr 14 2011 How to survive? Named args and default values somewhat mitigate this lac...
- Nick Sabalausky (28/89) Apr 14 2011 Oh absolutely. Haxe has nullable-primatives which really comes in handly...
- Pelle (7/13) Apr 15 2011 In my understanding they are, while related, distinct like so:
- Andrej Mitrovic (28/28) Apr 15 2011 I've recently made an attempt to make a curry alternative which can
- bearophile (10/15) Apr 15 2011 How do you give a void argument to a function, in D2? This doesn't work,...
- Andrej Mitrovic (10/10) Apr 15 2011 Here's a hardcoded example:
- David Nadlinger (78/86) Apr 16 2011 Correct me if I'm wrong, but might it be that you are conflating
- Andrej Mitrovic (4/4) Apr 15 2011 Oh and the reason I used a struct and opCall inside the template is
- KennyTM~ (8/26) Apr 15 2011 I don't see the point reviving the std.bind module*. In your case a new
- Dmitry Olshansky (5/38) Apr 15 2011 I absolutely agree, also creating delegate in place solves pretty much
- Lutger Blijdestijn (26/74) May 04 2011 partial application is getting a new function out of an existing one whe...
- bearophile (5/9) May 04 2011 A simple and good explanation.
- Cristi Cobzarenco (5/16) May 05 2011 Currying is well established name as well, especially for people coming ...
- Max Klyga (7/27) May 05 2011 Current implementation does not curry the function, it partialy applies ...
- bearophile (13/33) Apr 14 2011 Better to keep the language less perlish.
- spir (14/19) Apr 14 2011 Dunno C# at all.
- Jesse Phillips (4/6) Apr 14 2011 Really? You want this? I really like that a null array is equal to an em...
- Nick Sabalausky (7/12) Apr 14 2011 I've thought about that and I don't know how I feel about it. On one han...
- Kagamin (6/12) Apr 14 2011 In our project we use
- Nick Sabalausky (4/13) Apr 14 2011 My experience indicates it's hard to implement useful generics in C# at ...
- Bruno Medeiros (13/19) May 03 2011 Hum, I saw this Ceylon stuff posted on Slashdot, and I've finally gotten...
The first description of the Ceylon language, designed for business computing (for large teams developing multi-user applications) and meant to replace Java, from Red Hat, that will run on the Java Virtual Machine itself: http://blog.talawah.net/2011/04/gavin-king-unviels-red-hats-top-secret.html About the language (very slow download): http://www.qconbeijing.com/download/Gavin%20keynote.pdf About the its type system: http://www.qconbeijing.com/download/Gavin%20session.pdf Some of the Java things they are frustrated by: - non-typesafety of null values - the dangerous synchronized keyword - clumsy annotation syntax - verbose constructor syntax - all Java objects are semaphores?! - SE SDK overuses stateful (mutable) objects The following parts are from the PDF documents, plus few comments of mine. ------------- Ceylon does not support method overloading (or any other kind of overloading). ------------- If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages. ------------- Attributes and local variables are immutable by default. Assignable values must be annotated variable: variable Natural count := 0; ------------- A getter looks like a method without a parameter list: shared Natural currentValue { return count; } } Attributes are polymorphic. A subclass may override a superclass attribute. It may even override a simple attribute with a getter or vice versa! This means there is no need for explicit getter/setters until you are ready for them. This is nice. ------------- There is no new keyword: Counter c = Counter(); ------------- The local keyword may be used in place of a type for block-local declarations: local c = Counter(); ------------- Assignment to a variable value or attribute setter is done using the := operator. The = specifier is used only for specifying immutable values: shared assign currentValue { count := currentValue; } ------------- We may define a class method "by reference": void hello(String name) = hello; ------------- A method may declare multiple lists of parameters. The method body is executed after arguments have been supplied to all parameter lists: Float add(Float x)(Float y) { return x+y; } This is a kind of user defined and safe partial application, it's a cute idea. Providing arguments to just one parameter list produces a method reference: Float addOne(Float y) = add(1.0); Float three = addOne(2.0); (The point of all this is that we are able to provide all the functionality of first-class and higher-order functions without needing to resort to unnatural syntactic constructs inspired by the lambda calculus notation.) ------------- There is a Named argument syntax. They use it for a syntax trick: A named argument invocation is enclosed in braces, and non-vararg arguments are listed using the name=value; syntax. This seems one of the most peculiar and refined parts of the syntax of this language. See slides 34-37 in the first PDF. ------------- A class or interface satisfies zero or more interfaces shared class Character(Natural utf16) extends Object() satisfies Ordinal & Comparable<Character> { ... } The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types. ------------- The "actual" annotation specifies that a member refines a supertype member: shared class Character(Natural utf16) extends Object() satisfies Ordinal & Comparable<Character> { Natural nat = utf16; shared actual Comparison compare(T that) { return this.nat <=> that.nat; } The <=> operator is called "compare". It's just a shortcut for the method compare() of Comparable. ------------- Type narrowing, "Switching" by type Type narrowing is often frowned upon in object-oriented programming Unfortunately, Java exacerbates the problem: - the compiler does not inform us when addition of a new subtype breaks the list of cases Node<String> node = ... ; switch (node) case (is Leaf<String>) { leaf(node.value); } case (is Branch<String>) { branch(node.left, node.right); } else { somethingElse(node); } The compiler forces the switch statement to contain an else clause to handle other subtypes. ------------- Enumerated subtypes A class or interface may specify an explicitly enumerated list of subtypes. The functional programming community calls this an algebraic datatype: abstract class Node<T>(String name) of Branch<T> | Leaf<T> { ... } lass Leaf<T>(String name, T value) extends Node<T>(name) { ... } lass Branch<T>(String name, Node<T> left, Node<T> right extends Node<T>(name) { ... } The compiler validates that switch statements contain either an exhaustive list of possible subtypes or an else clause: Node<String> node = ... ; switch (node) case (is Leaf<String>) { leaf(node.value); } case (is Branch<String>) { branch(node.left, node.right); } ------------- A type may be covariant or contravariant in its type parameter. (Respectively in or out.): interface WeakReferenceGetter<out T> { shared formal T? get(T t); // Compile error: not covariant } interface WeakReferenceSetter<in T> { shared formal T set(T t); // Compile error: not contravariant } The compiler validates member signatures to check that the type really does respect the declared variance. This is way easier to understand than wildcard types in Java. Collections and variance: - An interface like List<T> should be covariant in T since we almost always want a List<String> to be a List<Object> - Therefore, we need to split operations which mutate the list to a separate interface OpenList<T> ------------- Bye, bearophile
Apr 13 2011
bearophile Wrote:String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible.How will it work on this code? String? name = process.args.first; myLibCustomEnforce(exists name); writeLine("Hello " name "!");A class or interface satisfies zero or more interfaces shared class Character(Natural utf16) extends Object() satisfies Ordinal & Comparable<Character> { ... } The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types.What does it mean?Node<String> node = ... ; switch (node) case (is Leaf<String>) { leaf(node.value); } case (is Branch<String>) { branch(node.left, node.right); } else { somethingElse(node); }Haha, finally properly scoped switch statement, but it goes java too much. Braces are required?
Apr 13 2011
Kagamin:How will it work on this code? String? name = process.args.first; myLibCustomEnforce(exists name); writeLine("Hello " name "!");If you want to implement the feature well, then the compiler has to manage a bit of type state too. The state of the type of the (here immutable) variable "name" before myLibCustomEnforce() is different from the state of the type of "name" after that call.Those Ordinal and Comparable<Character> seem interfaces, and each of them has a certain number of methods. If you use Ordinal | Comparable<Character> I persume the Character class must implement the methods of both interfaces (as in D), while with "&" you need to implement just the methods present in both interfaces. I don't have enough experience about this to tell how much useful this feature is. But it's not at the top of the things I look for.shared class Character(Natural utf16) extends Object() satisfies Ordinal & Comparable<Character> { ... } The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types.What does it mean?Haha, finally properly scoped switch statement, but it goes java too much. Braces are required?Ceylon is meant to be a very regular and safe language designed for not expert programmers too, so I presume they are required here. Bye, bearophile
Apr 13 2011
bearophile Wrote:Do you describe, how Ceylon can work hypotetically or how it actually works?How will it work on this code? String? name = process.args.first; myLibCustomEnforce(exists name); writeLine("Hello " name "!");If you want to implement the feature well, then the compiler has to manage a bit of type state too. The state of the type of the (here immutable) variable "name" before myLibCustomEnforce() is different from the state of the type of "name" after that call.
Apr 13 2011
On 04/13/2011 07:06 PM, bearophile wrote:Kagamin:Yo; and while you're at "typestating", extend the feature to any type (not only pointers). Denis -- _________________ vita es estrany spir.wikidot.comIf you want to implement the feature well, then the compiler has to manage a bit of type state too. The state of the type of the (here immutable) variable "name" before myLibCustomEnforce() is different from the state of the type of "name" after that call.How will it work on this code? String? name = process.args.first; myLibCustomEnforce(exists name); writeLine("Hello " name "!");
Apr 14 2011
"bearophile" <bearophileHUGS lycos.com> wrote in message news:io458e$elr$1 digitalmars.com...Ceylon does not support method overloading (or any other kind of overloading).Eewww. Haxe is like that and it's nothing but a royal pain in the ass.If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages.Yes, I'd *love* to see that in D, too.A method may declare multiple lists of parameters. The method body is executed after arguments have been supplied to all parameter lists: Float add(Float x)(Float y) { return x+y; } This is a kind of user defined and safe partial application, it's a cute idea. Providing arguments to just one parameter list produces a method reference: Float addOne(Float y) = add(1.0); Float three = addOne(2.0); (The point of all this is that we are able to provide all the functionality of first-class and higher-order functions without needing to resort to unnatural syntactic constructs inspired by the lambda calculus notation.)That really stikes me as a completly wrong way to do currying. Granted, I've never really used currying, but it seems it would only be appropriate for *outside* code to choose which to specify and not specify. Having the callee decide that seems to completely defeat the whole point. Although I guess it could be sometimes be useful as a really ugly hack to work around the lack of overloading.
Apr 13 2011
On 4/13/11 3:03 PM, Nick Sabalausky wrote:"bearophile"<bearophileHUGS lycos.com> wrote in message news:io458e$elr$1 digitalmars.com...I think you'd be hasty. As Kagamin mentioned, this ad-hoc guarding works straight against modularity. Also, without more details I can't really say, but if the type of the checked variable doesn't automagically change from T? to T inside the guarded code, a lot of subsequent uses (pass down to functions etc.) would have to repeat the check. Also, if the variable is reassigned it would have to change back the type from T to T?, which makes program understanding by both human and compiler (e.g. "do I need a test here?") a bitch. I'm highly skeptical of this feature in particular. I'm even more so because it's the kind of ad-hoc feature with many fuzzy corners that needs solid real-world validation, which... ("You can’t write code in the language just yet!") doesn't exist. AndreiCeylon does not support method overloading (or any other kind of overloading).Eewww. Haxe is like that and it's nothing but a royal pain in the ass.If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages.Yes, I'd *love* to see that in D, too.
Apr 13 2011
Kagamin:Do you describe, how Ceylon can work hypotetically or how it actually works?There is no Ceylon implementation yet, and even its authors probably will have to change some of their ideas during the implementation phase, so there is not much real about what I have written. I have just interpreted the first documents they have released. Sorry for not being sufficiently explicit about this. (From what I've seen in the development of Scala, the Java VM allows to create a first language implementation in a not so much time.) --------------------- Nick Sabalausky:That really stikes me as a completly wrong way to do currying. Granted, I've never really used currying, but it seems it would only be appropriate for *outside* code to choose which to specify and not specify.<Here we are talking about a special case of partial function application, it's not currying. I have used partial application in Haskell, and it's very nice and very handy. If you have a function foo(x,y), in Haskell you are able to write things like: map (foo 5) somelist foo5 = foo 5 map foo5 somelist map (5 +) [0 .. 10] Partial application is nice for template arguments too. This is a little Rosettacode task to use partial application: http://rosettacode.org/wiki/Partial_function_application The Task: - Create a function fs( f, s ) that takes a function, f( n ), of one value and a sequence of values s. - Function fs should return an ordered sequence of the result of applying function f to every value of s in turn. - Create function f1 that takes a value and retuns it multiplied by 2. - Create function f2 that takes a value and returns it squared. - Partially apply f1 to fs to form function fsf1( s ) - Partially apply f2 to fs to form function fsf2( s ) -Test fsf1 and fsf2 by evaluating them with s being the sequence of integers from 0 to 3 inclusive and then the sequence of even integers from 2 to 8 inclusive. The Haskell version is very very simple: fs f s = map f s f1 value = value * 2 f2 value = value ^ 2 fsf1 = fs f1 fsf2 = fs f2 main = do print $ fsf1 [0, 1, 2, 3] print $ fsf2 [0, 1, 2, 3] print $ fsf1 [2, 4, 6, 8] print $ fsf2 [2, 4, 6, 8] D has a partial applicator in std.functional, but I think it can't be used here, this is a not so good implementation: import std.stdio, std.algorithm, std.range; template fs(alias f) { auto fs(Range)(Range s) { return map!f(s); } } auto f1(T)(T x) { return x * 2; } auto f2(T)(T x) { return x * x; } void main() { alias fs!f1 fsf1; alias fs!f2 fsf2; auto d1 = iota(0, 4); writeln(fsf1(d1)); writeln(fsf2(d1)); auto d2 = iota(2, 9, 2); writeln(fsf1(d2)); writeln(fsf2(d2)); } The problems I see with unrestricted partial application as in Haskell are: - I see this feature as possible source of bugs. If you don't give all arguments you generate a function instead of a result. I am not sure of this. - In some situations it's not immediately easy to understand code and what it is doing. Ceylon is targeted to commercial applications, and they are clearly trying to design a simple language, much simpler than Haskell and simpler than D too. So I presume they have found a compromise between "wild" Haskell-style partial application and no partial application at all as in C/C++/Java. They let the person that write the function to define what partial applications are allowed. This explicit design is how some higher order functions in Phobos are designed. map!(to!string)([1, 2, 3]) works thanks to nested templates, this is a way to manually specify what partial application there is in the template arguments. I don't know if this Ceylon design is good, but it looks like an interesting idea that I have not seen before. ---------------------- Andrei:Also, without more details I can't really say, but if the type of the checked variable doesn't automagically change from T? to T inside the guarded code, a lot of subsequent uses (pass down to functions etc.) would have to repeat the check. Also, if the variable is reassigned it would have to change back the type from T to T?, which makes program understanding by both human and compiler (e.g. "do I need a test here?") a bitch.<I agree it's just a high level discussion, there are not enough details yet. It seems several new languages want to solve this problem. How and how well is to be seen. Bye, bearophile
Apr 13 2011
template fs(alias f) { auto fs(Range)(Range s) { return map!f(s); } }And by the way, this is similar to the "manual" partial application of Ceylon, just with a worse syntax. Bye, bearophile
Apr 13 2011
On 4/13/2011 2:14 PM, bearophile wrote:I agree it's just a high level discussion, there are not enough details yet. Rust. It seems several new languages want to solve this problem. How and how well is to be seen.a language with lofty goals that doesn't actually work and doesn't seem to have that it is valid and useful.
Apr 13 2011
On 04/13/2011 02:34 PM, bearophile wrote:------------- Ceylon does not support method overloading (or any other kind of overloading).How to survive? Named args and default values somewhat mitigate this lack, but still... I read (somewhere) this only for /operator/ overloading.------------- If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages.+++ But I guess optionality could, and should, extend to non-ref types; thus, null is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...} Also, they should reuse '?' to mean 'exists', possibly '!?' meaning the opposite: void f (int i?) { if (? i) doWithI(i); if (!? i) doWithoutI(); ... }------------- Attributes and local variables are immutable by default. Assignable values must be annotated variable: variable Natural count := 0;Immutability should be the default for locals (especialy params) in all languages. 'Natural' is great ;-)------------- A getter looks like a method without a parameter list: shared Natural currentValue { return count; } }goodAttributes are polymorphic. A subclass may override a superclass attribute. It may even override a simple attribute with a getter or vice versa! This means there is no need for explicit getter/setters until you are ready for them. This is nice.very good I often miss this in D. The fact that subtyping in D applies only to methods forces to add fake data members in supertypes (which are thus present in all subtypes...). I find this design crazy !!! Same note for mixins: why do they hold only methods? A "role" to be mixed-in often requires both data & methods.------------- There is no new keyword: Counter c = Counter();great! get rid of new in D as well coll = (new Coll(cap)).fill(data); ==> coll = Coll(cap).fill(data);------------- Assignment to a variable value or attribute setter is done using the := operator. The = specifier is used only for specifying immutable values: shared assign currentValue { count := currentValue; }If I understand you correctly, this is wrong. The operators should instead make distinct *creation* versus *change*: variable Natural count = 0; // create count := 3; // change local Natural i = 1; // cannot be changed------------- We may define a class method "by reference": void hello(String name) = hello;???------------- A method may declare multiple lists of parameters. The method body is executed after arguments have been supplied to all parameter lists: Float add(Float x)(Float y) { return x+y; } This is a kind of user defined and safe partial application, it's a cute idea. Providing arguments to just one parameter list produces a method reference: Float addOne(Float y) = add(1.0); Float three = addOne(2.0); (The point of all this is that we are able to provide all the functionality of first-class and higher-order functions without needing to resort to unnatural syntactic constructs inspired by the lambda calculus notation.)I don't get the diff between currying & partial app. And find this feature much complication for close to uselessness.------------- There is a Named argument syntax.A true programmer uses named args in half of all method calls; meaning, everywhere args' meanings are not absolutely obvious.They use it for a syntax trick: A named argument invocation is enclosed inbraces, and non-vararg arguments are listed using the name=value; syntax.This seems one of the most peculiar and refined parts of the syntax of this language. See slides 34-37 in the first PDF.examples?------------- A class or interface satisfies zero or more interfaces shared class Character(Natural utf16) extends Object() satisfies Ordinal& Comparable<Character> { ... } The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types.Too bad, they got it wrong, like D. Should instead rip Go interfaces, which are structural & implicite, while still fully compile-time type-safe: struct File inStream { ... void write (string s) {...}; } ... interface Writer { void write (string s); } File is *also* a Writer, thus one can call the following on a specimen of File: void formatWrite (Writer w, string s, string format) {...} More generally, any type can satisfy any number of interfaces, wherever and whenever they are defined (eg years after, in user code). The obligation of explicitely declaring interface satisfaction is both useless and blocking. Free interfaces even provide some kind of simple generics for free (like in above example). And there is no need for ... if (is(...)) or ... if (isWriter!T) =========================================== All in all, Ceylon looks like a very good imrovement. Too bad its base for imrovement is Java (there is no way to get light & flexible coding from there, you'd have to change everything ;-), and it's designed to run on the JVM. :-( Denis -- _________________ vita es estrany spir.wikidot.com
Apr 14 2011
"spir" <denis.spir gmail.com> wrote in message news:mailman.3497.1302788057.4748.digitalmars-d puremagic.com...On 04/13/2011 02:34 PM, bearophile wrote:Oh absolutely. Haxe has nullable-primatives which really comes in handly at times (it often prevents the need for a separate bool to keep track of). Only problem is that in Haxe, not only is nullable the default, but it doesn't even *have* any non-nullables at all, for any type.If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages.+++ But I guess optionality could, and should, extend to non-ref types; thus, null is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...}I don't get the diff between currying & partial app. And find this feature much complication for close to uselessness.I'm not certain either, but I *think* partial application is just like currying except there's some sort of arbitrary limitaion on what combination(s) of paramaters you can choose to specify or not specify. And that limitation is based purely on what order the function defines its parameters. So basically, my understanding is that partial application is an arbitrarily-gimped currying.I think Go's implicit interfaces are horrible. It's literally nothing more than duck-typing at compile time (ie, static duck-typing) and fully inherits duck-typing's downfalls (notably that it's sloppy and conflates name/signature with semantics - which is an entirely false connection). Of course, I guess this argument doesn't hold if you're a duck-typing fan ;)A class or interface satisfies zero or more interfaces shared class Character(Natural utf16) extends Object() satisfies Ordinal& Comparable<Character> { ... } The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types.Too bad, they got it wrong, like D. Should instead rip Go interfaces, which are structural & implicite, while still fully compile-time type-safe: struct File inStream { ... void write (string s) {...}; } ... interface Writer { void write (string s); } File is *also* a Writer, thus one can call the following on a specimen of File: void formatWrite (Writer w, string s, string format) {...} More generally, any type can satisfy any number of interfaces, wherever and whenever they are defined (eg years after, in user code). The obligation of explicitely declaring interface satisfaction is both useless and blocking. Free interfaces even provide some kind of simple generics for free (like in above example). And there is no need for ... if (is(...)) or ... if (isWriter!T)Too bad its base for imrovement is Java (there is no way to get light & flexible coding from there, you'd have to change everything ;-),Yup. This is one of the reasons I don't buy the claims of "Java's fast now, really!". In fact, the article I'm [trying to] write for the article competition relates to this. Basically, code can't be fast *and* flexible *and* maintable without real metaprogramming (and class-based generics don't count), and Java AFAIK just doesn't have metaprogramming. Although I suppose you might be able to hack it by using a pre-processor, but pre-processors have their downsides. And even if you did use one, Java's requirement that every aggregate type be a class can be a real hinderance. Of course, the JVM's advanced class/object optimizations may be able to help - but only to a point, and you still can't reliably prevent situations that would hinder the JVM's ability to do the necessary optimizations.
Apr 14 2011
On 04/15/2011 03:23 AM, Nick Sabalausky wrote:I'm not certain either, but I *think* partial application is just like currying except there's some sort of arbitrary limitaion on what combination(s) of paramaters you can choose to specify or not specify. And that limitation is based purely on what order the function defines its parameters. So basically, my understanding is that partial application is an arbitrarily-gimped currying.In my understanding they are, while related, distinct like so: int foo(int x, int y, int z); int delegate(int, int) p = partiallyApply(&foo, 3); int delegate(int) delegate(int) delegate(int) c = curry(&foo); assert (p(4,5) == foo(3,4,5)); assert (c(3)(4)(5) == foo(3,4,5));
Apr 15 2011
I've recently made an attempt to make a curry alternative which can take any number of parameters (currently the curry implementation only works with 1 parameter). I've put my implementation in bugzilla, it is extremely simple (and maybe buggy :p) http://d.puremagic.com/issues/show_bug.cgi?id=5829. I've also tried to create a some sort of 'bind' function which could let you bind arguments to specific parameters of a function. If I had it working it would really help (me) out in coding for e.g. the Windows API. For example you might have a WinAPI function such as (I'm pseudocoding here): CreateWindow(int x, int y, int w, int h, int* opt1, int* opt2, int* opt3, char* name); And if you want to create a certain type of window with some parameters which are always the same, you could create an alias that binds certain arguments to this function: alias bind!CreateWindow(void, void, width, height, null, null, null, void) myWindow; Here 'void' would designate arguments that you would have to fill in when calling myWindow. You would call it like: myWindow(posX, posY, "MyWindowName"); which would translate the call to: CreateWindow(posX, posY, width, height, null, null, null, "MyWindowName"); WinAPI is full of functions which take optional parameters which need to be set to null if they're not to be used, so this kind of 'bind' function could be pretty useful. But I've had zero luck with CTFE and templates. Perhaps Don's upcoming CTFE revamp could make this possible.
Apr 15 2011
Andrej Mitrovic:alias bind!CreateWindow(void, void, width, height, null, null, null, void) myWindow;How do you give a void argument to a function, in D2? This doesn't work, despite having templated void arguments seems potentially useful: void foo(T)(T x) {} void bar() {} void main() { foo(bar()); }But I've had zero luck with CTFE and templates. Perhaps Don's upcoming CTFE revamp could make this possible.Don has changed mostly how CT functions manage their memory. Bye, bearophile
Apr 15 2011
Here's a hardcoded example: http://codepad.org/klr8S1hi I've tried numerous ways of automatically creating the appropriate call to fun in the bind template, but I've been unsuccessful. Maybe using some form of string mixin would work.. My biggest issue is that I can't modify variables at compile time. I wish there was some special CTFE int type which is only visible at compile-time and which we can use however we want. That way I could keep count of things, for example I could generate a list of indexes that can then be mixed in as a string.
Apr 15 2011
On 4/15/11 8:19 PM, Andrej Mitrovic wrote:[…] My biggest issue is that I can't modify variables at compile time. I wish there was some special CTFE int type which is only visible at compile-time and which we can use however we want. That way I could keep count of things, for example I could generate a list of indexes that can then be mixed in as a string. […] I dunno, CTFE overall seems like a buggy thing where I have to guesswhether something will work or not. It's very stress-inducing.Correct me if I'm wrong, but might it be that you are conflating templates and CTFE, which are – although they are both used for metaprogramming – two entirely different concepts? Maybe it helps to think of calling a function at compile time as a gate into a parallel universe. In this other world, you can modify variables, call functions, etc. as you please, just as if you were executing code at runtime (well, inside the more or less implementation-defined boundaries of CTFE). The only restriction is that you can only return a single value through the gate, there is no other way to influence the »compiler« universe from inside the functions you call. More specifically, there is no way to manipulate types in the compiler universe – although you can instantiate templates in CTFE functions just like normal, you will never be able to »return« them back to the outside world. Also, be aware of the fact that a CTFE function can just work on _values_, like every other runtime function, not on types. So much for CTFE. Templates, on the other hand, are basically just named scopes with a few extra features which happen to make a Turing complete language. As such, there will never be something like a runtime variable modifiable at compile time in templates, as you asked (at least I hope so). The interesting thing about templates is that they allow you to work with types themselves. Due to the absence of mutable state, you are generally limited to functional techniques, though, which can be uncomfortably similar to the proverbial Turing tarpit in some cases (although it's surprising how easy it is to write certain algorithms in a functional manner once you got the hang of it). However, there are ways to combine templates and CTFE to your advantage. Without any concrete question, it's obviously hard to give a good suggestion, but an example would be to use template functions called at compile time to produce string mixins: --- string generateCode(T...)() { string code; [… construct a string containing some declarations …] return code; } template Foo(T...) { alias DoSomethingWithATypeTuple!(T) U; mixin(generateCode(U)); } --- You can also shorten this by using delegate literals: --- template Foo(T...) { alias DoSomethingWithATypeTuple!(T) U; mixin({ […] return "<some code generated while having access to T and U>"; }()); } --- Another small template metaprogramming example showing a way to process a list of types without needing mutable state. Specifically, it aliases a new type tuple to Result which doesn't contain any items where Exp.numerator is 0 (you can do the same with eponymous templates). TypeTuples are automatically flattened, which allows for a concise implementation here. --- template Process(T...) { static if (T.length == 0) { alias TypeTuple!() Result; } else { alias T[0] A; static if (A.Exp.numerator == 0) { alias Process!(T[1..$]).Result Result; } else { alias TypeTuple!(A, Process!(T[1..$]).Result) Result; } } } --- As for constructing lists of indices and then generating code of them: If you need to work on types for generating the list, you could e.g. use some recursive template to construct a type tuple of integer literals (that name really doesn't fit well), and then process it via CTFE to generate code to be mixed in – or whatever you need in your specific case. Feel free to ask about any specific problems in d.D.learn. David
Apr 16 2011
Oh and the reason I used a struct and opCall inside the template is because this somehow allowed me to use foreach for some things. I dunno, CTFE overall seems like a buggy thing where I have to guess whether something will work or not. It's very stress-inducing.
Apr 15 2011
On Apr 16, 11 00:29, Andrej Mitrovic wrote:I've also tried to create a some sort of 'bind' function which could let you bind arguments to specific parameters of a function. If I had it working it would really help (me) out in coding for e.g. the Windows API. For example you might have a WinAPI function such as (I'm pseudocoding here): CreateWindow(int x, int y, int w, int h, int* opt1, int* opt2, int* opt3, char* name); And if you want to create a certain type of window with some parameters which are always the same, you could create an alias that binds certain arguments to this function: alias bind!CreateWindow(void, void, width, height, null, null, null, void) myWindow; Here 'void' would designate arguments that you would have to fill in when calling myWindow. You would call it like: myWindow(posX, posY, "MyWindowName"); which would translate the call to: CreateWindow(posX, posY, width, height, null, null, null, "MyWindowName");I don't see the point reviving the std.bind module*. In your case a new function name 'myWindow' needs to be defined, which makes it easier to just create a wrapper function auto myWindow(int x, int y, char* name) { return CreateWindow(x, y, width, height, null, null, null, name); } *: http://www.digitalmars.com/d/2.0/phobos/std_bind.html
Apr 15 2011
On 15.04.2011 22:24, KennyTM~ wrote:On Apr 16, 11 00:29, Andrej Mitrovic wrote:I absolutely agree, also creating delegate in place solves pretty much all of std.bind use cases. -- Dmitry OlshanskyI've also tried to create a some sort of 'bind' function which could let you bind arguments to specific parameters of a function. If I had it working it would really help (me) out in coding for e.g. the Windows API. For example you might have a WinAPI function such as (I'm pseudocoding here): CreateWindow(int x, int y, int w, int h, int* opt1, int* opt2, int* opt3, char* name); And if you want to create a certain type of window with some parameters which are always the same, you could create an alias that binds certain arguments to this function: alias bind!CreateWindow(void, void, width, height, null, null, null, void) myWindow; Here 'void' would designate arguments that you would have to fill in when calling myWindow. You would call it like: myWindow(posX, posY, "MyWindowName"); which would translate the call to: CreateWindow(posX, posY, width, height, null, null, null, "MyWindowName");I don't see the point reviving the std.bind module*. In your case a new function name 'myWindow' needs to be defined, which makes it easier to just create a wrapper function auto myWindow(int x, int y, char* name) { return CreateWindow(x, y, width, height, null, null, null, name); } *: http://www.digitalmars.com/d/2.0/phobos/std_bind.html
Apr 15 2011
Nick Sabalausky wrote:"spir" <denis.spir gmail.com> wrote in message news:mailman.3497.1302788057.4748.digitalmars-d puremagic.com...partial application is getting a new function out of an existing one where one of the arguments is fixed / bound. More or less what std.functional curry does, confusingly. currying however doesn't involve specifying parameters at all, it means to get a function with one parameter out of a function with more than one parameter. This new function returns a function with one parameter, and so on and so forth until there is nothing left to curry. An example is clearer: int foo(int a, int b, int c) { return a + b + c; } auto curriedFoo(int a) { return (int b) { return (int c) { return foo(a, b, c); }; }; } assert( curriedFoo(1)(2)(3) == 6 ); Whereas partial application could be something like: auto partialApply(F)(int x, F fun) { return (ParameterTypeTuple!(F)[1..$] args) { return fun(x, args); }; } assert( partialApply(1, &foo)(2,3) == 6);On 04/13/2011 02:34 PM, bearophile wrote:Oh absolutely. Haxe has nullable-primatives which really comes in handly at times (it often prevents the need for a separate bool to keep track of). Only problem is that in Haxe, not only is nullable the default, but it doesn't even *have* any non-nullables at all, for any type.If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T? String? name = process.args.first; if (exists name) { writeLine("Hello " name "!"); } else { writeLine("Hello World!"); } Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible. This is exactly what I suggested for D in a enhancement request. It seems this kind of stuff is becoming a standard in new languages.+++ But I guess optionality could, and should, extend to non-ref types; thus, null is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...}I don't get the diff between currying & partial app. And find this feature much complication for close to uselessness.I'm not certain either, but I *think* partial application is just like currying except there's some sort of arbitrary limitaion on what combination(s) of paramaters you can choose to specify or not specify. And that limitation is based purely on what order the function defines its parameters. So basically, my understanding is that partial application is an arbitrarily-gimped currying.
May 04 2011
Lutger Blijdestijn:partial application is getting a new function out of an existing one where one of the arguments is fixed / bound. More or less what std.functional curry does, confusingly. [...]A simple and good explanation. Regarding the name of std.functional.curry(), since some time I have suggested to rename it "partial". Bye, bearophile
May 04 2011
Currying is well established name as well, especially for people coming from a functional programming background. (Cristi Cobzarenco) Profile: http://www.google.com/profiles/cristi.cobzarenco On 4 May 2011 23:40, bearophile <bearophileHUGS lycos.com> wrote:Lutger Blijdestijn:partial application is getting a new function out of an existing onewhereone of the arguments is fixed / bound. More or less what std.functional curry does, confusingly. [...]A simple and good explanation. Regarding the name of std.functional.curry(), since some time I have suggested to rename it "partial". Bye, bearophile
May 05 2011
On 2011-05-06 00:54:34 +0300, Cristi Cobzarenco said:Currying is well established name as well, especially for people coming from a functional programming background.Current implementation does not curry the function, it partialy applies it. Currying is converting a function that takes multiple arguments to a function that takes first argument and returns a function that takes the second argument and do on. Curry ((a, b) -> c) -> a -> b -> c Uncurry (a -> b -> c) -> (a, b) -> c(Cristi Cobzarenco) Profile: http://www.google.com/profiles/cristi.cobzarenco On 4 May 2011 23:40, bearophile <bearophileHUGS lycos.com> wrote: Lutger Blijdestijn:partial application is getting a new function out of an existing one where one of the arguments is fixed / bound. More or less what std.functional curry does, confusingly. [...]A simple and good explanation. Regarding the name of std.functional.curry(), since some time I have suggested to rename it "partial". Bye, bearophile
May 05 2011
spir:But I guess optionality could, and should, extend to non-ref types; thus, null is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...}not hard to implement them with the language itself).Also, they should reuse '?' to mean 'exists', possibly '!?' meaning the opposite: void f (int i?) { if (? i) doWithI(i); if (!? i) doWithoutI(); ... }Better to keep the language less perlish.great! get rid of new in D as wellThis was discussed a lot. I don't have much interest in this change.The second hello is a function reference. Nothing so interesting to see here.We may define a class method "by reference": void hello(String name) = hello;???I don't get the diff between currying & partial app.Take a look at the wikipedia pages, the difference is small, they are quite related things, their difference is no so important: http://en.wikipedia.org/wiki/Currying http://en.wikipedia.org/wiki/Partial_applicationAnd find this feature much complication for close to uselessness.In functional-style programming it's useful to be able to curry (or partially applicate) functions, it helps keep the code shorter and less noisy.examples?See the first PDF at those pages. In the meantime people have mirrored those PDFs, see the Reddit thread.Yo; and while you're at "typestating", extend the feature to any type (not only pointers).For this you may need to look for a language (Rust) designed for the ground up for this feature. Bye, bearophile
Apr 14 2011
On 04/14/2011 09:06 PM, bearophile wrote:But I find optionality far more useful for non-ref types, since in the general case there is no truelly special or invalid value like null. What value means undefined/inexistent/non-provided, for an int? a bool? Unlike for ref'ed types (actual pointers/classes/arrays) we simply cannot express this without language support. This also leads to actual distinction of null and [] or "" for arrays & strings. Just dreaming... Denis -- _________________ vita es estrany spir.wikidot.comBut I guess optionality could, and should, extend to non-ref types; thus, nullit's not hard to implement them with the language itself).is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...}
Apr 14 2011
spir Wrote:This also leads to actual distinction of null and [] or "" for arrays & strings. Just dreaming...Really? You want this? I really like that a null array is equal to an empty array. If you really care to find out if a string is null if(str is null)
Apr 14 2011
"Jesse Phillips" <jessekphillips+D gmail.com> wrote in message news:io7oov$21d8$1 digitalmars.com...spir Wrote:I've thought about that and I don't know how I feel about it. On one hand, I can certainly image cases where the distiction between null and empty would be useful. But OTOH, after having to put up with the nightmare of VB6's "One million distinct ways to have a string that doesn't contain anything", I'm hesitent at embracing extra ways to have "ain't nuthin' here".This also leads to actual distinction of null and [] or "" for arrays & strings. Just dreaming...Really? You want this? I really like that a null array is equal to an empty array.
Apr 14 2011
Nick Sabalausky Wrote:I've thought about that and I don't know how I feel about it. On one hand, I can certainly image cases where the distiction between null and empty would be useful. But OTOH, after having to put up with the nightmare of VB6's "One million distinct ways to have a string that doesn't contain anything", I'm hesitent at embracing extra ways to have "ain't nuthin' here".In our project we use if(string.IsNullOrEmpty(str)){...} almost everywhere only in two places null matters. T__T
Apr 14 2011
"bearophile" <bearophileHUGS lycos.com> wrote in message news:io7gk3$1jea$1 digitalmars.com...spir:(Ex: Missing IArithmetic, anyone?)But I guess optionality could, and should, extend to non-ref types; thus, null is just a particular case of non-existence. And this would apply especially on function parameters: void f (int i?) {...}it's not hard to implement them with the language itself).
Apr 14 2011
On 13/04/2011 13:34, bearophile wrote:The first description of the Ceylon language, designed for business computing (for large teams developing multi-user applications) and meant to replace Java, from Red Hat, that will run on the Java Virtual Machine itself: http://blog.talawah.net/2011/04/gavin-king-unviels-red-hats-top-secret.html About the language (very slow download): http://www.qconbeijing.com/download/Gavin%20keynote.pdf About the its type system: http://www.qconbeijing.com/download/Gavin%20session.pdfHum, I saw this Ceylon stuff posted on Slashdot, and I've finally gotten around to taking a look at it. I don't have yet an opinion of the language as a whole, but I do like some of things they did or are thinking about. Namely, that they are extending or changing the type system, and not just to put in non-nullable types (which is quite simple to do), but going much further than that: looking at generics, covariance in generics (and in the process placing the immutability of collections in the type system instead of the runtime), being able to specify all possible subclasses of a class, union types, etc. Interesting ideas. -- Bruno Medeiros - Software Engineer
May 03 2011