Re: Pair literal for D language

2014-06-29 Thread Mason McGill via Digitalmars-d

On Saturday, 28 June 2014 at 21:12:06 UTC, Timon Gehr wrote:

On 06/28/2014 06:11 PM, Mason McGill wrote:

On Saturday, 28 June 2014 at 09:15:29 UTC, Dicebot wrote:

On Friday, 27 June 2014 at 22:01:21 UTC, Mason McGill wrote:
I like DIP54 and I think the work on fixing tuples is 
awesome, but I
have 1 nit-picky question: why is it called 
TemplateArgumentList

when it's not always used as template arguments?

void func(string, string) { }

TypeTuple!(string, string) var;
var[0] = I'm nobody's ;
var[1] = template argument!;
f(var);

Why not a name that emphasizes the entity's semantics, like
StaticList/ExpandingList/StaticTuple/ExpandingTuple?


Because it is defined by template argument list and has 
exactly the
same semantics as one. And semantics are unique and obscure 
enough

that no other name can express it precisely.


Understood. I was just expressing my initial impression: that 
it seemed
strange that a symbol declared as a `TemplateArgumentList` was 
neither

passed nor received as template arguments.


That would be strange, but it isn't.

TypeTuple!(string, string) var;
 ^
 passed here


alias TypeTuple(T...)=T; - aliased here
^~~~
received here

Hence:

TypeTuple!(string, string) var;
^~
this is actually the template argument list that was passed

In any case, I just call it 'Seq'.


I understand, but I was talking about `var` being referred to as
a `TemplateArgumentList` when it's not used as such. It's used as
an `ArgumentList`, just not a `TemplateArgumentList`.

Cheers,
Mason


Re: Pair literal for D language

2014-06-28 Thread Mason McGill via Digitalmars-d

On Saturday, 28 June 2014 at 09:15:29 UTC, Dicebot wrote:

On Friday, 27 June 2014 at 22:01:21 UTC, Mason McGill wrote:
I like DIP54 and I think the work on fixing tuples is awesome, 
but I have 1 nit-picky question: why is it called 
TemplateArgumentList when it's not always used as template 
arguments?


 void func(string, string) { }

 TypeTuple!(string, string) var;
 var[0] = I'm nobody's ;
 var[1] = template argument!;
 f(var);

Why not a name that emphasizes the entity's semantics, like 
StaticList/ExpandingList/StaticTuple/ExpandingTuple?


Because it is defined by template argument list and has exactly 
the same semantics as one. And semantics are unique and obscure 
enough that no other name can express it precisely.


Understood. I was just expressing my initial impression: that it 
seemed strange that a symbol declared as a `TemplateArgumentList` 
was neither passed nor received as template arguments.


Re: Pair literal for D language

2014-06-27 Thread Mason McGill via Digitalmars-d
I like DIP54 and I think the work on fixing tuples is awesome, 
but I have 1 nit-picky question: why is it called 
TemplateArgumentList when it's not always used as template 
arguments?


  void func(string, string) { }

  TypeTuple!(string, string) var;
  var[0] = I'm nobody's ;
  var[1] = template argument!;
  f(var);

Why not a name that emphasizes the entity's semantics, like 
StaticList/ExpandingList/StaticTuple/ExpandingTuple?


Re: Designing a matrix library for D

2014-06-24 Thread Mason McGill via Digitalmars-d

On Tuesday, 24 June 2014 at 04:36:04 UTC, ed wrote:

On Monday, 23 June 2014 at 21:08:03 UTC, Mason McGill wrote:
[snip]


Concepts:
 InputGrid: anything with a size (size_t[n]) and n-dimensional 
opIndex.
 OutputGrid: anything with a size (size_t[n]) and 
n-dimensional opIndexAssign.

[snip]


Cheers,
Mason


I don't think 'Grid' is not a good name for the type. The term 
Grid is generally used to refer to any sort of grid; regular, 
semiregular, irregular, unstructured, curvilinear etc. etc. 
grids.


When you're talking about sampling on a grid, warping can either 
be thought of as warping the grid, or warping the function to be 
sampled. My library happens to work in terms of the second 
approach, so it is (pedantically) consistent. I see your point, 
though.


They are all very different in their use and internal 
representations. Often a grid will have support for metadata at 
each point (GIS etc.) whereas a matrix will not.


I think the word Matrix is a better fit, because that is what 
they these types are.


Not quite. Matrix connotes 2-dimensional tensors (in the linear 
algebra sense). The library I'm developing at work is for 
manipulating multidimensional arrays, which don't have the same 
semantics people expect from matrices (representing linear 
operators). However, the name Array already refers to at least 
3 data structures in D, so it was out. I picked Grid because 
the library is for processing data sampled regularly on 
n-dimensional grids (mostly vision). With my library, you could 
represent complex data in a GIS via a grid of structures, or 
multiple grids (layers).


If you're not convinced, I intend to release my work under a 
liberal license, so feel free to download it and find/replace 
Grid - Matrix :)


Also, check out this other option if you haven't already:
http://denis-sh.bitbucket.org/unstandard/unstd.multidimarray.html


Re: Designing a matrix library for D

2014-06-23 Thread Mason McGill via Digitalmars-d

On Monday, 23 June 2014 at 16:45:28 UTC, bearophile wrote:
I'm glad to hear there's interest in this! I've actually been 
working on a generic multidimensional array library myself (on 
and off) for the past few months (I'm hoping to have a 
well-documented dub package by the end of the summer). It's a bit 
of a hybrid between Julia's `AbstractArray`, NumPy's `ndarray`, 
Numba, and std.range, and I think it has a very D feel.


It is, however, designed for processing sampled signals (rather 
than matrix algebra), which may be more or less in line with 
different people's interests.


Concepts:
  InputGrid: anything with a size (size_t[n]) and n-dimensional 
opIndex.
  OutputGrid: anything with a size (size_t[n]) and n-dimensional 
opIndexAssign.


Functionality:
  - Lazy `map` and `reduce`.
  - Lazy `zip` with built-in broadcasting.
  - Lazy n-dimensional convolution and cross-correlation.
  - Lazy sampling and interpolation.
  - `collect` to force evaluation.
  - Element-wise operators and and fancy indexing via mixins*.
  - Everyone's favorite MATLAB-style constructors
(`zeros`, `identity`, `meshGrid`, etc.)
  - Audio/Video and JSON I/O, via GStreamer (though this
probably ought to be a separate package).

*Because D doesn't allow UFCS for operators, which is silly, but 
that's the way it is.


Other features:
  - Compatibility with an automatic binding
generator I've been working on.
  - Testing, because I've been using this at work :)

If people want to use this, it might make sense to add linear 
algebra to this package rather than building a separate, 
incompatible algebra library (see this thread: 
http://comments.gmane.org/gmane.comp.lang.julia.devel/14533).


I did a lot of thinking about the level of abstraction that would 
be the most useful, and I settled on something like Julia's 
`AbstractArray` because it fits into D nicely (like ranges, but 
different!) and easily maps onto something that can be passed to 
other languages (a block of memory with size/strides metadata). 
As in Julia, I decided to make rank (`nDim!grid`) a compile-time 
entity since


1) Writing rank-branching code for NumPy is cumbersome and error 
prone; rank should be part of overload resolution.
2) It speeds up component-programming-style operations without 
requiring leaky abstractions (having to specialize on concrete 
grid types).


It's a busy week so I probably won't be able to follow this 
thread, but I wanted to let you know I was working on this to 
avoid duplicated efforts, etc.


Cheers,
Mason


Re: Time to rename D to @D !?

2014-06-23 Thread Mason McGill via Digitalmars-d
On Monday, 23 June 2014 at 20:34:59 UTC, Jonathan M Davis via 
Digitalmars-d wrote:
It would be very cool if we could remove @ from all of the 
built-in
attributes, but the whole reason that they have them in the 
first place is
because it was decided that we didn't want to add new keywords 
- and that was
several years ago when D had a smaller user base. So, I really 
don't see it
changing at this point. If anything, we might go the _other_ 
way and add @
onto the attributes that don't have it in order to make them 
more consistent
(though I hope that we don't do that, because it's ugly and 
more verbose).


People (I've talked to) seem to like Python decorators and Java 
annotations, and they have mandatory @ characters.


I like the @ because it helps me (and my editor) distinguish 
between words that *define* a computation (return type, 
parameters, etc.) and words that *describe* a computation 
(attributes).


Re: Designing a matrix library for D

2014-06-23 Thread Mason McGill via Digitalmars-d
On Monday, 23 June 2014 at 21:33:40 UTC, H. S. Teoh via 
Digitalmars-d wrote:
You are far from the first one to write a multidimensional 
array library
in D. Denis has already done this some time ago, and I have, 
too.


I've seen Denis' library. It seems nice, but it's a lot more 
concrete that what the original post was discussing. Is yours 
online somewhere (for inspiration)?


I've thought about this a lot, and my conclusion is that matrix 
algebra
is best left to a matrix-specific library wrapper that endows 
matrix
algebra properties on top of a generic multidimensional array 
type. The
main reason is that matrix algebra is rather peculiar to 
matrices
specifically, particularly the non-commutative matrix product, 
and does
not have very many useful usages outside of matrix algebra 
itself; yet

multidimensional arrays in general are useful in a wider scope.

So in my mind, there are several components that are needed 
here:
- A generic multidimensional array, as a data container. This 
can be a
  set of diverse concrete types, e.g. to represent sparse 
matrices,

  etc.. No domain-specific operations are specified for these
  containers; they are purely for storage and access only.

- Specialized array types, like matrices which add matrix 
algebra
  semantics to the underlying multidimensional array storage 
container
  (e.g., matrix product), or tensor wrappers (endows tensor 
product

  semantics on the underlying container).

- Algorithms: these take any multidimensional array, or 
specialized
  matrix type (depending on the purpose of each algorithm), and 
operate
  on them using a common multidimensional array API. They 
should be as
  generic as they can be, but no more, e.g., LU decomposition 
algorithms
  would take a matrix type rather than the general 
multidimensional
  array type, because it is specific to matrices, whereas 
per-element
  summation would take any general multidimensional array type, 
since it

  doesn't need matrix-specific properties. Similarly, subarray
  operations should be able to work with any multidimensional 
array
  type, since it simply provides a restricted view on the 
underlying

  storage container, but doesn't depend on the implementational
  specifics of the container itself.


Seems reasonable.

I think the best solution would be a generic multidimensional 
concept

(analogous to the input range concept) that will fit all of our
multidimensional array implementations. Algorithms that can 
work with
diverse ranks shouldn't care if the rank of a particular 
concrete type

is compile-time or runtime, for example. Let the algorithms be
adaptable (up to practicality, of course -- if an algo can't 
work or

works very poorly with dynamic rank, then just add a
constraint that
requires static rank, for example), and the user can choose 
which

concrete type(s) best suits his needs.


One possible issue with dynamically-ranked grids is 
concept-testing. `isInputGrid!Collection` needs to check if 
`Collection` has a `size` property, and can be indexed with 
`size.length` indices. If this is to be done at compile-time, 
`size.length` needs to be constant.


The concrete types can then be provided by a separate module, 
and if we

do it right, should be interoperable with each other.


Definitely an important design goal. You seem quite knowledgeable 
on this topic and I hope we can continue this conversation when 
my work on this is further along.


Re: Why does this work?

2014-06-23 Thread Mason McGill via Digitalmars-d-learn

On Monday, 23 June 2014 at 08:30:44 UTC, h_zet wrote:

import std.typecons;

auto foo2(R)(R foopara){
return tuple(foopara, is(R==int));
}

void main(){
auto tuple(a,b) = foo2(1);
}


I'm expecting some error such as can not act as left value but 
when I compiled this, no error occured. DMD version is DMD64 
v2.065.(ldc2 exited with error function declaration without 
return type)


Why does this work? Or it is a bug?


Strange behavior, indeed. It took me a minute, but I think I know 
what's going on, and I'm pretty sure it's a bug. D recently 
introduced a short syntax for function-like templates:


  enum a(b) = some_value;

It looks like this also (sort of) works with other qualifiers, 
which I believe it shouldn't. Here's a minimal example that might 
be good to put in a bug report:


  void main() {
  enum a(x) = some_value; // Good.
  auto b(x) = some_value; // Huh?
  // This also works for `const`, `static`, etc.
  }


Re: Why does this work?

2014-06-23 Thread Mason McGill via Digitalmars-d-learn

On Monday, 23 June 2014 at 09:29:15 UTC, Mason McGill wrote:
Strange behavior, indeed. It took me a minute, but I think I 
know what's going on, and I'm pretty sure it's a bug. D 
recently introduced a short syntax for function-like templates:


  enum a(b) = some_value;

It looks like this also (sort of) works with other qualifiers, 
which I believe it shouldn't. Here's a minimal example that 
might be good to put in a bug report:


  void main() {
  enum a(x) = some_value; // Good.
  auto b(x) = some_value; // Huh?
  // This also works for `const`, `static`, etc.
  }


It looks like I'm mistaken. Variable templates are supposed to 
exist. Please ignore the previous post.


Re: nothrow function callbacks in extern(C) code - solution

2014-06-22 Thread Mason McGill via Digitalmars-d
On Thursday, 19 June 2014 at 23:41:25 UTC, H. S. Teoh via 
Digitalmars-d wrote:
Pretty soon, we need an attribute algebra to express these 
complicated

relationships.

It would be nice to have a solution that can handle all of 
these cases

without exploding complexity in the syntax.


Here's one idea:

Attributes can be thought of as declarative compile-time 
parameters--they don't directly define a computation, but they 
feel like compile-time parameters in that

  - They are variable in number.
  - They may take on many possible values.
  - They may be parameterized (like `extern`).
  - They play a role in overload resolution.
  - Their combinations may lead to combinatorial explosions
that can hopefully be mitigated with metaprogramming.

My point is, many of the problems we're encountering with 
attributes have already been solved (via templates, tuples, CTFE, 
`static if`, etc.)


Attribute propagation would be simple (not trivial, but 
appropriately simple) for user-defined attributes, because they 
can be arbitrary expressions. If built-in attributes were just 
treated as pre-defined symbols, they could be manipulated with 
templates and CTFE:


  enum mayThrow(alias func) =
  staticIndexOf!(nothrow, functionAttributes!func) == -1;

  template throwsLike(alias func) {
  static if (mayThrow!func)
  enum throwsLike = tuple().expand;
  else
  enum throwsLike = nothrow;
  }

  void call(alias func)() @throwsLike!func {
  func();
  }

(This thread may be relevant:
http://forum.dlang.org/thread/hfmulninvghjntqkp...@forum.dlang.org)


Re: DIP64: Attribute Cleanup

2014-06-21 Thread Mason McGill via Digitalmars-d

On Friday, 20 June 2014 at 22:01:31 UTC, Timon Gehr wrote:

On 06/20/2014 09:22 PM, Brian Schott wrote:

http://wiki.dlang.org/DIP64

Attributes in D have two problems:
1. There are too many of them and declarations are getting too 
verbose

2. New attributes use @ and the old ones do not.

I've created a DIP to address these issues.


Why not make the built-in attributes proper symbols instead and 
use


alias Seq(T...)=T;
alias spiffy = Seq!(pure,nothrow,safe);

float mul(float a, float b) @spiffy{ }

?

This will also allow use cases such as passing attributes by 
alias.


I think this would make the language a lot cleaner, and can be 
taken even further:


  @extern(C++, some.namespace)
  class C {
@private int x;
  }

Here `extern` is a regular function that returns an instance of 
some compiler-defined type. This makes built-in attributes just 
particular cases of properties (that happen to be recognized by 
the compiler).


Attribute and property are pretty much synonyms in English, 
and it always seemed strange to me that D had to define them as 
different--yet confusingly similar--entities.


Re: DIP64: Attribute Cleanup

2014-06-21 Thread Mason McGill via Digitalmars-d
On Sunday, 22 June 2014 at 05:18:05 UTC, Jonathan M Davis via 
Digitalmars-d wrote:

On Sun, 22 Jun 2014 00:12:20 +
Mason McGill via Digitalmars-d digitalmars-d@puremagic.com 
wrote:



Attribute and property are pretty much synonyms in English,
and it always seemed strange to me that D had to define them as
different--yet confusingly similar--entities.


They're not even vaguely similar in D. A property is a member 
of a struct or
class which is a variable or a function which emulates a 
variable, whereas
attributes are annotations put on symbols (currently just 
classes, structs,
and functions AFAIK) which indicate extra information to the 
compiler and to

type introspection.

So, while I can see why you might dislike the fact that 
attribute and property
do not mean the same thing in D, they're _not_ at all similar 
it how they're
used, so I find it very odd if anyone is confusing them. And 
it's not like D
pioneered these meanings for attributes and properties. C# uses 
them for the

same things.

- Jonatahn M Davis


I was referring to the `Property` and `PropertyIdentifier` 
entities in the D grammar (http://dlang.org/attribute.html), 
which are special cases of attributes. New-style attributes, 
like property, safe, and nogc, are `PropertyIdentifier`s 
and need to be written with the @ character. Older, 
non-property attributes, like pure and nothrow, do not.


Sorry if this wasn't clear in the former post.


Re: async/await in F#

2014-06-14 Thread Mason McGill via Digitalmars-d
Good tutorial choices; they're very well-written. I haven't used 
F# much, but here's my take (call me out on any mistakes in my 
understanding):


`async` being just a particular instance of a class of 
user/library-defined computation expression has a lot of good 
things going for it. This setup provides an alternative to nested 
lambda expressions that's more readable in some cases. And it's 
far more future-proof than C#'s approach.


There was one thing I didn't like about monadic F#: it's hard to 
read without being intimately familiar with the workflow you 
are using (e.g. `async`). If I see a `for..do` expression inside 
an `async` block, I don't know whether `async` has overridden 
that syntax unless I open up the `async`'s documentation. It 
seems this is easily side-stepped by using explicit syntax (e.g. 
`for!` instead of `for`), which makes me wonder why the F# 
designers made some of the syntax overrides stand out (`let!` and 
`do!`), but not others (`return` and `while..do`).


Finally, I wonder what happens if you nest computation 
expressions:


  async {
query {
  /* Code for an asynchronous query. */
}
  }

My guess it that the inner workflow (`query`) transforms the code 
inside it, then passes the result to the outer workflow, which 
then transforms it further. This could get confusing quickly, but 
I suppose you'd only write something like this if it was the best 
way to express your intent, which means the alternatives were 
*more* confusing.


Re: foreach

2014-06-12 Thread Mason McGill via Digitalmars-d
On Thursday, 12 June 2014 at 15:00:20 UTC, Manu via Digitalmars-d 
wrote:

I often find myself wanting to write this:
  foreach(; 0..n) {}
In the case that I just want to do something n times and I don't
actually care about the loop counter, but this doesn't compile.

You can do this:
  for(;;) {}

If 'for' lets you omit any of the loop terms, surely it makes 
sense

that foreach would allow you to omit the first term as well?
I see no need to declare a superfluous loop counter when it is 
unused.


Seems like a nice idea. Especially useful when it comes to 
reading other people's code:


  foreach (i; 0..n)
  {
  some();
  long();
  list();
  of();
  tasks();
  }
  // I always double back--wait, where did they use `i`?


Re: Optionally strongly typed array indexes

2014-06-06 Thread Mason McGill via Digitalmars-d
On Friday, 6 June 2014 at 20:22:35 UTC, Philippe Sigaud via 
Digitalmars-d wrote:

Sorry to intrude, but you can also get:

enum newton = 1.kg/m/s^^2;


Good point. I actually learned D had an exponentiation operator 
just yesterday. It definitely helps readability in this case.


Re: Optionally strongly typed array indexes

2014-06-05 Thread Mason McGill via Digitalmars-d

On Thursday, 5 June 2014 at 09:23:00 UTC, bearophile wrote:

Sorry for my answers coming so slowly.


Hah! I'm on these forums (selfishly) trying to understand/improve 
D for my own use at work, while you seem to be 
helping/teaching/contributing for the sake of it. I'm continually 
surprised by how pleasant and professional this community is; 
nothing at all to be sorry for!



void main() {
import std.stdio;
foreach (i; 0 .. 10) {
writeln(i);
i++;
}
}

Currently this prints just the even numbers, I think this is a 
little weird.


That is weird. It goes counter to the idea of `i` coming from 
the range. Though, I'd say someone writing that code is asking 
for strange behavior, so it's not much of an issue.



Generally in my D code I write like this, as explained here:
http://blog.knatten.org/2011/11/11/disempower-every-variable/


I agree, with the caveat of trying to not add so much noise 
that it becomes unreadable.


Immutable by default is probably the right choice for a modern 
language.


Yes, or at least making operations with side effects look 
different from operations without.


I think this is one part of the larger problem of representing 
units.


Units of measure introduce a good amount of complexity and 
logic that is absent in the idea of giving strongly types to 
array indexes.


You don't need to convert inches to centimetres,


True.

You don't need to perform a compile-time dimensional analysis 
for the correctness of expressions.


I'd argue you do, at least given my understanding of the goals of 
strongly-typed array indices. For example, consider strided 
indexing:


  const dogs = [Rover, Fido, Rex].of!dog;
  const cats = [Fluffy, Mr. Whiskers].of!cat;

  // This should work.
  const i1 = index!dog(1);
  dogs[i1];

  // This should not work.
  const i2 = index!cat(1);
  dogs[i2];

  // This should work.
  const i3 = 2 * i1;
  dogs[i3];

  // This should not work.
  const i4 = i2 * i1;
  dogs[i4];

So, the library needs to do some form of dimensional analysis to 
allow typed indices to be multiplied by unit-less scalars, but 
not scalars with units.


You don't need to keep in mind the 0-based problems of 
converting Celsius to Fahrenheit.


True. This is why I said the problem of strongly typed array 
indexes is *part* of the problem of units, not equivalent to it.


You don't need to solve the syntax problems of attaching m / 
s somehow to number literals.


Also true, though as a side note, I think a library solution for 
this could be quite nice:


  enum newton = 1.as!kg*m/s^2;  // One possibility.
  enum newton = 1*kg*m/square(s); // Another.


though I'll have to think about whether it covers all
the cases you're interested in.


Another problem is visible in this code, I have a function 
bar() that must receive a different value for each item of the 
enum Foo. If I use an associative array, the compiler doesn't 
catch at compile-time the bug of the missing Foo.B case:



enum Foo : ubyte { A, B }
void bar(int[Foo] aa) {}
void main() {
bar([Foo.A: 10]);
}


And often using an associative array for this purpose is a 
waste of memory and computation.


The Ada compiler is able to catch this bug at compile-time, 
using a simple fixed-size array (exactly as long as the number 
of items in the enum) with indexes strongly typed as Foo. So 
the array literal must contain all possible indexes only once:



import std.traits: EnumMembers;
enum Foo : ubyte { A, B }
void bar(int[@typed(Foo) EnumMembers!Foo.length] input) {}
void main() {
bar([Foo.A: 10, Foo.B: 20]);
}


If you give a strong type to the array index you avoid that bug 
at compile time. (To be accepted as index type, an enumeration 
must behave nicely, all such tests can be done at compile-time).


That's quite clever, though couldn't it also be done with a 
library?


  enum Foo : ubyte { A, B }
  enum nFoo = EnumMembers!Foo.length;
  alias AllFoo = WithUnits!(int[nFoo], Foo);

  void bar(AllFoo) {}

  void main() {
  bar(AllFoo([/*A*/ 10, /*B*/ 20]));
  }


Re: Optionally strongly typed array indexes

2014-06-04 Thread Mason McGill via Digitalmars-d

On Wednesday, 4 June 2014 at 09:43:20 UTC, bearophile wrote
You can give strong typing to indexes of a matrix library, this 
doesn't need language changes. So a dynamic array library in 
Phobos could fulfil most of the possible desires or needs for 
strongly typed indexes. But you lose some of the convenience of 
the built-in arrays, and you have to import a bulky library 
that you are mostly not using.
I see several places in all kinds of D code where strongly 
typed indexes can help tell things apart more clearly and 
safely, but I think only in some of such situations programmers 
are willing to import a numpy-like library just to have strong 
typing.


I'll have to check out Ada to get a sense of how this feature 
works and how people use it.


In D learn I see that people don't even add immutable to the 
foreach variable that spans an interval.


I noticed you did that, though I haven't seen this much on 
Dlang.org. Is this considered idiomatic? Coming mostly from 
JavaScript/Python/CUDA C++ I'm not sure how I feel about the 
terseness/safety trade-off (I can honestly see it both ways).


So I don't expect people to import numpy just to give types to 
two indexes of two 1D arrays. And statistically I think such 
cases of just two or tree 1D arrays are much more common than 
numerical code that manages several matrices with a good matrix 
library.


Good point. Though, I don't think adding compiler support for 
strongly typed array dimensions is the full solution. I think 
this is one part of the larger problem of representing units. 
Other languages have solutions to this (I particularly like F#'s: 
http://en.wikibooks.org/wiki/F_Sharp_Programming/Units_of_Measure), 
and it would be very nice to see something this in Phobos:


  /* User code. */
  import std.awesome_unit_library: Unit, of;
  // Unit: defines new types that can be multiplied  divided.
  // of: wraps a container in a stricter version, enforcing units.

  alias Name = Unit!name;
  alias Food = Unit!food;
  auto names = [Fred, Alice, Sue].of!Name;
  auto foods = [Apple, Orange, Tofu].of!Food;

  foreach (name; [Bill, Ted].of!Name)
  {
  names ~= name; // This compiles happily.
  foods ~= name; // This does not compile, preventing
 // Bill and Ted from being eaten.
  }


Re: Optionally strongly typed array indexes

2014-06-04 Thread Mason McGill via Digitalmars-d

On Wednesday, 4 June 2014 at 18:46:04 UTC, Mason McGill wrote:

  /* User code. */
  import std.awesome_unit_library: Unit, of;
  // Unit: defines new types that can be multiplied  divided.
  // of: wraps a container in a stricter version, enforcing 
units.


  alias Name = Unit!name;
  alias Food = Unit!food;
  auto names = [Fred, Alice, Sue].of!Name;
  auto foods = [Apple, Orange, Tofu].of!Food;

  foreach (name; [Bill, Ted].of!Name)
  {
  names ~= name; // This compiles happily.
  foods ~= name; // This does not compile, preventing
 // Bill and Ted from being eaten.
  }


You could actually just let the `of` template create the `Unit` 
type for you, if you want to be terse:


  import std.awesome_unit_library: of;

  auto names = [Fred, Alice, Sue].of!name;
  auto foods = [Apple, Orange, Tofu].of!food;

  foreach (name; [Bill, Ted].of!name)
  {
  names ~= name; // This compiles happily.
  foods ~= name; // This does not compile, preventing
 // Bill and Ted from being eaten.
  }

It looks like this library solution puts user work at or below 
the level of your proposed syntax, though I'll have to think 
about whether it covers all the cases you're interested in.


Operator/concept interoperability

2014-06-03 Thread Mason McGill via Digitalmars-d
I have a numerical/multimedia library that defines the concept of 
an n-dimensional function sampled on a grid, and operations on 
such grids. `InputGrid`s (analogous to `InputRange`s) can be 
dense or sparse multidimensional arrays, as well the results of 
lazy operations on other grids and/or functions 
(map/reduce/zip/broadcast/repeat/sample/etc.).


UFCS has been extremely beneficial to my API, enabling things 
like this:


  DenseGrid!(float, 2) x = zeros(5, 5);
  auto y = x.map!exp.reduce!max;

without actually defining `map` inside `DenseGrid` or `reduce` 
inside `MapResult`. `map` and `reduce` are defined once, at 
module scope, and work with any `InputGrid`.


As this is numerical code, it would be great to be able to do 
this with operators, as is possible in C++, Julia, and F#:


  auto opUnary(string op, Grid)(Grid g) if (isInputGrid!Grid)
{ /* Enable unary operations for *any* `InputGrid`. */ }

  DenseGrid!(float, 2) x = zeros(5, 5);
  auto y = -x;

This is currently not supported, which means users of my library 
get functions like `map` and `reduce` that work out of the box 
for any grids they define, but they need to do extra work to use 
convenient operator syntax for NumPy-style elementwise 
operations.


Based on my limited knowledge of DMD internals, I take it this 
behavior is the result of an intentional design decision rather 
than a forced technical one. Can anyone explain the reasoning 
behind it?


Also, does anyone else have an opinion for/against allowing the 
definition of operators that operate on concepts?


Thanks for your time,
-MM


Re: Operator/concept interoperability

2014-06-03 Thread Mason McGill via Digitalmars-d

On Tuesday, 3 June 2014 at 22:05:29 UTC, TheFlyingFiddle wrote:

Well one reason for this is that unlike methods it is hard to
resolve ambiguity between diffrent operator overloads that have
been defined in diffrent modules.

Example: 2D-vectors
//vector.d
struct Vector
{
float x, y;
}

//cartesian.d
Vector opBinary(string op : +)(ref Vector lhs, ref Vector rhs)
{
   //Code for adding two cartesian vectors.
}

//polar.d
Vector opBinary(string op : +)(ref Vector lhs, ref Vector rhs)
{
//Code for adding two polar vectors.
}

//main.d
import polar, vector;
void main()
{
auto a = Vector(2, 5);
auto b = Vector(4, 10);

auto c = a + b; //What overload should we pick here?

//This ambiguity could potentially be resolved like this:
auto d = polar.opBinary!+(a, b);
//But... This defeats the whole purpose of operators.
}


Interesting point. However, I believe this is also the case for 
ordinary functions used with UFCS:


  // cartesian.d
  Vector add(ref Vector lhs, ref Vector rhs)
{ /* Code for adding two cartesian vectors. */ }

  // polar.d
  Vector add(ref Vector lhs, ref Vector rhs)
{ /* Code for adding two polar vectors. */ }

  // main.d
  import polar, vector;
  void main()
  {
  auto a = Vector(2, 5);
  auto b = Vector(4, 10);
  auto c = a.add(b); // What overload should we pick here?

  // The fully qualified form looks quite different,
  // but it's rare, and intentionally explicit about what's
  // really going on, so that's OK.
  auto d = polar.add(a, b);
  }

It strikes me that ambiguous cases are not nearly as common as 
unambiguous cases, especially if you use selective imports.


I believe Julia uses a re-write rule for its operators: the first 
thing the compiler does when evaluating an operator expression is 
re-write it as a function call; after that, all the language's 
resolution rules apply as they would to any other function call. 
D could easily take this approach, simplifying the language while 
maintaining backwards-compatibility.



Side note:

You can achieve what you want to do with template mixins.

...

While this implementation is not as clean as global operator
overloading it works today and it makes it very simple to add
operators to new types of grids.


Thanks for the example. This is actually my current solution :) 
However, as you allude to, I'm not a huge fan of it because


1) It requires boilerplate on the part of library users.
2) It makes you scratch your head and go Huh; operator and 
non-operator functions have different compile-time polymorphism 
capabilities; why is that?


Re: Optionally strongly typed array indexes

2014-06-03 Thread Mason McGill via Digitalmars-d
Interesting idea. I run into these sorts of bugs often doing 
multimedia processing. There's definitely a tension between 
writing generic code (NumPy-style, operating on abstract 
dimensions) and safe code (operating on dimensions with 
semantics; OpenCV supports this to an extent). I've never used 
Ada so I may be missing the point, but here are my impressions:


It seems to me that the users who may benefit most from this 
feature are likely to be using non-built-in data structures. For 
example, you mention interpreting the first level of array 
nesting as rows and the second as columns, implying you are 
treating the nested arrays as a matrix (rather than a list of 
lists, boxes of kittens, etc.). I'm inclined to believe use-cases 
for strongly-typed indices would often overlap with use-cases for 
strongly-typed containers. If that is true, then the language 
already provides decent support for annotating indices with 
units:


  /* Deep in the belly of some image-processing library... */
  alias Row = Dimension!row;
  alias Column = Dimension!column;
  alias Channel = Dimension!channel;
  alias Image = DenseGrid!(ubyte, row column channel);

  /* In user code... */
  Image image = drawPrettyPicture();
  ubyte r = image[Row(0), Column(0), Channel(0)];
  ubyte g = image[Row(0), Column(0), Channel(1)];
  ubyte b = image[Row(0), Column(0), Channel(2)];

  /* Or if you want to get really fancy... */
  enum red = Channel(0), green = Channel(1), blue = Channel(2);
  ubyte r = image[Row(0), Column(0), red];
  ubyte g = image[Row(0), Column(0), green];
  ubyte b = image[Row(0), Column(0), blue];

  /* Depending on how DenseGrid.opIndex is defined,
 these statements could fail to compile... */
  image[Column(0), Row(0), red];
  image[blue, Row(0), Column(0)];

Speculation: A good behavior for such a `DenseGrid.opIndex` might 
allow untyped (size_t) indices for generic algorithms and users 
who can't be bothered, but reject incorrectly-typed indices (e.g. 
a `BoxOfKittens` should not be indexed with a `Row`, just as an 
`Image` should not be indexed with a `CatName`.


Re: More useful fixed-size array literals

2014-05-30 Thread Mason McGill via Digitalmars-d

On Friday, 30 May 2014 at 22:19:51 UTC, bearophile wrote:
A language solution is a literal syntax for fixed-sized arrays 
(here I slice it again because unfortunately count doesn't 
accept fixed-sized arrays):



immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
import std.algorithm: count;
assert(data.count([1, 5]s[]) == 3);
}


I would use this often. It's always seemed strange to me that 
static arrays are one of the few built-in data structures that 
don't have a dedicated literal form. `[1, 2, 3]s` nicely 
parallels the syntax for string and number literals.


Re: New syntax proposal for template type parameter contraints

2014-05-17 Thread Mason McGill via Digitalmars-d
On Saturday, 17 May 2014 at 01:53:46 UTC, Steven Schveighoffer 
wrote:

A possible solution:

template interface isInputRange(T, E) { .. No change in 
implementation .. }


void myTemplateFunction(T : isInputRange!int)(T t)
{
}

would basically change this into the equivalent of today's 
constraints. however, given that the template parameter is 
coupled with the constraint more directly, a better error 
message could be created, e.g. Type MyNonRangeType does not 
satisfy template interface isInputRange!int.


I like this, but may I suggest a slightly different approach: to 
parallel structures, classes, interfaces, etc., concepts could be 
defined as nouns. This avoids the need to define dummy type 
parameters (T, above) and construct lvalues from them. It also 
sidesteps the awkward is-typeof-lambda idiom:


  static interface InputRange(E)
  {
  // This code must compile for any InputRange!E.
  bool empty = this.empty;
  E front = this.front;
  this.popFront();
  }

  void f1(T : InputRange!int)(T) { }
  void f2(E, T : InputRange!E)(T) { }

This parallels the existing (declarative) notion of template 
specialization. With this scheme, one could also overload 
concepts:


  static interface InputRange
{ static assert(is(typeof(this)  InputRange!E, E)); }

  // For the common case in which we don't need to name
  // the element type:
  void f3(T : InputRange)(T) { }



Re: Abstract DDoc output for better document generation

2014-05-17 Thread Mason McGill via Digitalmars-d

On Saturday, 17 May 2014 at 18:03:53 UTC, Tolga Cakiroglu wrote:

After having some experience with documentation generation from
dmd command like, and seeing outputs, I wasn't satisfied with 
it.

Other alternatives as Doxygen is available, though it parses
codes itself that is not based on what version of DMD is
installed on system.

Since the structure of DDoc is already defined, instead of
generating HTML output, I would propose to generate an XML file
that contains meta data about codes and comments which can be
used by 3rd party documentation generator programmes to generate
HTML files. This way DDoc definitions can be simplified, better
looking documents can be generated much easily.


Try compiling with the -X flag to generate a JSON file describing
the source. Add the -D flag if you want documentation comments in
the JSON output.

Hope that helps!


Re: Suggestion to implement __traits(getImports, Scope)

2014-05-09 Thread Mason McGill via Digitalmars-d

On Friday, 9 May 2014 at 04:09:46 UTC, captaindet wrote:
by coincidence, i have use for this too. also thought 
__traits(allMembers, ...) would work. too bad it doesn't. is 
this a bug or expected behavior?


/det


Just out of curiosity, what's your use case?


Re: Julia vs. D?

2014-05-07 Thread Mason McGill via Digitalmars-d

On Tuesday, 6 May 2014 at 21:00:18 UTC, bearophile wrote:
The language tries its best to be flexible as a dynamic 
language. But variables never carry a run-time type tag, unlike 
in Lisp.


Hmm... Then how can I do this:

  x = 5
  typeof(x) # evaluates to Int64
  x = 5.0
  typeof(x) # evaluates to Float64

?

Is Julia doing something trickier than I think it is? Or do you 
just mean they don't carry type tags after compilation?


Re: A Briefer Syntax for Using Concepts

2014-05-07 Thread Mason McGill via Digitalmars-d

On Wednesday, 7 May 2014 at 11:57:51 UTC, w0rp wrote:
Here is a question, is it possible for D, or any future 
language, to eventually take something like this...


void foo(InputRange)(InputRange range) 
if(isInputRange!InputRange);


...and to instead be able to write it like this?

void foo(InputRange range);

Where the latter expands into something like the former, and 
InputRange is not a type. How to declare such a thing in the 
first place doesn't matter that much. There are many ways that 
could be done. I'm just wondering if the above is possible at 
all.


I think Julia does something like this, under the hood. Julia 
functions are instantiated once for every concrete argument type 
tuple they are invoked with:


  f(x) = x + 2
  f(5) # Instantiation for Int64
  f(5.0)   # Instantiation for Float64

The assembly for these instantiations can be inspected by calling 
`code_native`. This works well for Julia because its runtime and 
type system are designed around being able to do this (JIT 
compilation, multiple dispatch, duck typing, immutable types).


Programmers try to use run-time and compile-time polymorphism for 
the same thing: expressing operations on abstract types. But, 
each approach has its own advantage (CT: speed; RT: dynamic 
dispatch). I think the key insight is that the optimal 
implementation (RT vs. CT) depends only on how the generic 
function is used, not how it is defined. So, the choice of 
implementation can, in theory, be left up to a 
sufficiently-sophisticated runtime/JIT compiler. This seems to be 
what Julia has done (possibly along with some other Lispy 
languages; I'm not sure).


However, this scheme can't entirely replace D-style templates 
(e.g. pattern matching). So, Julia still lets you define 
templates (which they call objects with static parameters).


It would be great to have something like this in D (with 
compile-time semantics, of course).


Re: A new trait to retrieve doc comments (if available).

2014-05-06 Thread Mason McGill via Digitalmars-d

Thanks for the feedback!

On Tuesday, 6 May 2014 at 07:41:20 UTC, bearophile wrote:

Mason McGill:


Other implementations can choose to always evaluate it to .


Other implementations have to give the ddostring as well.


Good to know! This will simplify the entry in the Traits 
documentation page.



In D modules too have a ddoc string.

Regarding comments on single variables, like this, I think they 
can be ignored for the moment, and added later with the same 
API if needed:


int foo = 5; /// Not a string.


It appears DMD already extracts module and variable comments.  
The JSON output for the following code associates all 3 comments 
with the appropriate symbols (compiled with dmd -D -X -o- 
test.d).


/**
 * This is the test module.
 */
module test;

const x = 5; /// This is x.

/**
 * This is the main function.
 */
void main() {}

So, it seems `__traits(comment, symbol)` should work for any 
symbol, at least the way I plan to implement it. This seems like 
the most useful behavior.


Re: Julia vs. D?

2014-05-06 Thread Mason McGill via Digitalmars-d

On Tuesday, 6 May 2014 at 11:28:21 UTC, Chris wrote:
Maybe it's time to think about a D interface to Julia. If Julia 
catches on within the scientific community, it would be good to 
have a foot in the door. Science quickly creates large code 
bases, unfortunately, so far it's mostly Python and Matlab 
which makes it hard to use the algorithms in real world 
applications.


I've actually been working on just that, on and off for a few 
months now. Such a thing is kind of anti-Julian, though, since 
one of Julia's main goals is to reduce or eliminate the need for 
mixed-language projects.


However, with D, you can compile small shared libraries that can 
be automatically bound to your users' favorite dynamic runtimes 
(via compile-time reflection). I'm hoping this will be good for 
both D and Julia, allowing library developers to reach a broader 
audience, and library consumers greater flexibility.


I'll post on the D announce thread when I have something 
working, and I'd definitely appreciate tests/bug-reports at that 
time!


Re: A new trait to retrieve doc comments (if available).

2014-05-06 Thread Mason McGill via Digitalmars-d

This is now a pull request:
https://github.com/D-Programming-Language/dmd/pull/3531


A new trait to retrieve doc comments (if available).

2014-05-05 Thread Mason McGill via Digitalmars-d
**I'm fairly new to D, so let me know if this belongs in another 
thread.**


I'd like to contribute a new feature to the DMD front-end, and 
I'd appreciate some feedback on the design before I start on a 
pull request.


Feature:

`__traits(comment, symbol)` will evaluate to the doc-comment of 
`symbol`, if it is available, and , otherwise. For DMD, this 
means it will provide comment information if the -D compiler 
option is used. Other implementations can choose to always 
evaluate it to .


Use Cases:
==
Here's my use case: I'm building an automatic wrapper generator 
for binding D to dynamic languages (mostly for scientific 
applications, at the moment). It's like SWIG, but more automated 
and narrower in scope.  Right now, I have two suboptimal options 
for supporting documentation comments:


1) Have users put their documentation in UDAs (instead of 
comments), and extract those.  This means departing from D style 
guidelines, and that DDOC doesn't work.


2) Dig comments out of DMD's JSON output.  This means users have 
to inform the wrapping tool of all of their D source files (not 
just a shared library), complicating build setups.  It also means 
DMD loads and parses each file twice.


Having doc-comments accessible at compile time would let me 
simplify the wrapping process for my users.


Other applications include metaprogramming (e.g. forwarding 
documentation from a template argument) and simplifying 
documentation generators. I'm sure having doc-comments accessible 
in Python made things like Sphinx and IPython easier to build.


Implementation:
===
I'm not too familiar with DMD, but it seems like evaluating 
`__traits(comment, symbol)` would just require reading out the 
relevant `DSymbol`'s `comment` field.


Alternatives:
=
Alternative names:
- `__traits(getComment, symbol)`
- `__traits(documentation, symbol)`
- `__traits(getDocumentation, symbol)`

Alternative behaviors:
- `__traits(comment, symbol)` could evaluate to `null` (rather 
than ) if there is no comment associated with `symbol`.


Thoughts?