Pages: 1 2 3 4 5 6 7 8 9 10 11 ... 63 >>

31/07/10

Permalink 10:17:19 am, 280 words
Categories: Games

First impressions of the Kinect

So I got a chance to see a Kinect in action today, although I didn’t play myself. Here are some impressions.

  1. The whole thing was technically more impressive than I had thought it would be. No finger tracking, but [once it decided which person to track,] it looked smooth and pretty accurate. A lot smoother than the demo I saw last year.
  2. One cool touch is that the Kinect swivels upward when booting. It was unaccountably impressive, although I don’t know if it’s technically necessary. It somehow makes the thing look intelligent.
  3. Safety warnings? Three of them? (Maybe it was only two, but it reminds me precisely of the Wii)
  4. Except for graphics and input system, the included games are early 80’s arcade designs, just like all those Wii games. Good party games, not much else.
  5. Well, let me amend that statement. There are genius games in the simple early 80’s arcade style. But not many. You can count the games that outlived that era on one hand.
  6. And there are innovative ways to incorporate Kinect technology into a primarily gamepad-based game. For example, Johnny Lee’s head-tracking technology is possible for single player Kinect games. But coming up with new ideas is hard, and it’s not something that happens in the game industry much. I think Johnny Lee works for XBox now, so there’s some hope. But only a little, because I think the bottom line is that new gameplay doesn’t sell as well as copies of existing gameplay.
  7. All in all, I don’t have much hope that the cool tech in the Kinect will be used to create much more than copies of Wii games. I hope I’m wrong.

09/07/10

Permalink 09:54:23 pm, 258 words
Categories: Announcements [A]

Probable hiatus this summer

I just started work at Bing, so don’t expect many (any) blog posts for the next month or two.

Actually, the real reason is that I have stopped working on Fing until I can finish my dissertation revisions. There aren’t many—I estimate about a month’s worth—but who knows how much furniture/clothes/computer/phone shopping will interfere on the weekends. If there’s one thing I’ve learned during the move, it’s that serious shopping takes FOREVER. Also that it’s really tiring.

But that means that I won’t have anything super interesting to write about in the form of Fing code analysis. Or even anything at all, since I guess “super interesting” is about three notches about the normal fare for this blog.

Oh, and I just went through the Mandatory Online Legal Training today. So let me remind you: I do not speak for Bing or Microsoft on this blog. Even if I do discuss Bing, I do not do it in an official capacity, and my statements should not be taken to be indicative of any Bing policies or future directions. I’m not even going to tell you my microsoft e-mail address, except to say that it’s like 10 times better than the alphabet soup I got from Indiana University. I must have been at least the 23rd Nathan Sanders to go to IU.

And now that I know all about trademark law, who knows whether Fing will continue to be called Fing. I may have to change the name to F#$`ing after all.

17/06/10

Permalink 09:04:36 am, 1223 words
Categories: Code

F# Warts

Now that I’ve been using F# for real code for almost a month, I’ve noticed some warts. That’s pretty fast for a new language, but I am coming from Haskell, which is very similar. So some of these are warts on Haskell too, and others are complaints that F# is not Haskell.

Warts

  1. let for top-level functions instead of top-level pattern matching. Haskell’s pattern matching is the right default, but F# is too much an ML to change it. (I bet that Don Syme thought seriously about it at some point, though.)
  2. F# is a huge language because of .NET/ML dual heritage. There is massive redundancy so that both .NET people and ML people can pick up the language easily. It evokes memories of C++. At least F# 3.0 is unlikely to bolt on a whole NOTHER programming paradigm. I hope.
  3. As a side effect of the dual heritage, type syntax is not iconic like Haskell’s. Again, I’m sure the F# designers considered a change, but .NET programmers are already used to list<int> and, unlike Haskell, you also have the related types int[] and seq<int>.
  4. Another side effect of the dual heritage is that there are LOTS of keywords. There are a lot to memorise and usually two or three matching keywords to type every time you use them. while/do, for/in/do, match/with, etc.
  5. Infix functions and prefix operators are not as convenient as Haskell. This is really minor, but F# doesn’t have operator sections, and you have to fake the infixing backquotes with a reverse/pipe operator pair. Given the other syntax borrowed from Haskell, I had hoped that at least operator sections might make it in.

Those are mostly syntactic warts that I noticed. Nothing major, and CERTAINLY much improved from O’Caml, whose designers have paid very little attention to syntax. The semantic warts are a little more serious.

  1. The top-to-bottom, left-to-right compilation and baroque type system* restrict the order of expression somewhat.
  2. The monomorphism restriction means a lot of lambda-lifts (or type annotations).
  3. Even more lambda lifts occur because methods and properties are not functions (and the type checker gets dramatically dumber around OO constructs).
  4. A baroque OO type system instead of type classes, plus a love of explicitness, means that monads are much less generic/polymorphic than in Haskell. Theoretically, this is a huge demerit, because it makes it hard to write, for example, a truly generic mapM or sequence. Practically, however, monads are used less in F# anyway, and F# prefers explicitness—witness how frequently modules are used for namespacing compared to Haskell. So this is a matter of taste.. Have you heard of the BASIC monad? Typeclass abuse in Haskell can be quite scary.**

Examples

  1. No top-level pattern matching:
    let rec merge firstArg secondArg =
      match firstArg,secondArg with
      | [],[] -> ...
  2. Dual .NET/ML heritage:

    // struct
    type Point3D =
      struct
        val x: float
        val y: float
        val z: float
      end
    // record
    type Point3D = { 
      x : float; 
      y: float; 
      z: float; 
    }
  3. Non-iconic types: list<int> instead of [int] and int * string instead of (int,string).
  4. Too many keywords: while/do, for/in/do, match/with, class, struct, do, do!, yield, yield!, let, let!, return, return!, fun, function, try/finally, try/with…it’s a good thing that the indentation-based light syntax at least gets rid of the block-ending keywords.
  5. No infix/prefix flexibility:
    Seq.append (Seq.filter ((=) foo) x) seq2
  6. Strict order of compilation:
    let f l = l |> Seq.filter ((<>) foo)
    let main = printfn "%s" (f [1;2;3])
    // `main` has to appear after `f` since it references `f`. 
    // But that means the type of `l` can't be (completely) inferred 
    // `because `f` has no context for it.
    
  7. Monomorphism restriction:

    // both fail because generic functions as values are not allowed
    let f = g >> h >> i
    let csv = sepBy (pchar ',') (many anyChar)
  8. No 1st-class methods/properties:

    // both fail because neither properties nor methods 
    // can be used as functions
    let xvalues = Seq.map Point3D.x points
    let allsplits = Seq.map (string.Split [| ',' |]) filelines
  9. No generic monads:
    let sequence : ??? = ???
    I’m pretty sure even if you could write generic code for sequence, the type is impossible to express in .NET: list<’m<’a>> -> ‘m<list<’a>>.

Workarounds

  1. No top-level pattern matching:
    let rec map f = function
    | [] -> []
    | (x::xs) -> f x :: map xs
    // NOTE: Example only! Do NOT write List.map this way.
        

    The last argument is the most likely to be pattern-matched anyway, probably about 90% of the time.

  2. Dual .NET/ML heritage: Same as C++: Learn the whole language, then subset.
  3. Non-iconic types: Get used to it. It’s not that bad. Or just use arrays everywhere; you don’t usually write array<int>.
  4. Too many keywords: Subset! But this is not much of a workaround.
  5. No infix/prefix flexibility:
    Seq.filter ((=) foo) x |>Seq.append<| seq2
    But that only gives you infix functions, it doesn’t make prefix operators any prettier.
  6. Strict order of compilation: Put everything in a class—I think? Even if this solves the problem, it’s not a natural solution for some problems.
  7. Monomorphism restriction:

    // make a syntactic function or annotate type
    let f x = x |> g |> h |> i
    let csv : Parser<char,unit> = sepBy (pchar ',') (many anyChar)
  8. No 1st-class properties or methods:

    let xvalues = points |> Seq.map (fun p -> p.x)
    let allsplits = filelines |> Seq.map (fun s -> s.Split [| ',' |])

    Note that type inference doesn’t work unless the sequence being mapped are to the left of the function wrapping the property or method. There has been a tiny bit of discussion about specific syntax for this, so that something like this would be possible:

    let xvalues = points |> Seq.map Point3D#x
    let allsplits = filelines |> Seq.map (#Split [| ',' |])
    
  9. No generic monads: I don’t know that there is a workaround for this. I thought I had blogged earlier about a workaround, but I can’t find it now. In any case, this may not be a practical problem, since F# is generally used for larger systems with more developers than Haskell. There, a extra explicitness/verbosity is a decent tradeoff.

So far I like F# quite a bit. It’s really easy to pick up if you already know Haskell and/or O’Caml, and state is convenient at times, especially in an eager language. The semantics are solid. I’m really happy that Microsoft includes F# with Visual Studio now. They’re pushing the idea that the mainstream language doesn’t have to be a over-simplified lowest-common-denominator.

*It’s a perfectly good type system—for an OO type system. For a functional language (Hindley-Milner style), though, an OO type system adds a lot of complexity without giving as much as power as type classes (for example).

**I can’t find it now, but the basic idea is this: make a Num instance that wraps the Continuation monad, storing the “line number” in a map Int -> Continuation. Define a function goto that takes an int and looks up that continuation, calling it. I think. That’s conjecture, because I never saw the code, and I can’t find anything online. I think it was a joke going on the one time I stepped into #haskell.

main = do
  100 (putStrLn "Hello World")
  200 (goto 100)

16/06/10

Permalink 08:33:58 am, 876 words
Categories: Code

Developing Fing, part 4: command line interface

The previous entry in this series finished (sort of) the parser. Two things have been hurting my motivation to continue blogging. First is that I needed to blog about the F# version of the parser, since the version I’ve already written about is Haskell. I don’t really want to write about the same thing twice. Second, and more important, is that I was busy working on the actual code instead of blogging about it. There is a decent version online at http://github.com/sandersn/fing. It’s still missing three major features (web app, subtyping and type aliases), but it works for everything in FSharp.Core.

Now I’m at the point of bringing tests up-to-date with the code, so, you guessed it, I have more motivation to blog again. But I still don’t have the gumption to talk about the parser. I’m sick of parsing for now, so maybe I’ll write it up in six months, or when I have time to revamp the core token parser, which is super ugly.

Instead I’m going to write about simple stuff: the command line interface. It’s straightforward, but there is at least one interesting principle in there. I’ll work up to the more complicated parts of the code later.

module Main

[<EntryPoint>]
let main args = 
  let args,argmap = Opt.parse args
  let getrefs s = Seq.choose id (Opt.mapGet s argmap Seq.empty)
  let references = getrefs "r" |>Seq.append<| getrefs "reference"
  Fing.addReferences references
  match args with
  | [| t |] -> Fing.textSearch t
  | _ -> printfn "Fing is F# API Search. (rest of usage message...)"

There isn’t much surprising here: first I call Opt.parse to produce a list of arguments and keyword arguments. Then I define a function to arguments matching a string s, and use it to build a sequence of “-r” and “–reference” arguments. Well, wait a minute, that’s kind of weird, a nested function. I could have done it this way:

  let rs = Seq.choose id (Opt.mapGet s argmap Seq.empty)
  let references = Seq.choose id (Opt.mapGet s argmap Seq.empty)
  Fing.addReferences (rs |>Seq.append<| references)

And that’s not bad style, it just isn’t ideal. In the second way, I name the two values, repeating the code that generates them. In the first way, I name the code that generates the two values and repeat only the name I gave it. There’s a little more repetition the second way, with not much benefit.

(I also get a chance to show off the infix-function trick that I discovered. I’m still very proud of that.)

This illustrates one of the subtler aspects of functional programming. The three aspects of functional programming that I think of first are:

  1. Immutability
  2. Functions as data
  3. Functions everywhere

Well, ‘functions as data’ looks like a subset of ‘functions everywhere’, but both have a specific meaning. ‘functions as data’ refers to uses of functions that doesn’t occur at all in imperative or OO style: passing them around, saving them in data structures. ‘functions everywhere’ refers to the size and frequency of functions, which is far higher than in imperative or OO styles. Even though the ideal for all styles is many small functions (or methods), functional languages make it natural to achieve this ideal. It is definitely not natural in normal imperative, structured code, and all the “short methods are good for you” advice books indicate to me that it’s not natural in OO either. In any case, if you compare functional languages and OO languages, I think you will find a much greater percentage of the former make short function definition natural.

So, to finish up:

  match args with
  | [| t |] -> Fing.textSearch t
  | _ -> printfn "Fing is F# API Search. (rest of usage message...)"

There’s not much to say here, except that I am glad pattern matching works on arrays and I wonder why it doesn’t work on sequences. I can think of two reasons: first, seq (aka IEnumerable) is an interface, and pattern matching is a concrete operation. Second, it might be inefficient to pattern match the tail of a sequence. I don’t grok the efficiency model of iterators, but I think that, because they’re not defined recursively, a pattern-match, which treats them as recursive, must create a new enumerator to point to the tail of the matched sequence.

Regardless, it’s an inconvenience and likely one that can be fixed with an active pattern. That’s another F# feature I still need to learn.


Post-script: I had to write Opt.parse myself. I couldn’t find one built-in to .NET. Maybe I was just didn’t search hard enough, but all I found was half-baked code online. I started with one example, intending to translate it to F# in order to understand it. Once I understood it, I saw that it was buggy and incomplete, and wrote my own from scratch. (I just want back, read the comments below the code, and found a link to a reflection/annotation-based library called Consolery. Nothing in the standard library though.

Anyway, continuing with my earlier theme of “I’ll blog about whatever I want to blog about", I’ll probably talk about Opt.parse next. You might be able to help me iron out some of its ugly parts.

15/06/10

Permalink 10:51:25 am, 306 words
Categories: Announcements [A]

Announcements June 2010

It’s about time some changes were made around here.

The first you’ll notice is that the title of this site is no longer Journal, but Blogg. I didn’t like the word ‘blog’ when it was new, but I eventually got used to it. If I’m going to use it, though, it’s going to be the Scandinavian version.

Why Scandinavian? I just finished my doctorate with a dissertation on Swedish dialects. I don’t actually speak Swedish*, but I’ve picked up a little while getting my code to process it. So the change commemorates the fact that I am now (almost) officially Dr Sanders. Or Herr Doktor Sanders, a title bestowed upon students whose advisors are German.

The reason it’s (almost) official is that I have a few revisions to make on the dissertation. When those are done, I’ll upload the final version here. If you really want to see it before then, contact me.

Second, Fing 0.1 is out at github. There’s a binary in case you don’t want to download the source. There’s also a script to load Fing into fsi for interactive use. 0.1 can find functions even if you get the order of arguments wrong. You can also have it search your own assemblies, not just FSharp.Core. But type aliasing doesn’t work right yet, so if you rely on aliases with type variable arguments, you are out of luck until the next version.

The last announcement is that (if you didn’t already know), I’m starting a job at Bing at the beginning of July. Now is a good time to remind everyone that I don’t represent any of my employers, past, present or future, and that this blog is not connected officially or unofficially to Microsoft.

*Jag talar inte Svenska, med jag talar Swedish Chef, darfor vi har de har valdigt har bork bork bork!

1 2 3 4 5 6 7 8 9 10 11 ... 63 >>

powered by b2evolution free blog software