elmattic
elmattic

Reputation: 12184

Adding code in constructor with alternative class syntax

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# ?

Upvotes: 2

Views: 306

Answers (2)

kvb
kvb

Reputation: 55185

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

Upvotes: 5

Brian
Brian

Reputation: 118935

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

Upvotes: 4

Related Questions