Log of the #nice channel on irc.freenode.net

Using timezone: Central European Time
<xoltar>Good night02:00
* xoltar leaves
* bonniot leaves02:04
* bonniot joins11:01
* arjanb joins12:06
<bonniot>hello arjan12:09
<arjanb>hi
<bonniot>how are you?
<arjanb>well just awake
<bonniot>:-)12:10
here is something to wake you up completely:
http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/ConstructorSyntax
* bonniot leaves12:27
* bonniot joins12:28
oops12:29
comments about the proposal?
<arjanb>i find it odd13:47
<bonniot>which part?13:50
<arjanb>the .make call and it's mixing up things as i had in mind13:54
<bonniot>can you explain?
<arjanb>Point.make(...) and new Point(...) are the same unless there is some creation method?14:03
<bonniot>yes, that's the idea14:07
<arjanb>and if 'there is' = 'there happens to be'14:09
<bonniot>?14:10
<arjanb>i think .make will be used too much14:13
<bonniot>why?14:16
basically, you only need to call .make inside a creation method
<arjanb>so why not look for another solution in creation methods( == overloaded constructor ?)14:20
<bonniot>what do you mean?14:21
actually, if the last part is also implemented, you will need .make even less, because it is in the implicit default case14:22
the only case I see where it is needed is:
let Point origin = new Point(x: 0, y: 0);
new Point(0,0) = origin;14:23
how to avoid the loop there?
what is your problem with .make exactly?14:24
<arjanb>having 2 things doing exactly the same most of the time14:25
and .make isn't replacable as new is14:26
<bonniot>it does not matter what they _do_, what is important is what they _mean_
replacable?
i think i understand14:27
the point is, it seems sometimes you need to say "now _really_ create an object with these values"
and that's make14:28
while new means: i want an object with these characteristics14:29
<arjanb>hmm have to think about14:33
<bonniot>most of the time you will want the second, but the fist seems to be needed too14:34
hum, there is an alternative syntax, with the same idea:14:40
use Point(...) for overloaded constructors
and new Point(...) for the cases you really want a new instance14:41
it's clearer because 'new' means what it means ;-)
and Point(...) can now really be a normal method, no need for special parsing
the BIG problem is that the "normal" way to construct objects will be _without_ 'new'14:42
and that's a very big change of habits
the example would become:14:43
let Point origin = new Point(x: 0, y: 0);
Point(0,0) = origin;
usage: let p = Point(1,2);
custom constructor:14:44
new Point(double angle, double distance) = Point(x: distance*cos(angle), y: ...);14:45
new Point(0, double distance) = Point(x: distance, y: 0);
<arjanb>*away for an hour*15:04
* bonniot leaves15:22
* bonniot joins15:23
<arjanb>*back*16:10
isn't the looping problem more general than constructors only?16:11
<bonniot>well, you can always write looping methods if you are not careful. But without Point.make, you cannot _avoid_ the loop in this situation, that's the difference16:12
an interesting testcase:16:33
.16:34
./// PASS
./// package a
./// Toplevel
class Point { int x; }
let origin = new Point(x: 1);
./// package b
assert origin.x == 1;
./// Toplevel16:35
.// "cache"
new Point(1) = origin;
in a, it should be
let origin = Point(x: 1);16:36
(using the "new" syntax
)
the point is that in package a Point(...) should not resolve to the OC of package b
but that's natural, since it does not exist yet16:37
and then code of a is not recompiled
package b import a of course
hum, if Point is a normal method, the natural way to do things would actually create a loop16:39
let's start again16:44
the testcase is:
./// PASS
./// package a
./// Toplevel
class Point { int x; }
let origin = Point(x: 1);
./// package b import a
assert origin.x == 1;
./// Toplevel
.// "cache"
Point(1) = origin;
<arjanb>i don't see a loop in this one16:47
<bonniot>i will be NPR
NPE
when the JVM computes the value of origin, it calld Point(1)16:48
the dispatch finds that the implementation is the one defined in b
because the arg is 1
and that implementation returns the value of origin, which is still null16:49
so it's incorrect
the fact that you can get null is know, it's the old bug report
<arjanb>yes
<bonniot>the problem is, if we advise people to use Point(...)16:50
in package a it looks like a good idea to write
let origin = Point(x: 1);
but that makes package b impossible to write correctly16:51
well, you could do
if (origin == null) return new Point(x: 1);
but then why not:
if (origin == null) return new Point(x: 2);16:52
weird
actually, there is logic in this:
the author of package a that initial value of origin is the result of a method call
which means, the result depends on the implementations
if he really wants it to be the Point whose x is 1, he must write:16:53
let origin = new Point(x: 1);
makes sense...
so, it seems that a good solution is to say that new X is _not_ a method, and _not_ overloadable16:54
you can define custom constructors for it, of course16:55
in addition, we recommand people to instantiate objects with X(...) without the new, unless they are sure they need a new object
<arjanb>not sure16:56
<bonniot>X(...) is a normal method, except that it does not need to be declared: the default is simply to call X(...)
yes?
<arjanb>btw i'm ignoring the initialize/looping problem for now16:57
i think new Type(...) and Type(...) should be equivalent so 'new' is only optional for not making the syntax difference with java bigger16:59
<bonniot>i would agree with that if we needed only one construct17:01
but so far it seems we need two, since they have different semantics
how would you do:17:02
Point(0,0) = origin;
otherwise?
with:
let origin = new Point(0,0);
<arjanb>class Point 17:06
{
int x;
int y;
}
new Point(int x_, int y_ ) = this(x: x_, y: y_);
let origin = new Point(x_ : 0, y_: 0);
<bonniot>when woul this(...) be legal?17:09
sorry, this is a CC, right?
<arjanb>this(...) can only be a call to a real or custom constructer
yes
<bonniot>OK, this would work, but it's not very pretty17:10
if you look at:17:12
let origin = new Point(x_ : 0, y_: 0);
it's very obscure what you are doing
<arjanb>it isn't pretty but if someone really wants (something odd like) a overloaded constructor with exact the same signature as the real constructor then he has to do something for it
<bonniot>i don't think this is an odd case, i think it's very common:17:13
you have a natural interface for describing an instance (here x and y)17:14
so this is both the field you have in the class, and the parameters of the _client_ constructor
if it happens you want to do something else than the default constructor, both have the same signature. it's natural, not an accident17:15
<arjanb>class Point 17:16
{
private int x_;
private int y_;
getX() ...
setX() ...
getY() ...
setY() ...
}
let origin = new Point(x_ : 0, y_: 0);
<bonniot>that only works if origin is in the same module as the class declaration17:17
if you think of a caching system, it can very well be in a different package17:18
<arjanb>i think caching should be either in the same module or should be explicit17:19
<bonniot>yes, maybe17:21
it still feels strange to need to rename the fields just to be able to construct a specific instance
feels like a hack17:22
but OK, both designs seem OK at this point17:23
we need to let these ideas mature a bit, and get some feedback
<arjanb>agreed
<bonniot>do you have any specific argument against Point / new Point ?17:24
<arjanb>too easy to do wrong17:25
<bonniot>example?17:27
<arjanb>from java is new Point the thing you type automaticly and from others like python it's natural to leave it away
and when reading code you overlook easily whether new Point or Point is used17:29
<bonniot>well, it should be that Point will be used most of the time, so new Point will attract your attention17:31
<arjanb>i think it won't draw attention17:33
if it comes to having two different calls to constructors i'd rather have .make and new17:35
<bonniot>sounds logical to me that "new" means that the object will surely be new... :-)17:37
<arjanb>Type.make(...) and Type(...) then17:38
<bonniot>which one meaning what?17:39
<arjanb>.make calling the constructor directly17:40
<bonniot>and new Type ?
new Type(...)
<arjanb>yes
<bonniot>meaning what?
<arjanb>your Type(...) and new Type(...) is mine Type(...) and Type.make(...)17:42
<bonniot>but so you would make new Type(...) invalid?
ok, i have to go. let's think over it and we'll discuss later...17:43
<arjanb>make 'new' optional and maybe deprecated in the long term
* bonniot is away: ...
* bonniot is back (gone 05:12:46)22:56
news thoughts?
<arjanb>not for constructor things23:02
possible syntax for expression local variables type name := expression and name := expression23:08
<bonniot>when there is a type, := is useless, = would be good enough23:09
and it looks akward23:10
why use it there, but not for other local variables?
we already have var and let, why not be consistent?23:11
i think var would look fine:
for instance, using(var x = foo()) { ... }
<arjanb>because i don't find that look good
<bonniot>only you often won't want x to be variable23:12
what about val for 'value':
using(val x = foo()) { ... }
<arjanb>too close to var
<bonniot>val and let would be equivalent
yes its close
that can be seen as a disadvantage or an advantage23:13
(similar uses, similar names)
r and l are far on the keyboard, no risk on that account23:14
:-)
<arjanb>but for reading it's a difference
<bonniot>a difference from that?
from what?
(with what?)23:15
<arjanb>reading is easier when the keywords are very different
<bonniot>true23:18
only it does not make a big difference if x is variable or not23:20
the important thing is to see it's a new variable
it reads well:
using value x which is equal to foo, ...23:21
it's not like a catastrophy will happen if you think x is mutable when it is not23:22
<arjanb>i don't find the pronouncability important23:23
<bonniot>you can set your editor to give different colors to val and var :-)
and most importantly, this is not a big issue, is it?23:24
<arjanb>true
<bonniot>so ok for let/val ?23:28
<arjanb>i think at first expression local variable could be allowed only in arguments of some call23:29
<bonniot>agreed23:31
<arjanb>not difficult to parse and the visibility of the variable is obvious23:32
<bonniot>yes23:44
<arjanb>i have looked for alternatives for sf for the collection of nice libraries23:55
but i didn't find much23:56
<bonniot>nothing?00:00
<arjanb>there is savannah and many sites with only a few projects00:01
<bonniot>there is also developer.berlios.de (~ 1000 projects)00:19
but yeah, i saw subversion nowhere
they are preparing their 1.0, so the situation may change soon...
<arjanb>the additional type for in patterns doesn't allow arrays and such00:45
and the error message is a bit odd00:46
D:\Nice\.\utils\indentwriter.nice: line 9, column 3:
There is an ambiguity about which version of the overloaded method "write" this alternative belongs
to.
Try to use more patterns.
Possible methods:
nice.lang.void write(java.io.Writer, nice.lang.int) defined D:\Nice\.\utils\indentwriter.nice
nice.lang.void write(Writer, String) defined line 243, column 16
nice.lang.void write(Writer, nice.lang.Array<char>) defined line 241, column 16
i surely haven't defined any write method00:47
<bonniot>what is the source code?00:49
<arjanb>import java.io.*;00:50
class IndentWriter extends Writer
{
Writer out;
write(cbuf) = out.write(cbuf);
}
<bonniot>why is this surprising?00:52
<arjanb>because i haven't defined any write method00:53
<bonniot>ok, but you extend Writer, which has write methods00:54
<arjanb>yes but the error message shouldn't point to my file00:55
<bonniot>ah
yes00:56
i think it's because that method is defined in the JDK
<arjanb>and the other with a line number but no file don't make much sense either
<bonniot>the source location is unknown
i picks the name of the current file when that method was loaded, which is indeed misleading00:57
I suppose we should have Locations like: "in class java.io.Writer"00:58
<arjanb>yes
<bonniot>it should not be hard, now that Location is an abstract class
:-)00:59
i guess you are working on pretty-printing Nice source?
<arjanb>no just a general utility thing01:00
but no arrays possible in the additional pattern type is a bug i would say01:02
any activity on nicedoc?01:17
<bonniot>no, but i will write to ask01:19
for array, you can do:
foo(Array x) { ... }01:20
isn't that OK?
<arjanb>maybe but i want write(cbuf(char[])) = ...01:21
<bonniot>isn't the syntax foo(Class(Type) x) ?01:22
<arjanb>foo(x(Type)) is correct too at least in the old style01:24
<bonniot>old style was foo(x@Class(Type))01:26
but maybe you could have (Type) without Class01:27
you know that better than me :-)
<arjanb>old style allows additional type after every pattern so after name only too01:28
<bonniot>ok
<arjanb>foo(Array x) { ... } only works if there are no other alternatives01:30
at array patterns can yield incorrect code01:32
0 aload_0
1 instanceof #14 nice/lang/rawArray
4 ifeq 12
<bonniot>why is that incorrect?01:35
Array x does not filter out methods that are don't have an array (or Object, or Any T) at that place?01:36
if so, please submit a testcase
<arjanb>void foo(char[?] cbuf);
foo(Array cbuf) { assert true; }
foo(null) { assert false;}
foo(['a','b']);01:37
<bonniot>what is this for? codegen, or ambiguity?01:39
<arjanb>wdym?01:40
<bonniot>i thought you said there was a problem resolving ambiguities with arrays01:41
but we are speaking about code generation now only, right?01:42
<arjanb>that's the other bug
yes
<bonniot>testcase for the other bug?01:43
<arjanb>void foo(int[] arr);01:45
void foo(char[] arr);
foo(Array(int[]) arr) {}
foo(Array(char[]) arr) {}
<bonniot>agreed. it should be only a parsing change. can you look at that?01:46
i'm looking at the dispatch thing01:47
<arjanb>the dispatch test for Array depends on the declararion type of the argument01:51
<bonniot>if the array has been wrapped as a list, the current code will work01:52
<arjanb>yes
int[] and char[] would have the same typeconstructor?01:56
<bonniot>yes, Array01:57
<arjanb>so than i can't fix it with only a parsing change01:58
<bonniot>y?
<arjanb>because other code expects that a resolved additional type is an typeconstructor
<bonniot>but that parser accepts types, or TCs?02:00
<arjanb>typeident
<bonniot>and resolved to a TC, given what you said02:01
<arjanb>yes
<bonniot>i think it could be changed to parse a monotype in all cases02:02
this is more general, and will handle arrays nicely
<arjanb>right but i don't know how to do the typing changes of this02:03
<bonniot>yes, it will be a bit more work in this case. is it urgen for you, or can you workaround?02:19
<arjanb>i can workaround
<bonniot>ok. so you could simply submit testcases02:20
i have a fix for the array dispatch :-)
<arjanb>is done for codegeneration
<bonniot>?
<arjanb>submitted a testcase02:21
<bonniot>ok
i can compare with mines :-)
<arjanb>good night02:38
* arjanb leaves