Re: opPow, opDollar
Walter Bright wrote: Andrei Alexandrescu wrote: In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for automatic loop fusion that would tilt my opinion in disfavor of ^^, and if not, it would tilt my opinion in favor of ^^. I don't think this is a valid argument for making pow() an operator, because what about sin()? cos()? It's all the same issue, and they all can't be operators. Exponentiation, like addition, multiplication etc.. can be used multiple times in an expression at the same scope: a + b + c a * b * c a ^^ b ^^ c xor, sin, cos are only binary & unary operations. I think that is a good enough argument for which deserves operator over long function name but unlike the others, exponentiation is right associative so this should mean the same as: a ^^ (b ^^ c) This may also reduce the likely hood of bugs due to mathematical formulas being expressed incorrectly. It is far too easy to accidentally write: a ^^ b ^^ c as pow(pow(a,b),c) This one operator would really help D be accepted into the mathematical world.
Re: opPow, opDollar
On Sat, Nov 7, 2009 at 20:22, dsimcha wrote: > == Quote from Robert Jacques (sandf...@jhu.edu)'s article > > I'd recommend rolling that into a basic statistics struct containing > > common single pass metrics: i.e. sum, mean, variance, min, max, etc. > > I've been wondering for a while if something like this is general enough > for > non-statisticians and a good candidate for Phobos: > > http://svn.dsource.org/projects/dstats/docs/summary.html > > Good? Overkill? Too niche? > Oh nice. Though I'll probably never use dstats in its globality, I'll most certainly use this summary module. Having a small std.stats module inserted into phobos doesn't strike me as overkill or too niche, but maybe I'm biased. I'm sure everyone here use less than a dozen modules on most projects. I mean, I never do sockets, xml, GUI, ... But I intensively use std.functional, algorithm, traits, range, typecons, typetuple, array, ...
Re: opPow, opDollar
On Sat, Nov 7, 2009 at 17:33, Pelle Månsson wrote: > I am all in favor of adding convenience functions sum and product to > phobos. I use them both often enough. > vote++ And also min (on a range), max (on a range). Those are simple one-liners, though they can create some name-shadowing problems and are dubious with empty ranges. ElementType!R min(R)(R range) { enforce(!range.empty, "Don't use min on an empty range."); return reduce!(std.algorithm.min)(ElementType!R.max, range); } Maybe R doesn't have elements with a .max property, but then the same remark can be used on sum/product (0 or 1 are not necessarily the neutral elements for + and * on your struct/class). For specific structures, use your own sum function. Some other languages also have and( on a boolean range) and or( on a boolean range), though I never use them. They are slightly different from reduce!"a&&b"(range) as they can exit early on a 'false' or 'true'. Has anyone ever used this? Philippe
Re: opPow, opDollar
Stewart Gordon wrote: Matti Niemenmaa wrote: It's essentially because Haskell has separate type classes (knda like D interfaces... I won't go into that topic) for integers, fractional numbers, and floating-point numbers. In D the types of those three operators could be something like: anyinteger ^(anyintegerbase, anyinteger exponent); anyfractional ^^(anyfractional base, anyinteger exponent); anyfloating **(anyfloating base, anyfloating exponent); You've merely expanded on what I'd already made out - it doesn't explain why these generic functions can't share the same name. Is it because Haskell doesn't support function overloading as D does, or for some other reason? The former. Haskell does function overloading via type classes. I think that the reason why these functions can't have the same name is that they should all have a single, well-defined type and value. If they're all called 'pow', what is the type of pow? It can't have all three types at once, that makes no sense. And what happens if I give pow to a higher-order function: which one does it end up calling? You'd need some kind of notation to disambiguate. The developers of Haskell evidently opted to simply force differently-typed values to have different names, instead of being able to give them all the same name but then having to qualify which one you mean whenever you use it. That'd pretty much amount to them having different names anyway, I think. Just to show that this quality of Haskell isn't very limiting in practice, a somewhat tangential explanation of the way these exponentiation functions are overloaded follows. The types of these functions in Haskell are (read '::' as 'has type', the type after the last '->' as the return value and the others as the parameters): (^) :: (Num a, Integral b)=> a -> b -> a (^^) :: (Fractional a, Integral b) => a -> b -> a (**) :: (Floating a) => a -> a -> a The part before the '=>' is the class context, restricting the type variables 'a' and 'b'. 'a' and 'b' can be any type at all, as long as they satisfy the constraints. For instance, for (^), the base can be of any numeric type, but the exponent must be integral, and the result is of the same numeric type as the base. So when you're actually using the function, you might be using it under any of the following types: (^) :: Integer -> Integer -> Integer (^) :: Float -> Integer -> Float (^) :: Double -> Int8 -> Double As you can see, the functions are already overloaded, in a sense. What Haskell does not support is 'overloading the implementation' the way derivatives of C++ (or whatever language first came up with this) do: a function cannot have different implementations for different types. Instead, a type class defines certain methods that each type that is an instance of it must implement. For example, (^) could be defined in terms of (==), (*), and (-), like so: base ^ pow = if pow == 0 then 1 else base * (base ^ (pow-1)) (*) and (-) are methods of the Num class, and (==) belongs to a superclass of Num, so we can infer the type of this as: (^) :: (Num a, Num b) => a -> b -> a (The standard-library one restricts b to Integral, because this kind of definition is obviously valid only for integer exponents.) We now have a generic implementation of (^) that works for any two number types. What we can't do is say that it should do something different for certain types: its definition shows that it depends only on the methods (==), (*), and (-), so if we want to change the behaviour of (^) we can do so only by changing their behaviour. This is doable only by changing the Num instance involved, which can only be done by changing the types in question. The only things that can change their behaviour directly depending on the types involved are class methods, which are defined separately for each type. For instance, (-) is defined for Integers as bignum subtraction and (-) for Floats is some kind of built-in operation which eventually compiles to an fsub on x86. In fact, (**) is a method of the Floating class, and thus has a separate implementation for all floating-point types. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Re: opPow, opDollar
Matti Niemenmaa wrote: It's essentially because Haskell has separate type classes (knda like D interfaces... I won't go into that topic) for integers, fractional numbers, and floating-point numbers. In D the types of those three operators could be something like: anyinteger ^(anyintegerbase, anyinteger exponent); anyfractional ^^(anyfractional base, anyinteger exponent); anyfloating **(anyfloating base, anyfloating exponent); You've merely expanded on what I'd already made out - it doesn't explain why these generic functions can't share the same name. Is it because Haskell doesn't support function overloading as D does, or for some other reason? Stewart.
Re: opPow, opDollar
On Sat, Nov 7, 2009 at 2:43 AM, Don wrote: > Walter Bright wrote: >> >> Don wrote: >>> >>> A little while ago I said I'd create a patch for ^^ as an exponentiation. >>> A couple of people had requested that I make a post to the ng so they'd know >>> when it happens. Here it is. >>> >>> This is opPow(), x ^^ y >>> >>> http://d.puremagic.com/issues/show_bug.cgi?id=3481 >> >> I don't understand the rationale for an exponentiation operator. It isn't >> optimization, because pow() could become an intrinsic that the compiler >> knows about. pow() is well known, ^^ isn't. (Fortran uses **) Yes, pow() is a well-known annoyance in languages that don't have an exponentiation operator. :-) > It's primarily about syntax sugar: pow() is so ugly. In practice, the most > important case is squaring, which is an extremely common operation. > pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that > noone uses it: you always change it to xxx * xxx. But then, xxx gets > evaluated twice. xxx also has to be typed twice. Cubes also appear fairly often. > Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because > it had such a limited character set, but it's not really a natural choice; > the more mathematically-oriented languages use ^. Obviously C-family > languages don't have that possibility. I think ^^ is a fine choice. This is great for folks who do a lot of numerical stuff. --bb
Re: opPow, opDollar
Stewart Gordon wrote: Andrei Alexandrescu wrote: Matti Niemenmaa wrote: Haskell has three exponentiation operators in the standard library: ^, ^^, and **. They are for non-negative integral exponents, integral exponents, and floating-point exponents respectively. I wonder whether that's an illustration of the power or of the failure of function overloading. (Seriously.) I'm not sure either. I don't speak Haskell, but my guess is that ^ and ^^ were meant to cut out the confusion that would happen if Word32 ^ Word32 (what weird naming conventions Haskell has!) returned an integer type but Int32 ^ Int32 returned a floating point type. But why it needs yet another for floating-point exponents, I don't know. Maybe Haskell supports only IFTI rather than true function overloading. It's essentially because Haskell has separate type classes (knda like D interfaces... I won't go into that topic) for integers, fractional numbers, and floating-point numbers. In D the types of those three operators could be something like: anyinteger ^(anyintegerbase, anyinteger exponent); anyfractional ^^(anyfractional base, anyinteger exponent); anyfloating **(anyfloating base, anyfloating exponent); A noteworthy fractional is the Rational type, a ratio of two integral values. Note that 0.5 is a valid Rational: it's 1/2. Note, still, that 0.5 ** 0.5 is no longer a valid Rational: it's the square root of 1/2. This is why ^^ is separate: fractionals can be safely raised to integer exponents, but if you take a fractional and raise it to a fractional power, you might not get a fractional back.
Re: opPow, opDollar
On Sat, 07 Nov 2009 16:53:01 -0500, Andrei Alexandrescu wrote: Robert Jacques wrote: On Sat, 07 Nov 2009 12:56:35 -0500, Andrei Alexandrescu wrote: Robert Jacques wrote: I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. Well the problem is that if you want to compute several one-pass statistics in one pass, you'd have to invent means to combine these functions. That ability is already present in reduce, e.g. reduce(min, max)(range) yields a pair containing the min and the max element after exactly one pass through range. Andrei Yes, but reduce(mean, std)(range) doesn't work. From std.algorithm's doc: // Compute sum and sum of squares in one pass r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); // Compute average and standard deviation from the above auto avg = r.field[0] / a.length; auto stdev = sqrt(r.field[1] / a.length - avg * avg); I'm not saying there's no need for a more specialized library, just that I purposely designed reduce to be no slouch either. Even reduce(count) would require the range to be mapped. (This I don't get.) Besides, in my use case I need lazy evaluation, and I'd much rather add elements to a statistics struct, than write a range wrapper. Well if you go for surgery on an existing struct then the opportunity for reuse is diminished. Andrei Thanks. BTW the behavior of a tuple as input to a multiple function reduce, although in the example, doesn't seem to be in the doc text.
Re: opPow, opDollar
On Sat, 07 Nov 2009 21:31:46 -0500, Phil Deets wrote: On Sat, 07 Nov 2009 13:37:33 -0500, Andrei Alexandrescu wrote: In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei If a function is marked pure, I don't see any reason why this would be a bad idea. Make that pure and nothrow (and possibly safe).
Re: opPow, opDollar
On Sat, 07 Nov 2009 13:37:33 -0500, Andrei Alexandrescu wrote: In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei If a function is marked pure, I don't see any reason why this would be a bad idea.
Re: opPow, opDollar
Andrei Alexandrescu wrote: Matti Niemenmaa wrote: Don wrote: Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Haskell has three exponentiation operators in the standard library: ^, ^^, and **. They are for non-negative integral exponents, integral exponents, and floating-point exponents respectively. I wonder whether that's an illustration of the power or of the failure of function overloading. (Seriously.) I'm not sure either. I don't speak Haskell, but my guess is that ^ and ^^ were meant to cut out the confusion that would happen if Word32 ^ Word32 (what weird naming conventions Haskell has!) returned an integer type but Int32 ^ Int32 returned a floating point type. But why it needs yet another for floating-point exponents, I don't know. Maybe Haskell supports only IFTI rather than true function overloading. Stewart.
Re: opPow, opDollar
dsimcha wrote: == Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article Robert Jacques wrote: On Sat, 07 Nov 2009 12:56:35 -0500, Andrei Alexandrescu wrote: Robert Jacques wrote: I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. Well the problem is that if you want to compute several one-pass statistics in one pass, you'd have to invent means to combine these functions. That ability is already present in reduce, e.g. reduce(min, max)(range) yields a pair containing the min and the max element after exactly one pass through range. Andrei Yes, but reduce(mean, std)(range) doesn't work. From std.algorithm's doc: // Compute sum and sum of squares in one pass r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); // Compute average and standard deviation from the above auto avg = r.field[0] / a.length; auto stdev = sqrt(r.field[1] / a.length - avg * avg); I'm not saying there's no need for a more specialized library, just that I purposely designed reduce to be no slouch either. Don't get me wrong, I love reduce and it's definitely the right tool for some jobs. It's just that computing standard deviations isn't one of them. Finding the sum of the squares explicitly is an absolutely **horrible** way to find the standard deviation because it's numerically unstable. What if you have a few billion numbers being read in lazily from a file and you want to find the standard deviation of them? Heck, summing explicitly isn't even a very good way to find the mean. I'm sure you could implement a proper algorithm for this using reduce, but it would be really awkward. IMHO reduce's place is as a convenience for simple things like finding the max and min of a range. Once you're trying to shoehorn something into reduce that doesn't fit nicely, it's time to give up using reduce and just write a "real" function. I agree. Andrei
Re: opPow, opDollar
== Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article > Robert Jacques wrote: > > On Sat, 07 Nov 2009 12:56:35 -0500, Andrei Alexandrescu > > wrote: > > > >> Robert Jacques wrote: > >>> I'd recommend rolling that into a basic statistics struct containing > >>> common single pass metrics: i.e. sum, mean, variance, min, max, etc. > >> > >> Well the problem is that if you want to compute several one-pass > >> statistics in one pass, you'd have to invent means to combine these > >> functions. That ability is already present in reduce, e.g. reduce(min, > >> max)(range) yields a pair containing the min and the max element after > >> exactly one pass through range. > >> > >> Andrei > > > > Yes, but reduce(mean, std)(range) doesn't work. > From std.algorithm's doc: > // Compute sum and sum of squares in one pass > r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); > // Compute average and standard deviation from the above > auto avg = r.field[0] / a.length; > auto stdev = sqrt(r.field[1] / a.length - avg * avg); > I'm not saying there's no need for a more specialized library, just that > I purposely designed reduce to be no slouch either. Don't get me wrong, I love reduce and it's definitely the right tool for some jobs. It's just that computing standard deviations isn't one of them. Finding the sum of the squares explicitly is an absolutely **horrible** way to find the standard deviation because it's numerically unstable. What if you have a few billion numbers being read in lazily from a file and you want to find the standard deviation of them? Heck, summing explicitly isn't even a very good way to find the mean. I'm sure you could implement a proper algorithm for this using reduce, but it would be really awkward. IMHO reduce's place is as a convenience for simple things like finding the max and min of a range. Once you're trying to shoehorn something into reduce that doesn't fit nicely, it's time to give up using reduce and just write a "real" function.
Re: opPow, opDollar
Robert Jacques wrote: On Sat, 07 Nov 2009 12:56:35 -0500, Andrei Alexandrescu wrote: Robert Jacques wrote: I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. Well the problem is that if you want to compute several one-pass statistics in one pass, you'd have to invent means to combine these functions. That ability is already present in reduce, e.g. reduce(min, max)(range) yields a pair containing the min and the max element after exactly one pass through range. Andrei Yes, but reduce(mean, std)(range) doesn't work. From std.algorithm's doc: // Compute sum and sum of squares in one pass r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); // Compute average and standard deviation from the above auto avg = r.field[0] / a.length; auto stdev = sqrt(r.field[1] / a.length - avg * avg); I'm not saying there's no need for a more specialized library, just that I purposely designed reduce to be no slouch either. Even reduce(count) would require the range to be mapped. (This I don't get.) Besides, in my use case I need lazy evaluation, and I'd much rather add elements to a statistics struct, than write a range wrapper. Well if you go for surgery on an existing struct then the opportunity for reuse is diminished. Andrei
Re: opPow, opDollar
On Sat, 07 Nov 2009 13:37:33 -0500, Andrei Alexandrescu wrote: Walter Bright wrote: KennyTM~ wrote: Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. As amply illustrated, one can make this argument pro and con about any builtin operator. The waterfront real estate of builtin operators is extremely limited, so we need to be very parsimonious in allocating it. Candidates for builtin operators need to have a very high bar. The question is, does ^^ clear that bar or not? In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for automatic loop fusion that would tilt my opinion in disfavor of ^^, and if not, it would tilt my opinion in favor of ^^. Actually, if you look at Matlab, a[] = b[] ^^ 3; is well defined. Also, given real foo(real r) { return r*r; } providing syntactic sugar for a[] = foo(b[], 3); => a[] = map!foo(b[],3); might be nice.
Re: opPow, opDollar
On Sat, 07 Nov 2009 14:22:01 -0500, dsimcha wrote: == Quote from Robert Jacques (sandf...@jhu.edu)'s article I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. I've been wondering for a while if something like this is general enough for non-statisticians and a good candidate for Phobos: http://svn.dsource.org/projects/dstats/docs/summary.html Good? Overkill? Too niche? Looks good.
Re: opPow, opDollar
On Sat, 07 Nov 2009 12:56:35 -0500, Andrei Alexandrescu wrote: Robert Jacques wrote: I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. Well the problem is that if you want to compute several one-pass statistics in one pass, you'd have to invent means to combine these functions. That ability is already present in reduce, e.g. reduce(min, max)(range) yields a pair containing the min and the max element after exactly one pass through range. Andrei Yes, but reduce(mean, std)(range) doesn't work. Even reduce(count) would require the range to be mapped. Besides, in my use case I need lazy evaluation, and I'd much rather add elements to a statistics struct, than write a range wrapper.
Re: opPow, opDollar
Walter Bright wrote: Andrei Alexandrescu wrote: In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for automatic loop fusion that would tilt my opinion in disfavor of ^^, and if not, it would tilt my opinion in favor of ^^. I don't think this is a valid argument for making pow() an operator, because what about sin()? cos()? It's all the same issue, and they all can't be operators. It's another case where pow(x, 2) is not the same as x ^^ 2. The argument for excluding exponentiation is largely, "pow does the same thing, without introducing an operator".
Re: opPow, opDollar
Andrei Alexandrescu wrote: In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for automatic loop fusion that would tilt my opinion in disfavor of ^^, and if not, it would tilt my opinion in favor of ^^. I don't think this is a valid argument for making pow() an operator, because what about sin()? cos()? It's all the same issue, and they all can't be operators.
Re: opPow, opDollar
Mo Chen wrote: Suppose we have a matrix library, I'd like to have two product operators, one is for matrix product, the other is for element wise product, just like what we do in matlab (A*B and A.*B). I'd like to save ** to that scenario. Btw I'm no Fortran user. ^^ is fine by me. The D forms are A*B for matrix product, A[]*B[] for element-wise product. .
Re: opPow, opDollar
Walter Bright wrote: KennyTM~ wrote: Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. As amply illustrated, one can make this argument pro and con about any builtin operator. The waterfront real estate of builtin operators is extremely limited, so we need to be very parsimonious in allocating it. Candidates for builtin operators need to have a very high bar. The question is, does ^^ clear that bar or not? Yes, that's exactly the question. From an old post by Bill Baxter, here's a list of languages with an exponentiation operator: # x ↑ y: Algol, Commodore BASIC # x ^ y: BASIC, J, Matlab, R, Microsoft Excel, TeX (and its derivatives), Haskell (for non-negative integer exponents), and most computer algebra systems # x ^^ y: Haskell (for integer exponents) # x ** y: Ada, Bash, Fortran, FoxPro, Perl, Python, Ruby, SAS, ABAP, Haskell (for floating-point exponents), Turing # x * y: APL None of the languages derived from C and Pascal include exponentiation. (I suspect that if it had been included in C, there would be very few languages without it: since Algol and Fortran both had it). Note that D currently has <>, <>=, !<>, !<>=, !>=, !<=, !>, !<, which would have to be lower down the list than exponentiation. As one of the very few users who actually uses them, I'd happily sacrifice them in exchange for exponentiation. And BTW, there is another issue with pow(), relating to implicit conversion. Given an int x, x * x is also an int. But pow(x, 2) is a double, so they are not at all equivalent. (and pow() definitely needs to return float for general exponents). The recently introduced integer range tracking for implicit conversions could fix this nicely.
Re: opPow, opDollar
Suppose we have a matrix library, I'd like to have two product operators, one is for matrix product, the other is for element wise product, just like what we do in matlab (A*B and A.*B). I'd like to save ** to that scenario. Btw I'm no Fortran user. ^^ is fine by me. On Sat, Nov 7, 2009 at 5:56 PM, Walter Bright wrote: > Don wrote: > >> A little while ago I said I'd create a patch for ^^ as an exponentiation. >> A couple of people had requested that I make a post to the ng so they'd know >> when it happens. Here it is. >> >> This is opPow(), x ^^ y >> >> http://d.puremagic.com/issues/show_bug.cgi?id=3481 >> > > I don't understand the rationale for an exponentiation operator. It isn't > optimization, because pow() could become an intrinsic that the compiler > knows about. pow() is well known, ^^ isn't. (Fortran uses **) >
Re: opPow, opDollar
== Quote from Robert Jacques (sandf...@jhu.edu)'s article > I'd recommend rolling that into a basic statistics struct containing > common single pass metrics: i.e. sum, mean, variance, min, max, etc. I've been wondering for a while if something like this is general enough for non-statisticians and a good candidate for Phobos: http://svn.dsource.org/projects/dstats/docs/summary.html Good? Overkill? Too niche?
Re: opPow, opDollar
Andrei Alexandrescu wrote: > Walter Bright wrote: >> KennyTM~ wrote: >>> Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's >>> primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In >>> practice, the most important case is the sum from 1 to n, which is an >>> extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly >>> ugly for something so fundamental. It's so ugly that noone uses it: >>> you always change it to n*(n+1)/2. But then, n gets evaluated twice. >> >> As amply illustrated, one can make this argument pro and con about any >> builtin operator. The waterfront real estate of builtin operators is >> extremely limited, so we need to be very parsimonious in allocating >> it. Candidates for builtin operators need to have a very high bar. >> >> The question is, does ^^ clear that bar or not? > > In order for everyone to air an informed opinion, a related question is: > will loop fusion be allowed with function calls? > > Loop fusion currently only works with operators, and adding ^^ would allow: > > a[] = b[] ^^ 3; > > But with pow you can't do that: > > a[] = pow(b[], 3); > > > Andrei > > P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for > automatic loop fusion that would tilt my opinion in disfavor of ^^, and > if not, it would tilt my opinion in favor of ^^. Does ^^ really even need to be a builtin operator to be overloadable? I remember a discussion where we considered adding abstract operators that have no inherent meaning in the language (not builtins), but are overloadable to allow better exploitation of infix notation. Things like (+), (*), (%), (&), [+], [*], [%], and so on.
Re: opPow, opDollar
Walter Bright wrote: KennyTM~ wrote: Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. As amply illustrated, one can make this argument pro and con about any builtin operator. The waterfront real estate of builtin operators is extremely limited, so we need to be very parsimonious in allocating it. Candidates for builtin operators need to have a very high bar. The question is, does ^^ clear that bar or not? In order for everyone to air an informed opinion, a related question is: will loop fusion be allowed with function calls? Loop fusion currently only works with operators, and adding ^^ would allow: a[] = b[] ^^ 3; But with pow you can't do that: a[] = pow(b[], 3); Andrei P.S. FWIW, I'm ambivalent on the issue; if functions were allowed for automatic loop fusion that would tilt my opinion in disfavor of ^^, and if not, it would tilt my opinion in favor of ^^.
Re: opPow, opDollar
KennyTM~ wrote: Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. As amply illustrated, one can make this argument pro and con about any builtin operator. The waterfront real estate of builtin operators is extremely limited, so we need to be very parsimonious in allocating it. Candidates for builtin operators need to have a very high bar. The question is, does ^^ clear that bar or not?
Re: opPow, opDollar
Robert Jacques wrote: I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. Well the problem is that if you want to compute several one-pass statistics in one pass, you'd have to invent means to combine these functions. That ability is already present in reduce, e.g. reduce(min, max)(range) yields a pair containing the min and the max element after exactly one pass through range. Andrei
Re: opPow, opDollar
On Nov 8, 09 00:15, Robert Jacques wrote: On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: On Nov 7, 09 18:43, Don wrote: Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Well, since D supports unicode, you can always define: alias reduce!("a+b") ∑; Or pure nothrow T ²(T)(T x) { return x*x; } alias sqrt √; :p (OK ²(xxx) is still odd.)
Re: opPow, opDollar
dsimcha wrote: == Quote from Robert Jacques (sandf...@jhu.edu)'s article On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: On Nov 7, 09 18:43, Don wrote: Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Well, since D supports unicode, you can always define: alias reduce!("a+b") ∑; On a more serious note, I'm starting to think that Phobos needs a specific convenience function for sum, not because reduce!"a + b" is ugly (it isn't) or too much typing (it isn't) but because reduce!"a + b" doesn't work on zero-length ranges. Obviously, the sum of a zero-length range is zero, but reduce is too general to know this. This bit me a few times in some code I was debugging last week. Rather than inserting extra checks or passing an explicit start value in (which requires you to remember the element type of your range; is it an int or a float?), I simply handwrote a sum function and replaced all my reduce!"a + b" with sum. Just in case it helps, the two-arguments version of reduce is meant exactly to make it work with an empty array and seed the accumulation. Namely, reduce!"a+b"(range) throws on an empty range, but reduce!"a+b"(0.0, range) returns 0.0 on an empty range. Andrei
Re: opPow, opDollar
On Sat, 07 Nov 2009 11:26:36 -0500, dsimcha wrote: == Quote from Robert Jacques (sandf...@jhu.edu)'s article On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: > On Nov 7, 09 18:43, Don wrote: >> Walter Bright wrote: >>> Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 >>> >>> I don't understand the rationale for an exponentiation operator. It >>> isn't optimization, because pow() could become an intrinsic that the >>> compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) >> >> It's primarily about syntax sugar: pow() is so ugly. In practice, the >> most important case is squaring, which is an extremely common operation. >> pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly >> that noone uses it: you always change it to xxx * xxx. But then, xxx >> gets evaluated twice. >> > > Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's > primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In > practice, the most important case is the sum from 1 to n, which is an > extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly > for something so fundamental. It's so ugly that noone uses it: you > always change it to n*(n+1)/2. But then, n gets evaluated twice. > >> Yes, ^^ hasn't been used for exponentiation before. Fortran used ** >> because it had such a limited character set, but it's not really a >> natural choice; the more mathematically-oriented languages use ^. >> Obviously C-family languages don't have that possibility. >> > Well, since D supports unicode, you can always define: alias reduce!("a+b") ∑; On a more serious note, I'm starting to think that Phobos needs a specific convenience function for sum, not because reduce!"a + b" is ugly (it isn't) or too much typing (it isn't) but because reduce!"a + b" doesn't work on zero-length ranges. Obviously, the sum of a zero-length range is zero, but reduce is too general to know this. This bit me a few times in some code I was debugging last week. Rather than inserting extra checks or passing an explicit start value in (which requires you to remember the element type of your range; is it an int or a float?), I simply handwrote a sum function and replaced all my reduce!"a + b" with sum. I'd recommend rolling that into a basic statistics struct containing common single pass metrics: i.e. sum, mean, variance, min, max, etc. P.S. Don't forget to vote for the patches in bugzilla.
Re: opPow, opDollar
dsimcha wrote: == Quote from Robert Jacques (sandf...@jhu.edu)'s article On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: On Nov 7, 09 18:43, Don wrote: Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Well, since D supports unicode, you can always define: alias reduce!("a+b") ∑; On a more serious note, I'm starting to think that Phobos needs a specific convenience function for sum, not because reduce!"a + b" is ugly (it isn't) or too much typing (it isn't) but because reduce!"a + b" doesn't work on zero-length ranges. Obviously, the sum of a zero-length range is zero, but reduce is too general to know this. This bit me a few times in some code I was debugging last week. Rather than inserting extra checks or passing an explicit start value in (which requires you to remember the element type of your range; is it an int or a float?), I simply handwrote a sum function and replaced all my reduce!"a + b" with sum. I am all in favor of adding convenience functions sum and product to phobos. I use them both often enough.
Re: opPow, opDollar
== Quote from Robert Jacques (sandf...@jhu.edu)'s article > On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: > > On Nov 7, 09 18:43, Don wrote: > >> Walter Bright wrote: > >>> Don wrote: > A little while ago I said I'd create a patch for ^^ as an > exponentiation. A couple of people had requested that I make a post > to the ng so they'd know when it happens. Here it is. > > This is opPow(), x ^^ y > > http://d.puremagic.com/issues/show_bug.cgi?id=3481 > >>> > >>> I don't understand the rationale for an exponentiation operator. It > >>> isn't optimization, because pow() could become an intrinsic that the > >>> compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) > >> > >> It's primarily about syntax sugar: pow() is so ugly. In practice, the > >> most important case is squaring, which is an extremely common operation. > >> pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly > >> that noone uses it: you always change it to xxx * xxx. But then, xxx > >> gets evaluated twice. > >> > > > > Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's > > primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In > > practice, the most important case is the sum from 1 to n, which is an > > extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly > > for something so fundamental. It's so ugly that noone uses it: you > > always change it to n*(n+1)/2. But then, n gets evaluated twice. > > > >> Yes, ^^ hasn't been used for exponentiation before. Fortran used ** > >> because it had such a limited character set, but it's not really a > >> natural choice; the more mathematically-oriented languages use ^. > >> Obviously C-family languages don't have that possibility. > >> > > > Well, since D supports unicode, you can always define: alias > reduce!("a+b") ∑; On a more serious note, I'm starting to think that Phobos needs a specific convenience function for sum, not because reduce!"a + b" is ugly (it isn't) or too much typing (it isn't) but because reduce!"a + b" doesn't work on zero-length ranges. Obviously, the sum of a zero-length range is zero, but reduce is too general to know this. This bit me a few times in some code I was debugging last week. Rather than inserting extra checks or passing an explicit start value in (which requires you to remember the element type of your range; is it an int or a float?), I simply handwrote a sum function and replaced all my reduce!"a + b" with sum.
Re: opPow, opDollar
On Sat, 07 Nov 2009 10:48:11 -0500, KennyTM~ wrote: On Nov 7, 09 18:43, Don wrote: Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Well, since D supports unicode, you can always define: alias reduce!("a+b") ∑;
Re: opPow, opDollar
Matti Niemenmaa wrote: Don wrote: Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Haskell has three exponentiation operators in the standard library: ^, ^^, and **. They are for non-negative integral exponents, integral exponents, and floating-point exponents respectively. I wonder whether that's an illustration of the power or of the failure of function overloading. (Seriously.) Andrei
Re: opPow, opDollar
On Nov 7, 09 18:43, Don wrote: Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Nice. Meanwhile, I'd like an opSum() operator (∑ range) as well. It's primarily about syntax sugar: reduce!("a+b")(range) is so ugly. In practice, the most important case is the sum from 1 to n, which is an extremely common operation. reduce!("a+b")(iota(1,n+1)) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to n*(n+1)/2. But then, n gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility.
Re: opPow, opDollar
Don wrote: Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility. Haskell has three exponentiation operators in the standard library: ^, ^^, and **. They are for non-negative integral exponents, integral exponents, and floating-point exponents respectively.
Re: opPow, opDollar
> the more mathematically-oriented languages use ^ And BASIC ;-) -=mike=-
Re: opPow, opDollar
Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) It's primarily about syntax sugar: pow() is so ugly. In practice, the most important case is squaring, which is an extremely common operation. pow(xxx,2) is horribly ugly for something so fundamental. It's so ugly that noone uses it: you always change it to xxx * xxx. But then, xxx gets evaluated twice. Yes, ^^ hasn't been used for exponentiation before. Fortran used ** because it had such a limited character set, but it's not really a natural choice; the more mathematically-oriented languages use ^. Obviously C-family languages don't have that possibility.
Re: opPow, opDollar
Walter Bright wrote: Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 AWESOME! Thanks a lot, Don! I've been hoping for this since I started using D. Walter Bright wrote: I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **) I don't understand the rationale for a concatenation operator. It isn't optimization, because strcat() could become an intrinsic that the compiler knows about. strcat() is well known, ~ isn't. (Java uses +) I'm not trying to be rude, I'm just trying to illustrate that the first point doesn't make a good case against an exponentiation operator. I can only speak for myself, but I use exponentiation a lot. I mostly write numerical code, and as I understand it, I'm not the only one in the community doing so. Being able to overload the exponentiation operator also makes a lot of sense. Matrices and BigInts are the first things that come to mind. -Lars
Re: opPow, opDollar
Don wrote: A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 I don't understand the rationale for an exponentiation operator. It isn't optimization, because pow() could become an intrinsic that the compiler knows about. pow() is well known, ^^ isn't. (Fortran uses **)
opPow, opDollar
A little while ago I said I'd create a patch for ^^ as an exponentiation. A couple of people had requested that I make a post to the ng so they'd know when it happens. Here it is. This is opPow(), x ^^ y http://d.puremagic.com/issues/show_bug.cgi?id=3481 And this is opDollar!(int dim) for multi-dimensional indexing http://d.puremagic.com/issues/show_bug.cgi?id=3474 There have been long bikeshed discussions about the naming of both of these several times in the past. Please don't ask for name changes to x ^ y, x ** y, opLength, or opSize: there are known problems with all of those. And opEnd has the problem that you expect it to be paired with an opBegin. opDollar is not as aesthetically pleasing as you might wish, but it's obvious and completely unambiguous. I think they're the best options we have.