views:

118

answers:

2
type Foo = 
    class
        inherit Bar

        val _stuff : int

        new (stuff : int) = {
            inherit Bar()
            _stuff = stuff
        }
    end

I want to add this code in above constructor:

if (stuff < 0) then raise (ArgumentOutOfRangeException "Stuff must be positive.")
else ()

How can I achieve this in F# ?

+3  A: 

Hm, looks like a hole in the grammar; I'll file a suggestion. You can work around it like this:

type Bar() = class end

type Foo =     
    class        
        inherit Bar        
        val _stuff : int        
        private new (stuff : int, dummyUnused : int) = {            
            inherit Bar()            
            _stuff = stuff        
            }
        new (stuff : int) = 
            Foo(stuff, 0)
            then
                if (stuff < 0) then 
                    raise (System.ArgumentOutOfRangeException 
                             "Stuff must be positive.")
    end

where the first constructor is a dummy whose sole purpose is to allow the second real constructor to call it with the "other-constructor then side-effect" syntax.

However you'll live a longer, happier life if you use

type Foo(_stuff:int) =     
    inherit Bar()
    do
        if (_stuff < 0) then 
            raise (System.ArgumentOutOfRangeException "Stuff must be positive.")

instead. Use classes with primary constructors whenever possible. (A 'primary constructor' is the constructor at the class declaration - in the example above, the arguments immediately after "type Foo" are the constructor arguments, and any let/do statements inside the class body define the primary constructor body.)

EDIT:

Here's a much simpler workaround

type Foo =     
    class        
        inherit Bar        
        val _stuff : int        
        new (stuff : int) = 
            let effect = 
                if (stuff < 0) then 
                    raise (System.ArgumentOutOfRangeException 
                            "Stuff must be positive.")
            {            
            inherit Bar()            
            _stuff = stuff        
            }
    end
Brian
Thanks. I know about primary ctor, in my case I need several ctors, so the only way to go is class/end syntax.
Stringer Bell
+4  A: 

You can do this without needing any workarounds, but the placement of the initial left curly is fairly sensitive (or maybe the parser is buggy?). To do the effect first:

type Foo =
  class
    inherit Bar
    val _stuff : int
    new (stuff : int) = 
      if stuff < 0 then raise (System.ArgumentOutOfRangeException("Stuff must be positive"))
      { 
        inherit Bar() 
        _stuff = stuff 
      }
  end

To do the effect second:

type Foo =
  class
    inherit Bar
    val _stuff : int
    new (stuff : int) = 
      { 
        inherit Bar() 
        _stuff = stuff 
      }
      then if stuff < 0 then raise (System.ArgumentOutOfRangeException("Stuff must be positive"))
  end
kvb
Neat, good call.
Brian
Thanks! It just works. The placement of braces is indeed picky.
Stringer Bell