Re: [racket-dev] [plt] Push #26002: master branch updated

2013-01-01 Thread Neil Toronto

On 01/01/2013 12:36 PM, mfl...@racket-lang.org wrote:

07d5a9e Matthew Flatt mfl...@racket-lang.org 2013-01-01 12:31
:
| fix `expt' on small negative number and large positive odd
|
| The pow() function apparently gets it wrong on some platforms.
|
| Closes PR 13391


Thanks, Matthew. I'm looking forward to getting bugged by DrDr less. :D

One question about the fix:


src/racket/src/number.c
~~~
--- OLD/src/racket/src/number.c
+++ NEW/src/racket/src/number.c
@@ -2729,7 +2729,16 @@ static double sch_pow(double x, double y)
  return scheme_infinity_val;
  }
} else {
-return protected_pow(x, y);
+double r;
+r = protected_pow(x, y);
+if ((r == 0.0)  !minus_zero_p(r)) {
+  /* check large odd power of a small negative number,
+ which some libraries get wrong for some reason */
+  if ((x  0)  (fmod(y, 2.0) == 1.0)) {
+   r = scheme_floating_point_nzero;
+  }
+}
+return r;
}
  }
  #endif


I looked into fixing this myself, and identified this as a spot to 
change. I also saw some JIT-looking stuff for `flexpt' that looked kind 
of like it was machine code, so I didn't try to fix it. Does this code 
you just changed get compiled during the build and then inlined by the JIT?


Neil ⊥

_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] [plt] Push #26002: master branch updated

2013-01-01 Thread Matthew Flatt
At Tue, 01 Jan 2013 14:16:27 -0700, Neil Toronto wrote:
 I looked into fixing this myself, and identified this as a spot to 
 change. I also saw some JIT-looking stuff for `flexpt' that looked kind 
 of like it was machine code, so I didn't try to fix it. Does this code 
 you just changed get compiled during the build and then inlined by the JIT?

In the case of `flexpt', the inlined code is just a call to the
sch_pow() C function (which is inline enough to avoid boxing).

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Five feature/limitation interactions conspire to drive mad

2013-01-01 Thread Matthias Felleisen

On Dec 31, 2012, at 6:32 PM, Sam Tobin-Hochstadt wrote:

 I'm not sure that an ad-hoc naming solution is the right thing.  I
 really want to avoid adding more ad-hoc complexity to the Typed Racket
 type checker, and instead work on simplifying it into something that
 can be more precisely characterized, and thus be more sure that it's
 implemented correctly.
 
 Is there a generalization of this solution that we can give a clean story for?


Sometimes you have to make the internals quite complex to make it 
all appear elegant and simple. Guy Steele, as conveyed by Matthew
and confirmed by Sam 


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Five feature/limitation interactions conspire to drive mad

2013-01-01 Thread Matthias Felleisen

Neil, 

thanks for the user story. We should hear more of those for all kinds of 
corners in our world. 

Question: did you start the math library in an untyped form (and switch) or did 
you go with types from the get-go? 

-- Matthias



On Dec 31, 2012, at 3:27 PM, Neil Toronto wrote:

 The subject sounds complainy, and so will the rest of this email. So I will 
 state up front that I love Typed Racket, and I'm only frustrated because I 
 want to love it more.
 
 Also, I apologize for the length of this email, but I have to tell a story. 
 Otherwise, I'll get a bunch of Why don't you try this? replies, which I'll 
 have to answer, leading to an inseparable tangle of ideas. How the features 
 and limitations interact is not always obvious.
 
 The features and limitations are:
 
 1. The reader is set by the #lang line, but not submodule forms.
 
 2. Implicit argument types in let loops are generalized from the types
of their initial values.
 
 3. let: loops require every argument type and the return type to be
annotated.
 
 4. TR can't produce contracts for single-arity `case-' types.
 
 5. Using single-arity `case-' types makes annotating function bodies
in certain ways impossible.
 
 So here's my user story.
 
  ** ONCE UPON A TIME **
 
 I'm working on `math/matrix'. TR doesn't do generics, which is fine for now, 
 but it means a lot of the matrix library's functions have to have 
 single-arity types like this:
 
  (: matrix-hermitian (case- ((Matrix Real) - (Matrix Real))
  ((Matrix Number) - (Matrix Number
 
 It could be (Matrix Number) - (Matrix Number). But the real matrices are 
 closed under almost every matrix operation, so `math/matrix' shouldn't make 
 users worry needlessly about complex numbers.
 
 Annotating expressions inside the bodies of functions with single-arity 
 `case-' types like that is often impossible, because there's no name for 
 polymorphic type arguments (in this case, either `Real' or `Number'). To 
 separate the issues from `math/matrix', consider this function instead:
 
  (: repeat+1 (case- (Index Real - (Listof Real))
  (Index Number - (Listof Number
  (define (repeat+1 n num)
(let loop ([i 0] [acc empty])
  (cond [( i n)  (loop (+ i 1) (cons (+ num 1) acc))]
[else  acc])))
 
 It should act like this:
 
   (repeat+1 3 10)
  - : (Listof Real)
  '(11 11 11)
   (repeat+1 0 11+4i)
  - : (Listof Number)
  '()
 
 But it doesn't type:
 
  Type Checker: Expected (Listof Real), but got (Listof Any) in: acc
  Type Checker: Expected (Listof Number), but got (Listof Any) in: acc
 
 The highlighted expression is the `acc' inside of [else acc]. The causes: TR 
 gives the expression `empty' the type (Listof Any) in both passes through the 
 function body (one for each case).
 
 The level of inference TR does is generally fine, requiring few annotations. 
 The problem here is that *I can't annotate `empty'*. I don't have a name for 
 the type argument to `Listof'.
 
 Here's one annotation-less solution:
 
  (define (repeat+1 n num)
(cond [(= n 0)  empty]
  [else
   (let loop ([i 1] [acc  (list (+ num 1))])
 (cond [( i n)  (loop (+ i 1) (cons (+ num 1) acc))]
   [else  acc]))]))
 
 TR helpfully generalizes the type of (list (+ num 1)) from (List Real) to 
 (Listof Real) in the first typechecking pass and from (List Number) to 
 (Listof Number) in the second typechecking pass, so `acc' has the correct 
 type in both passes.
 
 I committed the off-by-one error [i 0] and the copy error [acc (list num)] 
 while deriving that solution. Not liking either kind of error, I figure this 
 is safer, and also cleverer:
 
  (define (repeat+1 n num)
(let loop ([i 0] [acc  (rest (list num))])
  (cond [( i n)  (loop (+ i 1) (cons (+ num 1) acc))]
[else  acc])))
 
 I'm trying to get a properly typed `empty' by taking the rest of a 
 one-element list.
 
 I get two type errors like this, highlighting (cons (+ num 1) acc):
 
  Type Checker: Polymorphic function cons could not be applied to
  arguments:
  Types: a (Listof a) - (Listof a)
 a b - (Pairof a b)
  Arguments: Real (Listof Nothing)
  Expected result: (Listof Nothing)
 
 Ah, I see what happened. TR generalized from the type of (rest (list num)), 
 which is (Listof Nothing) because (list num) has the type (List Real) or 
 (List Number). I need to force it to generalize differently. One way to do 
 that is to turn the base case into a call to a polymorphic function like 
 `empty-listof':
 
  (define (repeat+1 n num)
(let loop ([i 0] [acc  (empty-listof num)])
  (cond [( i n)  (loop (+ i 1) (cons (+ num 1) acc))]
[else  acc])))
 
  (: empty-listof (All (A) (A - (Listof A
  (define (empty-listof x) (rest (list x)))
 
 Basically, `empty-listof' gives me a way to name the type parameter to 
 `Listof' in that one expression.
 
 Well, it's either this or 

[racket-dev] Working on Ragg. Suggestions?

2013-01-01 Thread Danny Yoo
Hi everyone,

I've been working on a parsing framework with the design goal to be
easy to use.  I'm calling it ragg: Racket AST Generator Generator.
(It used to be called 'autogrammar', but that was too much of a
mouthful. Thanks to Joe Politz for the new name!)


The current source code uses PLaneT2 conventions:

https://github.com/dyoo/ragg

The beginnings of its documentation can be read here:

http://hashcollision.org/ragg/


Major features:

* Ragg provides a #lang for writing extended BNF grammars.  Modules
written in #lang ragg automatically generate a parser.  It tries to
follow HTDP doctrine, for the structure of the grammar informs the
structure of the parser's output: the generated parsers produces
native Racket syntax objects in the same shape as the rules.

The documentation link above shows a trivial example, and I'll put
more substantive examples and uses in:

https://github.com/dyoo/ragg/blob/master/ragg/examples
https://github.com/dyoo/ragg/blob/master/ragg/test

(Note: the Python parser example works!  It's basically a copy and
paste of the one in the original Python source tree.)

* The language uses an uppercase convention to determine if a
production is a terminal token or not.  Tokens can optionally provide
location, and the generated syntax objects will have source location
if the tokens do.

* Ragg should work on ambiguous grammars.  I'm using a parser based
(hilariously enough) on the cfg-parser from the algol60 collection,
rather than the more finicky LALR parser in parser-tools/yacc.

---

I need to polish ragg.  I'm going to get most of the test cases, error
traps, and documentation done by the end of this week.  I would really
like some comments and suggestions before I release this on PLaneT2,
because I do want this to be useful to other people.  In my view, the
big thing missing is a story about lexers, which I don't quite know
what to do yet, and if anyone has ideas, I'd love to hear them.

Other work: I don't know if cfg-parser has been optimized yet.  I'll
have to investigate that.


Hope this helps!
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] [plt] Push #26005: master branch updated

2013-01-01 Thread Neil Toronto

On 01/01/2013 04:16 PM, stamo...@racket-lang.org wrote:

stamourv has updated `master' from 1f8370d2d6 to 678451f8c4.
   http://git.racket-lang.org/plt/1f8370d2d6..678451f8c4

=[ 2 Commits ]==
Directory summary:
   10.3% collects/tests/typed-racket/succeed/
8.6% collects/tests/typed-racket/unit-tests/
   81.0% collects/typed-racket/base-env/

~~

4137eb9 Vincent St-Amour stamo...@racket-lang.org 2012-12-31 17:26
:
| Make let: annotations optional.
:


I think I can remove every instance of #{v : t} from my code now. Yay!

Neil ⊥

_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] Five feature/limitation interactions conspire to drive mad

2013-01-01 Thread Neil Toronto

On 01/01/2013 03:35 PM, Matthias Felleisen wrote:


Neil,

thanks for the user story. We should hear more of those for all kinds of 
corners in our world.


You're welcome!


Question: did you start the math library in an untyped form (and switch) or did 
you go with types from the get-go?


It's all been in Typed Racket from the beginning. This was initially 
because I mostly had floating-point functions planned, and I wanted TR's 
help proving that I never used non-flonums by mistake. Also, I wanted 
the special functions to have performance competitive with C 
implementations.


When I decided to do arrays, Typed Racket was again the natural choice. 
First, because it's not possible to use `require/typed' to import 
polymorphic struct types. Second, because it allowed me to avoid a lot 
of runtime checks.


I discovered reasons #3 and #4 while I was writing `math/array':

3. Passing around higher-order functions can get confusing. I can't 
speak for anyone else, but when I get something like `array-axis-reduce' 
- which is like a fold but with complicated types - to pass the type 
checker, my code is usually correct.


4. TR's types for Racket's numeric tower, especially the additional 
`Index' type, makes it easy to safely use unsafe indexing. Throughout 
`math/array', values of type `Index' are always either a size (e.g. a 
vector length) or an index that has been proved to be less than a size. 
IOW, if I can get TR to prove j : Index, I'm satisfied that 
(unsafe-vector-ref xs j) is actually safe. Also, if `j' is a loop 
counter, TR can usually compare and increment using unsafe fixnum ops.


There are a bunch of other little things that are like #4 (which is only 
a big thing because indexes are so prevalent in `math/array'). Maybe 
I'll collect those into a separate user story.


Neil ⊥

_
 Racket Developers list:
 http://lists.racket-lang.org/dev


Re: [racket-dev] TR: Five feature/limitation interactions conspire to drive mad

2013-01-01 Thread Neil Toronto

On 12/31/2012 02:56 PM, Vincent St-Amour wrote:

At Mon, 31 Dec 2012 13:27:50 -0700,
Neil Toronto wrote:

   2. Don't generalize argument types in let loops.

This is a bad idea. Often, inferring the types of loops only works
because of type generalization.


Agreed. Since this one is only a problem because of the other
limitations you list, ideally we should fix the others and leave this
one alone. Do you agree?


Very yes.


   3. Allow let: loops to have unannotated arguments and return values.

This would totally work. I could use [i : Nonnegative-Fixnum 0] instead
of [#{i : Nonnegative-Fixnum} 0], and still not have to annotate `acc'
or the loop's return value.


Trying this one right now.


Thanks again. :D


   4. Extend the set of types TR can produce contracts for.

This probably only works for first-order function types. It would be
helpful, but may not even work for functions with `Array' or `Matrix'
arguments (they're higher-order).


I can look into making contract generation smarter. Could you send me
a list of types that caused you issues with contract generation?


Actual examples are attached as a standalone Typed Racket program, with 
the function bodies stubbed out. I think they cover pretty much all the 
uses of `require/untyped-contract' in the math library.


Neil ⊥

#lang typed/racket

(struct: (A) Array ())

(define-type Indexes (Vectorof Index))
(define-type In-Indexes (U Indexes (Vectorof Integer)))

;; 
---
;; Changing argument types from In-Indexes to (Vectorof Integer)

;; Most uses of `require/untyped-contract' in `math/array' are for this.

(: make-array (All (A) (In-Indexes A - (Array A
(define (make-array ds v)
  (error 'undefined))

;; The contract can be created, but is ambiguous and always fails. Exported to 
untyped Racket using
;; this subtype:
#;(All (A) ((Vectorof Integer) A - (Array A)))

;; 
---
;; array-map's type

;; There was no subtype of this under which I could export it to untyped code:
(: array-map (All (R A B T ...)
  (case- ((- R) - (Array R))
  ((A - R) (Array A) - (Array R))
  ((A B T ... T - R) (Array A) (Array B) (Array T) ... 
T - (Array R)
(define array-map
  (case-lambda
[(f)  (error 'undefined)]
[(f arr)  (error 'undefined)]
[(f arr0 arr1)  (error 'undefined)]
[(f arr0 arr1 . arrs)  (error 'undefined)]))

;; I ended up making a separate, typed implementation for untyped code, with 
the type
#;(All (R A) (case- ((- R) - (Array R))
 ((A - R) (Array A) - (Array R))
 ((A A A * - R) (Array A) (Array A) (Array A) * - (Array 
R

;; 
---
;; Matrix argument types

;; Almost all uses of `require/untyped-contract' in `math/matrix' are for this.

(: matrix-determinant (case- ((Array Real) - Real)
  ((Array Number) - Number)))
(define (matrix-determinant M)
  (error 'undefined))

;; Exported using the subtype
#;((Array Number) - Number)

;; 
---
;; First-order numeric functions

;; Almost all uses of `require/untyped-contract' in `math/number-theory' and 
`math/special-functions'
;; are variations of the following:

(: factorial (case- (Zero - One)
 (One - One)
 (Integer - Positive-Integer)))
(define (factorial n)
  (error 'undefined))

;; Exported using the subtype
#;(Integer - Positive-Integer)
_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Five feature/limitation interactions conspire to drive mad

2013-01-01 Thread Ray Racine
All good points on TR development flows.

If I could elaborate from my perspective on Neils' #3.  I think this is the
#1 benefit of TR over R.  Yes, static type checking, real-time while you
type is superb road kill on the highway of code development   And I do
enjoy it so.

BUT what TR really, really grants is the ability to just get META with HOF
and not go insane, all evidence to the contrary, while doing so.

For me, cursed with wrong end of the bell curve working set intelligence,
the following example of HOF without TR's training wheels would result in a
multi-week rest visit to Arkham for me if undertaken in plain ol' R.

e.g quick sample from some proto code.
https://github.com/RayRacine/racketlib/blob/master/io/iteratee/iteratee.rkt
https://github.com/RayRacine/racketlib/blob/master/mapred/types.rkt
https://github.com/RayRacine/racketlib/blob/master/mapred/shuffle/merge-sort.rkt

BTW, I'm throwing down an inferencing gauntlet.  Here is a convenient
example of where TR's inferencing falls a bit short.
In merge-sort.rkt above.

(: merge-sort-inmem-blocks-to-disc (All (D) (Listof (Listof D))
(Sorter D) (Writer D) - (Listof (Block D
(define (merge-sort-inmem-blocks-to-disc lst-data sorter writer)
  (let: ((enum : (Enumerator D (Listof (Block D)))
(enumerator/select-from-n-lists lst-data sorter))
 (iter : (Iteratee D (Listof (Block D)))   (iter-block
(generate-rdd-block-filename) writer)))
(icomplete (enum iter

Here the let: bindings are necessary hints for TR inferencing to succeed.
I'd prefer.

(: merge-sort-inmem-blocks-to-disc (All (D) (Listof (Listof D)) (Sorter D) (
Writer D) - (Listof (Block D
(define (merge-sort-inmem-blocks-to-disc lst-data sorter writer)
(icomplete ((enumerator/select-from-n-lists lst-data sorter) (iter-bloc
(generate-rdd-block-filename) writer)))


Random musing follows.

If I could lay on more subject anecdote.  Consider Scala, probably
envisioned by Martin O. as a properly done core OO language with
relatively seamless functional layering, i.e., lambda smoothly filled in
around the edges.   An unintended consequence, I think, was how hell bent a
serious subset of Scala users were to use Scala as a Functional Language
at the core with OO smoothly filled in around the edges.  Scalaz, Scala
Type Classes et al.  A substantial core of Scala user effort in and around
essentially coding Haskell in Scala.

Abusing the analogy towards TR and R.  I think a potential unintended
consequence is that TR will encourage continued user pressure on TR
development for further ability to code Haskell in TR  e.g. Co/contra
type variance (for collections), type bounds, generics (data types), ,
TRing of generics methods (gen:*) setting a basis for TR's version of Type
Classes, etc.

Extrapolating to a hypothetical future, TR will ultimately result in a
distinct separation in from R.  Technically, the development of a library
in TR will always allow for some sort of mechanical means of isomorphic
translation to R.   Practically, future libraries in TR will get more and
more HOF (Haskell-idiomatic if you will) like and mapping down to R, which
will technically work/run, however code/library interfaces will retain
their HOF characteristics to such an extant that use in R coding will be a
struggle.  Though leverage lifting R into TR, analogous how Scala supports
leveraging the vast amount of Java code will be common.

In other words, three years from now, the same developer fluent in R and TR
idioms, developing the same library, would fundamentally write two
different libraries, technically isomorphic (translatable), but practically
for-use distinct.

Bottom line wild hair prediction.  Beyond Racket core collections which by
skill and effort by core maintainers to be bi-use (R and TR), future 3rd
party libraries / collections will be TR xor R in nature.

While I grant it is a huge overreach to offer analogy of religious wars
into programming language musings, TR and R may very well turn out to be
Catholic and Protestants (Emacs and Vi) all over again.  You are one or the
other and rarely both.


On Tue, Jan 1, 2013 at 7:42 PM, Neil Toronto neil.toro...@gmail.com wrote:

 On 01/01/2013 03:35 PM, Matthias Felleisen wrote:


 Neil,

 thanks for the user story. We should hear more of those for all kinds of
 corners in our world.


 You're welcome!

  Question: did you start the math library in an untyped form (and switch)
 or did you go with types from the get-go?


 It's all been in Typed Racket from the beginning. This was initially
 because I mostly had floating-point functions planned, and I wanted TR's
 help proving that I never used non-flonums by mistake. Also, I wanted the
 special functions to have performance competitive with C implementations.

 When I decided to do arrays, Typed Racket was again the natural choice.
 First, because it's not possible to use `require/typed' to import
 polymorphic struct types. Second, because it allowed me to avoid a lot of