1) I highly suggest starting in Typed Racket if you are going to go end up there. I made the mistake of writing it untyped and then retrofitting which clearly is the more difficult path.
2) The conversion caught one likely-to-happen-sometime bug, thank you.
3) The end-product appears to be a 50%-performance hybrid due to boundary contracts, but ameliorated runtime-wise by utilizing the typed/racket/no-check language after it's all working in type checked mode.
4) I failed to create a valid new language with conditional inclusion of typed and no-check variants, but a command line or in-program conditional ability to disable types would permit an easy to accept morphing systems which need to gently attain 100% typed nature. At the moment, I use a Unix shell script to doctor the #lang lines. For instance 'raco -no-check exe ...' would really be nice after concluding that my slow hybrid is operating correctly.
5) When retrofitting, Dr Racket nicely points out errors, which in quantity should perhaps be limited to speed the retrofit cycle. Being familiar with G++ template errors, I was not too shocked. One thing that I learned was instead of attacking the first error which often was deeper in a function, it was more profitable to start at the outside, i.e. the function signature, and allow that information to imply further information. I found that otherwise, I ended up with correct but superfluous annotations.
6) A few missing typed versions of libraries were what caused me to not start there, notably the lack of typed/db.
Thanks,
JG
Assuming that I'm reasonably sure from empirical tests that my contracts implied by the typed/untyped bridge are being satisfied, then this looks like a good idea.
Thanks for this addition to the system.
--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Seeing all the options, I believe that my favorite one is to type only at the border of my code, leaving the implementation in untyped Racket. By dropping the contract cost, code still goes fast, and the borders are type-checked.
For the meantime, I'll be doing this on new code
#lang typed/racket[/unsafe maybe]
(module 'hundred-lines-of-untyped racket
...
(define (my-function A B C)
...)))
(require/typed/provide 'hundred-lines-of-untyped
[ my-function (-> NICE TYPED ARGS RESULT) ])
If I understand this correctly, the unsafe version will perform the same static checks on callers of the functions published by (provide) but not incur contract cost.
If I understand this correctly, the unsafe version will perform the same static checks on callers of the functions published by (provide) but not incur contract cost.
Not sure I understand this stance:
* Does this mean if I want to use types proactively, TR is not a recommended PL?
* Or maybe it means adding types proactively is just not a recommended way to go in general, and types should only be added when the code base reaches certain trigger conditions?
> The actual purpose is to record with sound, checked types what the designer had in his head retroactively so that developers can benefit from this type information and so that the creation of *new code* can benefit from the (shallow but large) advantages of types and type checking.
BTW I did read this "actual purpose" paragraph. I'm just not sure how this answers my comments above :-).
> I don't understand this bullet. Bullet 1 says your code is now completely typed. Our experience is that completely typed versions are about as fast and on many occasions (eg., numeric) faster than completely untyped versions.
>
Yes, it was hybrid and is still, although today I made quite a few conversions where the cost/benefit (all mental cost/benefit, not speed) was conducive. This project is 40 files, 17 of which are hybrid with untyped code in submodules.
I started this Typed Racket in mid-December, but I'm getting there. My feeling is that I rather like making small modules with typed borders but sometimes untyped implementations. I look forward to seeing future performance improvements in these hybrids.
I'm looking for a middle ground between Python and C++, the two basic language tools in use at the office. I like typing fast with my fingers and typing loose with my data, until it passes 100 lines of Python, the point at which my opinion flips 180 degrees. After 100 lines, my option is to go to C++ or put another tool in the mix. Here are my constraints for a potential middle ground tool:
1) It must run on command-line non-X11 Linux, (and OSX as well if possible)
2) It must have a reasonable FFI to use our proprietary C++ libraries and allow foreign controlled data structures. There are pointers to substantial C++ side heap allocations requiring execution of C++ destructors at disposal time.
3) The nature of our library calls is that a language permitting optional named arguments
is almost a requirement to harness the capabilities of our library.
4) It must be considerably more productive than C++, otherwise it's C++
5) I've had enough uncaught flaws in Python that I'm now convinced that I need types.
6) It needs pattern matching, otherwise I'm back to C++, flex and bison or I have to figure out Stroustrup's Mach 7 which does not yet seem settled.
7) A reasonable size, polite, and intelligent group driving the technology.
My preferences include:
1) reasonably fast executables
2) Lightweight threads
3) Reasonable ability to use multiple cores safely.
4) Reliable environment generating reliable JavaScript
5) Immutability of data
6) Weighted more towards functions than objects
So, two things come to mind, Racket and SBCL because I've used them before, and the ML family - Haskell, OCaml, and Scala. Having tried Scala, I like the language but the associated environmental baggage appeared heavy and brittle from build dependencies. Both Haskell and OCaml seem quite plausible. Having types potentially in Racket keeps it in the running.
Anyway, Racket floated first to the top because I reimplemented a network service that really needed pattern matching to combat the growing complexity of patterns. I grabbed a familar (untyped) Racket and made a prototype. Unfortunately, the prototype worked so well that I'm using it now for real. Nevetheless, it has the smell of something that might be easier to maintain long-term with compiler-checked type annotations. Typed Racket has improved or at least my utilization of it considerably since I looked at it about 4 years back. Likewise, the places module which had previously been for me ungrokkable and lethargic was now easy and fast enough.
While those MLs are definitely still in mind, I'm going to get more comfortable with Typed Racket first.
With these constraints seems like http://extempore.moso.com.au/ could be interesting to you. It implements this http://extempore.moso.com.au/temporal_recursion.html model that I had not heard about before.
> My preferences include:
>
> 1) reasonably fast executables
> 2) Lightweight threads
> 3) Reasonable ability to use multiple cores safely.
> 4) Reliable environment generating reliable JavaScript
> 5) Immutability of data
> 6) Weighted more towards functions than objects
>
>
> So, two things come to mind, Racket and SBCL because I've used them before, and the ML family - Haskell, OCaml, and Scala. Having tried Scala, I like the language but the associated environmental baggage appeared heavy and brittle from build dependencies. Both Haskell and OCaml seem quite plausible. Having types potentially in Racket keeps it in the running.
>
I really like ML like languages, but the reason I enjoy racket more is... basically s-expressions :-).
In both Haskell and OCaml simply printing or inspecting a value of a custom data type is a bit convoluted when you compare it to more dynamic language like racket.
For a long while OCaml had some ambiguities about which macro processor was the go-to one... now there's something new that is also nothing as easy as s-expression manipulation (ppx something...). In Haskell I don't even know how I'd write some macro-like behavior.
If I could have built-in ADTs, pattern matching and s-expressions on a single language, I'd be a happy programmer :).