Another Phobos2 test

2011-02-07 Thread bearophile
I've found another taks in the rosettacode.org site:
http://rosettacode.org/wiki/Tic-tac-toe

The program itself is not so interesting, and probably there are better ways to 
implement a Tic-tac-toe player program. But it's a good enough example to test 
Phobos2, to see how much handy it is when you compare it to the original Python 
version.

The original Python3 code was first translated to Python2.x, then translated to 
D2. The translation to D was a bit of pain, for many things there was a need to 
do some experiments to find a syntax that works. This is bad.

Some stats:
- Python2 source code: 91 lines, 2385 bytes.
- D2 source code: 134 lines, 3620 bytes.
- D2 binary, default compilation: 338 KB on Windows with DMD.

Here are small parts of the Python2 version followed by the D2 translation, 
sometimes followed by some comments. The D translation may be improved, if you 
see something, feel free to comment.



'''
Tic-tac-toe game player.
Input the index of where you wish to place your mark at your turn.
'''

import random


/**
Tic-tac-toe game player.
Input the index of where you wish to place your mark at your turn.
*/

module tic_tac_toe;

import std.stdio, std.random, std.string, std.algorithm,
   std.array, std.typecons, std.conv;


The D version requires many more imports because Python has a tons of built-in 
features. The comment in the Python version is a docstring of the module, about 
as in D. But in Python you are able to access the docstrings from the code 
itself (see below the print __doc__), this allows to write those comments just 
once in the Python program, while they are written twice in the D code.

I'd like the DMD compiler to be able to produce a JSON tree out of the current 
module during compilation, through a library, and allow the normal code to use 
it at compile time. So with a library you are able to extract any kind of data 
about the module and its code. This will be a good material (a way to perform 
static introspection) to later build a user-defined attributes feature on.

All the Python2.x and D2 code shown is tested, unless otherwise specified.

--

board = list('123456789')
wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8),
(0, 3, 6), (1, 4, 7), (2, 5, 8),
(0, 4, 8), (2, 4, 6))


alias char[] TBoard;
TBoard board = "123456789".dup;
enum WINS = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
 [0, 3, 6], [1, 4, 7], [2, 5, 8],
 [0, 4, 8], [2, 4, 6]];


An alias is not as good as a typedef, to make statically sure the various 
functions do take a board and nothing else as input.

--

def print_board():
print '\n-+-+-\n'.join('|'.join(board[x:x+3]) for x in (0, 3, 6))


auto print_board() {
string[] parts;
foreach (x; [0, 3, 6])
parts ~= array(map!(to!string)(board[x .. x+3])).join("|");
writeln(parts.join("\n-+-+-\n"));
}


I'd like join to work with a lazy range and on chars too, allowing code like 
(untested):

auto print_board() {
string[] parts;
foreach (x; [0, 3, 6])
parts ~= board[x .. x+3].join("|");
writeln(parts.join("\n-+-+-\n"));
}


This means:
join("123", "x") ==> "1x2x3"

And:
join(map!(to!string)([1,2,3]), "x") ==> "1x2x3"

See:
http://d.puremagic.com/issues/show_bug.cgi?id=4468
http://d.puremagic.com/issues/show_bug.cgi?id=5542

--

def score(board=board):
for w in wins:
b = board[w[0]]
if b in "XO" and all(board[i] == b for i in w):
return (b, [i+1 for i in w])
return None


auto score(TBoard sboard=board) {
foreach (w; WINS) {
auto b = sboard[w[0]];
bool found = canFind!((i){ return sboard[i] != b; })(w);
if ((b == 'X' || b == 'O') && !found) {
return new Tuple!(char, int[])(b, array(map!q{a+1}(w)));
}
}
return cast(typeof(return))null;
}


This function has required several tries to be written. That final cast allows 
code to be more DRY, and it comes from some experiments. Here we have a "auto" 
return type and a typeof(return) in the same function.

There is no clean way to create a tuple on the heap, the way I have used is the 
best I have found.

I'd like Python simple functions all() and any() in Phobos2 too. With it you 
are able to write code a bit less ugly like (untested):


auto score(TBoard sboard=board) {
foreach (w; WINS) {
auto b = sboard[w[0]];
if ((b == 'X' || b == 'O') && all!((i){ return board[i] == b; })(w)) {
return new Tuple!(char, int[])(b, array(map!q{a+1}(w)));
}
}
return cast(typeof(return))null;
}


Compared to the original Python code this D2 code is not so good still.

See:
http://d.puremagic.com/issues/show_bug.cgi?id=5544

--

def finished():
return all(b in 'XO' for b in board)


auto finished() {
return reduce!q{a && b}(true, map!q{a == 'X' || a == 'O'}(board));
}


This D2 code comes from some experime

Re: Another Phobos2 test

2011-02-07 Thread Adam Ruppe
My gut tells me you'd get much better results if you tried to
write D in D instead of Python in D.

I might take a stab at this myself. I can see lots of improvements
to the original code.


Re: Another Phobos2 test

2011-02-07 Thread bearophile
Adam Ruppe:

> My gut tells me you'd get much better results if you tried to
> write D in D instead of Python in D.

That's really beside the point. The point of the post is that there are some 
spots where I'd like to see Phobos improved. (And I am willing to write part of 
the Phobos code I am asking for).


>I might take a stab at this myself. I can see lots of improvements to the 
>original code.<

The original Python code is globally quite bad. Don't waste your time trying to 
improve it. Improve Phobos instead :-)

Bye,
bearophile


Re: Another Phobos2 test

2011-02-07 Thread Jonathan M Davis
On Monday, February 07, 2011 15:34:26 bearophile wrote:
> Adam Ruppe:
> > My gut tells me you'd get much better results if you tried to
> > write D in D instead of Python in D.
> 
> That's really beside the point. The point of the post is that there are
> some spots where I'd like to see Phobos improved. (And I am willing to
> write part of the Phobos code I am asking for).

Actually, it's not beside the point at all. Regardless of what language you're 
programming in, it's generally best to program in the typical paradigms of that 
language. Trying to contort it to act like another language is _not_ going to 
result in optimal code.

Now, that's not to say that Phobos can't be improved upon (it certainly can 
be), 
but if you focus too much on how it doesn't do something like some other 
language does, you'll miss what it _can_ do. And it's quite possible that it 
actually does what you're trying to do quite well if you'd just stop trying to 
contort it to act like another language (be it Python or Haskell or Rust or Go 
or Java or C++ or C or Ruby or...).

- Jonathan M Davis


Re: Another Phobos2 test

2011-02-07 Thread bearophile
Jonathan M Davis:

> Regardless of what language you're 
> programming in, it's generally best to program in the typical paradigms of 
> that 
> language. Trying to contort it to act like another language is _not_ going to 
> result in optimal code.

D supports functional style too now. In Bugzilla I have put most of the 
requests I think are useful. So if you have specific comments please add to 
those.

Bye,
bearophile


Re: Another Phobos2 test

2011-02-07 Thread Andrew Wiley
On Mon, Feb 7, 2011 at 6:36 PM, bearophile  wrote:

> Jonathan M Davis:
>
> > Regardless of what language you're
> > programming in, it's generally best to program in the typical paradigms
> of that
> > language. Trying to contort it to act like another language is _not_
> going to
> > result in optimal code.
>
> D supports functional style too now. In Bugzilla I have put most of the
> requests I think are useful. So if you have specific comments please add to
> those.


That's not the point. No matter what styles of programming D supports, it
will support them differently from other languages. This is true for pretty
much any language, so direct comparisons don't really get you much.
I come from the Java world with some Scala experience, and I frequently find
myself trying to write code the Java make-everything-an-object way, and I
just as frequently find that D can do things much more simply if I blend the
OO with imperative code and chuck in a few functional elements where useful.
I can appreciate what you're trying to do, but doing a line by line
comparison of D and Python and asking for features to make D look more like
Python just feels like you're trying to contort D into something it never
claimed to be. It's not entirely wrong, but it's not entirely right either.


Re: Another Phobos2 test

2011-02-07 Thread Nick Sabalausky
"Jonathan M Davis"  wrote in message 
news:mailman.1382.1297122691.4748.digitalmar...@puremagic.com...
> On Monday, February 07, 2011 15:34:26 bearophile wrote:
>> Adam Ruppe:
>> > My gut tells me you'd get much better results if you tried to
>> > write D in D instead of Python in D.
>>
>> That's really beside the point. The point of the post is that there are
>> some spots where I'd like to see Phobos improved. (And I am willing to
>> write part of the Phobos code I am asking for).
>
> Actually, it's not beside the point at all. Regardless of what language 
> you're
> programming in, it's generally best to program in the typical paradigms of 
> that
> language. Trying to contort it to act like another language is _not_ going 
> to
> result in optimal code.
>
> Now, that's not to say that Phobos can't be improved upon (it certainly 
> can be),
> but if you focus too much on how it doesn't do something like some other
> language does, you'll miss what it _can_ do. And it's quite possible that 
> it
> actually does what you're trying to do quite well if you'd just stop 
> trying to
> contort it to act like another language (be it Python or Haskell or Rust 
> or Go
> or Java or C++ or C or Ruby or...).
>

Using std.algorithm qualifies as contorting D?





Re: Another Phobos2 test

2011-02-07 Thread Nick Sabalausky
"Nick Sabalausky"  wrote in message 
news:iiq4pa$28aa$1...@digitalmars.com...
> "Jonathan M Davis"  wrote in message 
> news:mailman.1382.1297122691.4748.digitalmar...@puremagic.com...
>> On Monday, February 07, 2011 15:34:26 bearophile wrote:
>>> Adam Ruppe:
>>> > My gut tells me you'd get much better results if you tried to
>>> > write D in D instead of Python in D.
>>>
>>> That's really beside the point. The point of the post is that there are
>>> some spots where I'd like to see Phobos improved. (And I am willing to
>>> write part of the Phobos code I am asking for).
>>
>> Actually, it's not beside the point at all. Regardless of what language 
>> you're
>> programming in, it's generally best to program in the typical paradigms 
>> of that
>> language. Trying to contort it to act like another language is _not_ 
>> going to
>> result in optimal code.
>>
>> Now, that's not to say that Phobos can't be improved upon (it certainly 
>> can be),
>> but if you focus too much on how it doesn't do something like some other
>> language does, you'll miss what it _can_ do. And it's quite possible that 
>> it
>> actually does what you're trying to do quite well if you'd just stop 
>> trying to
>> contort it to act like another language (be it Python or Haskell or Rust 
>> or Go
>> or Java or C++ or C or Ruby or...).
>>
>
> Using std.algorithm qualifies as contorting D?
>

(Although, I didn't read the OP very closely, so maybe I'm off-base.)




Re: Another Phobos2 test

2011-02-07 Thread bearophile
Nick Sabalausky:

> (Although, I didn't read the OP very closely, so maybe I'm off-base.)

They are right, I have done a "strategic" error. In the original post I have 
mixed two kinds of very unrelated things: very small suggestions to improve (in 
my opinion) Phobos, plus some critiques to the D2 language compared to Python. 
People have rightly not appreciated my post because of the second group of 
useless comments. I am sorry, I am just stupid. Regarding the original post, in 
Bugzilla I have added only Phobos-related things.

Bye,
bearophile


Re: Another Phobos2 test

2011-02-07 Thread Jonathan M Davis
On Monday, February 07, 2011 16:55:02 Andrew Wiley wrote:
> On Mon, Feb 7, 2011 at 6:36 PM, bearophile  wrote:
> > Jonathan M Davis:
> > > Regardless of what language you're
> > > programming in, it's generally best to program in the typical paradigms
> > 
> > of that
> > 
> > > language. Trying to contort it to act like another language is _not_
> > 
> > going to
> > 
> > > result in optimal code.
> > 
> > D supports functional style too now. In Bugzilla I have put most of the
> > requests I think are useful. So if you have specific comments please add
> > to those.
> 
> That's not the point. No matter what styles of programming D supports, it
> will support them differently from other languages. This is true for pretty
> much any language, so direct comparisons don't really get you much.
> I come from the Java world with some Scala experience, and I frequently
> find myself trying to write code the Java make-everything-an-object way,
> and I just as frequently find that D can do things much more simply if I
> blend the OO with imperative code and chuck in a few functional elements
> where useful. I can appreciate what you're trying to do, but doing a line
> by line comparison of D and Python and asking for features to make D look
> more like Python just feels like you're trying to contort D into something
> it never claimed to be. It's not entirely wrong, but it's not entirely
> right either.

Agreed. I like Haskell, and I like programming in a functional style in D (I 
_love_ how you can effectively process ranges like s lists), but I don't try 
and 
program in D like I would in Haskell. They're two different languages. I don't 
even try and program in D like I would in C++. Sure, a lot is similar, and what 
you know about other programming languages and styles informs how you program 
in 
D (or any other language), but if you properly use a particular programming 
language, you often end up doing things differently than you would in other 
programming languages even if you _can_ program in the same way that you would 
in another programming language.

- Jonathan M Davis


Re: Another Phobos2 test

2011-02-07 Thread Jonathan M Davis
On Monday, February 07, 2011 17:11:50 bearophile wrote:
> Nick Sabalausky:
> > (Although, I didn't read the OP very closely, so maybe I'm off-base.)
> 
> They are right, I have done a "strategic" error. In the original post I
> have mixed two kinds of very unrelated things: very small suggestions to
> improve (in my opinion) Phobos, plus some critiques to the D2 language
> compared to Python. People have rightly not appreciated my post because of
> the second group of useless comments. I am sorry, I am just stupid.
> Regarding the original post, in Bugzilla I have added only Phobos-related
> things.

Stupid is going a bit far. You do seem to have a tendancy however to at least 
present things as if D should act like python, which isn't necessarily a good 
thing. Different points of view on how to go about solving problems can lead to 
better solutions however. It's just that it doesn't necssarily make sense for D 
to act like python, and you often come across like D is defficient when it does 
things differently than python.

- Jonathan M Davis


Re: Another Phobos2 test

2011-02-07 Thread Nick Sabalausky
"Jonathan M Davis"  wrote in message 
news:mailman.1384.1297127779.4748.digitalmar...@puremagic.com...
>
> I don't even try and program in D like I would in C++.

Neither would I. For instance, if I were about to do some coding in C++, I 
would begin by bashing my head into a brick wall. Sure, that would prevent 
me from getting much done, but it would make the whole experience quicker 
and less painful. With D, by contrast, the head-into-brick-wall idiom is 
much less practical.





Re: Another Phobos2 test

2011-02-07 Thread Adam Ruppe
My implementation

http://arsdnet.net/tictactoe.d
source: 138 lines, 2420 bytes

You can see the byte count is comparable to the python 2, but I have
more lines. This reflects my preferences of one line = one instruction.

I usually prefer "Introduction to Programming" style code than
"functional code golf" style, so you see that too.

I also put in a lot of contracts just because i can. I'm trying to
get into the habit of that.

> Input the index of where you wish to place your mark at your turn.

  writef("Input the index of your move (from %s): ",

End user instructions have no place as documentation comments. Being
able to print out documentation comments at runtime is almost useless -
doing so indicates a high probability of bad comments.

You can see that I used a simple string literal for this, declaring
it where it is used.

> I'd like the DMD compiler to be able to produce a JSON tree out of > the 
> current
module during compilation, through a library, and allow > the normal code to use
it at compile time.

dmd -X to generate it, then dmd -J to load it up for use at compile
time. Documentation comments are already included in the json output.

However, see my comment above on how I feel about the need for this...

> An alias is not as good as a typedef, to make statically sure the
> various functions do take a board and nothing else as input.

I wrote: struct Board { }

If you want a separate type, make a separate type. I'm sad to see
typedef go too, personally, but this is a very poor use case for it.
typedef is actually pretty rare. A struct or class is usually
a better choice.

> I'd like join to work with a lazy range and on chars too, allowing > code like
(untested):

I think that could be useful, though it's possible today already
for this example (see toImpl for arrays)

> There is no clean way to create a tuple on the heap, the way I have
> used is the best I have found.

The method you used looks like the right way to do it - you just
"new" it, like anything else.


> I'd like Python simple functions all() and any() in Phobos2 too.
> With it you are able to write code a bit less ugly like (untested):

I think these would be useful too.

There's already one similar thing here:

http://dpldocs.info/allSatisfy

But it doesn't work on the right types it looks like. If we made
that a little more generic I think we'd have a winner.

> My suggestion to avoid this quite bad situation is to look at
> sboard, it's a char[] and not a string. So a solution to this messy
> situation is to make string a strong typedef.

This behavior is by design.

http://digitalmars.com/d/2.0/phobos/std_array.html

ElementType!(String)[] array(String)(String str);
Convert a narrow string to an array type that fully supports random access.
This is handled as a special case and always returns a dchar[], const(dchar)[], 
or
immutable(dchar)[] depending on the constness of the input.


The idea is if you ask for an array, it's because you want to do
O(1) random access, which, assuming you want code points, means
dchar.

You probably could have done reduce!("a ~ b")("", filter) to
get the char[]...

Though, I'd rethink this whole design. The board isn't a string,
so you shouldn't represent it as one. I used int[9] in my code.


> There are many situations where I'd like afilter() ===
> array(filter()) and amap() == array(map()).

But, this isn't orthogonal!


> auto my_turn(char xo, TBoard sboard) {
>auto options = space();
>char choice = options[uniform(0, options.length)];
>sboard[to!int(choice~"") - 1] = xo;
>return choice;
> }

I wrote this thus:
int suggestMove(int player)
out(ret) {
assert(ret >= 0);
assert(ret < 9);
assert(isAvailable(ret));
}
body {
return randomCover(openPositions(),
Random(unpredictableSeed)).front;
}

You can see it is a one-liner, yet not an unreadable one. The reason
is because I picked a more correct representation of the board.

It makes no sense whatsoever to populate an array with its indexes,
then get indexes to get a value which is then converted back into an
index!

I you use an index in the first place, which makes conceptual sense,
you save piles of busy work.

> to!int(choice) doesn't do what you think it does, it converts the
> choice char to its integer representation:

That's actually exactly what I think it does, coming from C. I'd be
ok with just making cast() be the thing to do though. I usually
cast for this use case anyway (again coming from C, that's just the
natural way that comes to mind).

> I'd like a _very_ handy std.random.choice(), that allows to write
> code like (untested):

I don't see the big benefit over randomCover here, but I wouldn't
veto it's inclusion (if I had such power). It's a trivial function
though.


> In Python both for and while loops have an optional "els

Re: Another Phobos2 test

2011-02-08 Thread bearophile
Adam Ruppe:

> My implementation
> http://arsdnet.net/tictactoe.d

Thank you for your answers and code. Your code is better.

This kind of indentations is interesting:

string positionString(int pos)
in {
assert(...);
}
out(ret) {
assert(...);
}
body {
// ...
}


> I don't think it helps your case at all to use such horribly
> awful code to make points. Half of your statements are the direct result of
> the source code being garbage.

The original code was not mine, and I know it's bad code. That's why I have 
suggested you to not work on it. I have used it just because it contains 
several compact constructs used in Python. My next posts I'll use a different 
strategy to explain things.


> source: 138 lines, 2420 bytes
> You can see the byte count is comparable to the python 2, but I have
> more lines.

Replacing the tabs with spaces, as in the original Python and D versions, and 
using Windows newlines, it becomes 3278 bytes.


> I usually prefer "Introduction to Programming" style code than
> "functional code golf" style, so you see that too.

Your code is not functional-style, it's procedural and contains some mutables. 
My discussion was about improving Phobos things that are especially useful if 
you write code in functional style.

Programs in ML-derived functional languages are often written in a more compact 
style. This doesn't make them significantly more bug-prone because purity, 
immutability, very strong type systems, and some other of their features avoid 
many bugs.


> I also put in a lot of contracts just because i can. I'm trying to
> get into the habit of that.

Very good, I do the same.
That code was not production code, it was an experiment focused on showing some 
possible improvements for Phobos. Adding contracts (and annotations as pure, 
const, immutable), and several other things to the code was just a way to 
distract the people that read that code from the purposes of the discussion.

D2 shows that there are three (or more) "sizes" of functional programming:
- Micro scale: when you use a line of code that uses array(map(filter())).
- Medium scale: when you use normal procedural code inside small 
functions/methods, but the small functions are mostly pure and use mostly 
const/immutable data.
- Large scale: when your functions are mostly procedural and sometimes use 
mutable inputs too, but the main fluxes of data in your large application are 
managed in a immutable/functional way (like from the DBMS, etc).

Large-scale functional programming is done in Java programs too, and it's not 
much influenced by Phobos, it's a matter of how your very large program is 
structured.

Medium-scale functional programming is well doable in D2 thanks to pure 
annotations and transitive const/immutable.

So a question is how much micro-scale functional programming is 
right/acceptable in a very little or very large D2 program. I don't have an 
answer yet (probably the answer is: not too much). Some Scala programmers use 
lot of micro-scale functional style (see some little examples here: 
http://aperiodic.net/phil/scala/s-99/ ), but Scala allows to write that code 
with a significantly less noisy syntax. What I am able to say is that currently 
using a micro-scale functional programming style in D2 is awkward, there's too 
much syntax noise, making the code not so readable and maintenable. But that 
tictactoe code was an experiment, you need to perform some experiments, because 
they reveal you new things.

In production code, in larger programs written in a mostly procedural language, 
I usually write code more similar to yours, it's just better if you need to 
maintain lot of code for years. In a more functional language I use a different 
style, but I avoid golfing if the code needs to be used for a lot of time.

In script-like programs I sometimes use a little more compact style, but not as 
compact as the original Python code. In such Python/D scripts I don't write 
stuff like this:

string toString() {
string lineSeparator = "-+-+-\n";
string row(int start) {
return format("%s|%s|%s\n",
positionString(start + 0),
positionString(start + 1),
positionString(start + 2));
}

string ret;

ret ~= row(0);
ret ~= lineSeparator;
ret ~= row(3);
ret ~= lineSeparator;
ret ~= row(6);

return ret;
}

Using what Python offers functional-style allows to write code about equally 
safe. Too many lines of code require more time to be written (experiments have 
shown that programmer tend to write approximately the same number of lines / 
hour. This doesn't hold up to code golfing, of course). This style of writing 
code is seen as "bloated" and Java-style by lot of people (by me too). This is 
why Java programs are sometimes 10+ times longer than Python ones, I prefer 
more compact Python code. On the other hand too much compact code gives 
problems. So as usual in programming you need to 

Re: Another Phobos2 test

2011-02-08 Thread Hamad
== Quote from Adam Ruppe (destructiona...@gmail.com)'s article
> My implementation
> http://arsdnet.net/tictactoe.d
after your permtion i post your code in http://rosettacode.org/wiki/Tic-tac-toe



Re: Another Phobos2 test

2011-02-08 Thread bearophile
Hamad:

> == Quote from Adam Ruppe (destructiona...@gmail.com)'s article
> > My implementation
> > http://arsdnet.net/tictactoe.d
> after your permtion i post your code in 
> http://rosettacode.org/wiki/Tic-tac-toe

On Rosettacode they don't want too much long lines, so I suggest you to reduce 
indents to just 4 spaces, keeping lines under 75 chars.

Bye,
bearophile


Re: Another Phobos2 test

2011-02-08 Thread Adam Ruppe
bearophile:
> This kind of indentations is interesting:

I'm still trying to find something I like for this. Currently,
I see the contracts as part of the public interface, just like
the name, so I'm indenting them like I would if the argument list
ran too long.

void doSomethingBig(
  int arg1,
  int arg2)
{

}

(Sometimes I put the { on the same line as the ) but then I often
find it hard to see the difference between the arguments and local
variables.)

So, similarly, the in and out get indented. It would be messy to
shove them all on one line, but without the indent, it'd look
like it's all part of the body.

>  In such Python/D scripts I don't write stuff like this:
> [snip toString ]

One practical reason for such separation is this (seen in Python
but D does it too):

  >>> s = [1,2,3]
  >>> print s[34], s[44]
  Traceback (most recent call last):
File "", line 1, in 
  IndexError: list index out of range


Error messages give a line number... but if there's still several
points of similar failure on that one line, it doesn't help as much
as it could.

This leads me to write things like this sometimes too:

auto author =
  stuff["data"]
  [0]
  ["from"]
  ["name"];


So if the data isn't what I expected, the line number in the error
message tells exactly what was missing. (This is also a good
example of why semicolons are a gift from God)

>>> s = ((1,2), (3,4), (5,6))
>>> print s[1]
(3, 4)


Ahhh, I wanted a child of it!

Now, I'm forced to do it on one monster line...

>>> print s[1][3]
Traceback (most recent call last):
  File "", line 1, in 
IndexError: tuple index out of range

Gah, which one? I guess I'll use a temp variable...



Anyway, sometimes this can be fixed in the runtime by including
the data and the index as part of the exception, but not always
(what if you did [0][0]?). Putting them on separate lines is
an easy, reliably way to get more information out of the error.


> I know, but I was suggesting something different, to turn the JSON
> creation into some kind of Phobos library that you may call at
> compile-time from normal D code. Then a compile-time JSON reader in
> Phobos will allow to perform certain kinds of static introspection,
> that later will be quite useful to create user-defined @annotations.

We could do that today with a combination of -X, -J, and a CTFE
JSON parser (it's possible that std.json would work today. I haven't
tried it specifically, but ctfe tends to surprise me with its
capabilities).

Of course, you'd have to run the compiler twice, but there's other
advantages to that too (like getting dependencies - my build tool
does this - and the first run is fast anyway.


I'm tempted to do it now just to prove we can... but I'm already
a bit loaded with stuff to do.


> With "new Tuple!()()" you need to manually specify the types of all
> the fields, while "tuple()" spares this need, but allocates on the
> stack. A newTuple() function allows to do both, but I don't know
> how much often it is needed.

Maybe a generic toHeap!(T) function would be good for this. It
takes an existing object and copies it to the heap if necessary.

return toHeap!(tuple(1, 2, 3));


However, it seems to me that most tuples are likely to be small
value types anyway. You had an int, char[]. When I use tuples, they
are usually small collections of ints and strings too.

Value types don't really need to be on the heap. You can just
return them and pass them to functions normally and it works fine.


> What I'd like is a way to tell the type system that I am creating a
> sequence of 8-bit chars, and not a string of chars.

Maybe try ubyte[]?

> I know, but programming life is not orthogonal :-)

That's part of the reason I said it... I'm only half serious.

Though, on the other hand, I've used the ncurses library which does
this kind of thing. The number of function names is obscene, and
the benefit is quite small. I'm not convinced the parentheses are
a big deal. (Hell, I've done lisp before... and kinda liked it. :P)


> I think to!int('1') == 1 is useful, but I am not sure if C-derived
> programmers accept/like to!int to work differtly from cast(int) in
> this case.

The way I see it is if you are working with single chars, it is
probably because you want to do some work with the char itself -
it's numeric value. Thus it fits the same general area as int.

Perhaps you want to just work with one length strings? str[0..1]
instead of str[0].


Re: Another Phobos2 test

2011-02-08 Thread spir

On 02/08/2011 04:11 PM, Adam Ruppe wrote:

I know, but I was suggesting something different, to turn the JSON
>  creation into some kind of Phobos library that you may call at
>  compile-time from normal D code. Then a compile-time JSON reader in
>  Phobos will allow to perform certain kinds of static introspection,
>  that later will be quite useful to create user-defined @annotations.

We could do that today with a combination of -X, -J, and a CTFE
JSON parser (it's possible that std.json would work today. I haven't
tried it specifically, but ctfe tends to surprise me with its
capabilities).

Of course, you'd have to run the compiler twice, but there's other
advantages to that too (like getting dependencies - my build tool
does this - and the first run is fast anyway.


I'm tempted to do it now just to prove we can... but I'm already
a bit loaded with stuff to do.


What I dream of is something a bit different: a D "decoder" (lexical, 
syntactic, semantic(*) analyser) that constructs an AST as a plain D data 
structure --without any fancy stuff. And writes it out on demand as a D module 
(in static this(), since for a reason I haven't yet caught data description can 
only go there).
I can't even start to imagine all what we could then do /easily/. (we would 
even have type defs in D... would change from obscure RTTI)


=
import std.stdio;
a = 1;
void main () {
writeln(a);
}
=
==>
=
import AST; // Node types, mainly
Module module;

static this () {
module = Module ([
Import("std.stdio"),
Assignment("a", Integer(1)),
FunctionDef(
/* name */  "main",
/* params */[],
/* block */ [
FunctionCall(
/* name */   "writeln",
/* args */   [Symbol(a)]
)
]
)
]);
}
=

Too bad we're missing named args, would be highly helpful here; but we can 
probably survive that...

(Yes, Bearophile, there's certainly a bug report for this ;-)

I would enjoy writing a prototype when I have some time (not tomorrow), for a 
tiny subset of D (kind of proof of concept).


Denis

(*) As far as possible.
--
_
vita es estrany
spir.wikidot.com



Re: Another Phobos2 test

2011-02-08 Thread bearophile
Adam Ruppe:

> I'm still trying to find something I like for this.

Me too.


> Error messages give a line number... but if there's still several
> points of similar failure on that one line, it doesn't help as much
> as it could.

I understand. But splitting lines too much make the code a bit too much thin. I 
think a better solution is this request (from Lewis):
http://d.puremagic.com/issues/show_bug.cgi?id=5521


> We could do that today with a combination of -X, -J, and a CTFE
> JSON parser



> (it's possible that std.json would work today. I haven't
> tried it specifically, but ctfe tends to surprise me with its
> capabilities).

Currently the JSON data is not computed at compile-time, and it's written as 
file text on the disk, while a library is meant to not touch the disk. So the 
situation isn't good enough yet.


> Maybe try ubyte[]?

There are moments when I want an array of ubytes, other moments when I want an 
array of 8 bit chars, and other situations where I want a string of chars. An 
ubyte[] is a workaround for a type system not good enough yet.


> Though, on the other hand, I've used the ncurses library which does
> this kind of thing. The number of function names is obscene, and
> the benefit is quite small.

I agree that too many functions are going to give problems. But an "a" suffix 
is burden smaller than two names fully new.


> I'm not convinced the parentheses are
> a big deal. (Hell, I've done lisp before... and kinda liked it. :P)

Scala, Ruby, ML-class languages like Haskell, etc have means to reduce 
parentheses count. Reducing syntax noise in functional-style code is something 
that a lot of people wants (me too). I have used Scheme, but parentheses tire 
me after a while.


> Perhaps you want to just work with one length strings? str[0..1]
> instead of str[0].

I have done this some times. I presume I will need to use this more.

Bye and thank you,
bearophile


Re: Another Phobos2 test

2011-02-08 Thread Adam D. Ruppe
bearophile:
> I understand. But splitting lines too much make the code a bit
> too much thin.

I like it being thin so for me, it's a win/win.
I use small and split windows as well as
8 character tab stops. (4 characters just blend into the background..)

> I think a better solution is this request (from Lewis):
> http://d.puremagic.com/issues/show_bug.cgi?id=5521

That wouldn't help with runtime errors... and I don't think
it would help much for compile either, as a general rule.
Something like "cannot call function foo() with args abc" puts
you in the right place anyway, even on a pretty complex line.

> Currently the JSON data is not computed at compile-time, and it's
> written as file text on the disk, while a library is meant to not
> touch the disk. So the situation isn't good enough yet.

dmd -X -Xf- file.d

That dumps it to stdout, which you can pipe out to where it needs
to be. Though, getting it into the program being compiled might
be a little tricky without touching the disk. But then again,
does it really matter? The compile process writes files as
part of its normal operation anyway.

> An ubyte[] is a workaround for a type system not good enough yet.

I wouldn't say that it isn't good enough. It's just that you
and Andrei have a different philosophy about this.

> Reducing syntax noise in functional-style code is something that
> a lot of people wants (me too).

Remember, one man's noise is another's parsing anchors. For example,
I find an if without parens to just look... naked.


Re: Another Phobos2 test

2011-02-08 Thread bearophile
Adam D. Ruppe:

> I like it being thin so for me, it's a win/win.
> I use small and split windows as well as
> 8 character tab stops. (4 characters just blend into the background..)

I see. I prefer to see a chunk of code that does something, on the screen, and 
to not scroll too much.
For lot of time the common indent for Delphi code was of 2 spaces :-)


> That wouldn't help with runtime errors... and I don't think
> it would help much for compile either, as a general rule.
> Something like "cannot call function foo() with args abc" puts
> you in the right place anyway, even on a pretty complex line.

The column number of errors helps a little when you have lines of code like 
(and in other situations):

void main() {
int[2] f;
auto r = f[1] + f[2];
}


> > Currently the JSON data is not computed at compile-time, and it's
> > written as file text on the disk, while a library is meant to not
> > touch the disk. So the situation isn't good enough yet.
> 
> dmd -X -Xf- file.d
> 
> That dumps it to stdout, which you can pipe out to where it needs
> to be.

I meant something different. I don't want to convert JSON tree from-to text, 
I'd like to bypass the text representation fully. So the compile-time JSON 
Phobos library returns a data structure that represents the JSON tree (created 
by the compiler) in memory. There are zero files, stdout, pipes and text 
streams.


> Though, getting it into the program being compiled might
> be a little tricky without touching the disk. But then again,
> does it really matter? The compile process writes files as
> part of its normal operation anyway.

It matters if you want to use the JSON data in a larghish program as a static 
reflection mean to implement good user defined attributes. The less you convert 
and parse data, the faster and more usable the whole game is.


> > An ubyte[] is a workaround for a type system not good enough yet.
> 
> I wouldn't say that it isn't good enough. It's just that you
> and Andrei have a different philosophy about this.

I don't remember Andrei's opinion about that idea.


> > Reducing syntax noise in functional-style code is something that
> > a lot of people wants (me too).
> 
> Remember, one man's noise is another's parsing anchors. For example,
> I find an if without parens to just look... naked.

Removing some syntax noise is not a so optional thing in functional languages. 
In Haskell you often have code like:

vmoot xs = (xs++).map (zipWith (+) lxs). flip matmul r_90.
  map (flip (zipWith (-)) lxs) .reverse . init $ xs
   where lxs = last xs

If you start putting parentheses everywhere, you produce something less 
readable than Lisp.

I have never suggested to introduce optional parenthesis in D (the opposite: 
I'd like function calls to always require them in D), I have just suggested to 
replace two functions like array(map()) with amap().

Bye,
bearophile


Re: Another Phobos2 test

2011-02-08 Thread spir

On 02/08/2011 10:11 PM, bearophile wrote:

Adam Ruppe:


I'm still trying to find something I like for this.


Me too.


I like Adam's solution as well, but it's not perfect. The only other solution 
(like for constraints) would be a syntactic difference, but since we're limited 
by keyboard keys, this would instead certainly augment visual noise.



Error messages give a line number... but if there's still several
points of similar failure on that one line, it doesn't help as much
as it could.


I understand. But splitting lines too much make the code a bit too much thin. I 
think a better solution is this request (from Lewis):
http://d.puremagic.com/issues/show_bug.cgi?id=5521


Just done it for my parser. Once you get the line nr...


Maybe try ubyte[]?


There are moments when I want an array of ubytes, other moments when I want an 
array of 8 bit chars, and other situations where I want a string of chars. An 
ubyte[] is a workaround for a type system not good enough yet.


After some more interrogations on the topic, I think there should be 4 somewhat 
related types.
* Bytes --> processing of data at plain binary/numeric level, no link to text 
(eg pixmap)

* ByteString --> single-byte charset text (ascii, latin-X,...)
On the implementation side, there no difference in data structure (not even 
code check like for D chars). But conceptually and semantically, these types 
are unrelated. (It would be a bit strange for me to process a pixmap using a 
type that exposes tons of text-processing functionality.)

ByteString is, I guess, more or less what Steven proposed.
* D' utf-8 string for i/O of unicode text without any manipulation (except 
concat).
* A Text like what I proposed for unicode text manipulation, conceptually an 
array of univoque text-characters (an array of no-copy-slices into a normalised 
utf-8 string).



Though, on the other hand, I've used the ncurses library which does
this kind of thing. The number of function names is obscene, and
the benefit is quite small.


I agree that too many functions are going to give problems. But an "a" suffix 
is burden smaller than two names fully new.


I like your proposal. But -a suffixes are no good, use -Array or array- prefix 
instead.



I'm not convinced the parentheses are
a big deal. (Hell, I've done lisp before... and kinda liked it. :P)


Scala, Ruby, ML-class languages like Haskell, etc have means to reduce 
parentheses count. Reducing syntax noise in functional-style code is something 
that a lot of people wants (me too). I have used Scheme, but parentheses tire 
me after a while.


Editors do that for you, don't they? Even for languages they don't know... 
(never been annoyed by paren counts, not even in Lisp-like slangs)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Another Phobos2 test

2011-02-08 Thread spir

On 02/09/2011 01:35 AM, bearophile wrote:

I meant something different. I don't want to convert JSON tree from-to text, 
I'd like to bypass the text representation fully. So the compile-time JSON 
Phobos library returns a data structure that represents the JSON tree (created 
by the compiler) in memory. There are zero files, stdout, pipes and text 
streams.


Just what I would like to rip from a D parser in D (which doesn't prevent to 
write it into a D source module if useful).


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Another Phobos2 test

2011-02-08 Thread Adam D. Ruppe
bearophile:
> I see. I prefer to see a chunk of code that does something, on the > screen, 
> and
to not scroll too much.

That's what functions are for!

> I meant something different. I don't want to convert JSON tree
> from-to text, I'd like to bypass the text representation fully.

Yes, that would be the ideal implementation. But as a practical
matter, who's going to write that code? I don't know the compiler
well enough to do it myself, but I am confident that I could
write a little program to call and parse dmd -X; it's something
we could do ourselves without bugging Walter.

We need to look more at imperfect solutions we can do ourselves
with the existing tools than the perfect solutions that need
smart people like Walter and Don to do for us.

> It matters if you want to use the JSON data in a larghish program
> as a static reflection mean to implement good user defined
> attributes. The less you convert and parse data, the faster and
> more usable the whole game is.

If the build tool was sufficiently smart (something as simple
as plain old make is good enough for this), it could only parse
the json once.

Again not ideal, but something simple we could do ourselves.


On user defined attributes, I wish the @attrs were done differently,
but what's done is done and I don't know the compiler well enough
to write a patch.

Instead, we might look at some template ideas that define some
enums we can use to access the attributes. As I understand it,
Ruby does something similar to this too.

> I don't remember Andrei's opinion about that idea.

It's been discussed on the Phobos list pretty recently. Look
for the threads about new string types (I don't remember the
exact subject, but Steven did a lot of work on it so searching
for his name with the string keyword should find the thread.)

> If you start putting parentheses everywhere, you produce
> something less readable than Lisp.

Gah, that Haskell already is significantly less readable to Lisp!

Actually, on optional parens in D, I'm almost split on that. I
resisted dropping them from templates at first, but now I love
it. I like the property syntax just the way it is too (well,
usually. It's annoying when it calls the function when I don't
want it to though!)