[Question]
  [
Inspired by [this question](https://codegolf.stackexchange.com/questions/66202/product-over-a-range) by [@CᴏɴᴏʀO'Bʀɪᴇɴ](https://codegolf.stackexchange.com/users/31957/c%E1%B4%8F%C9%B4%E1%B4%8F%CA%80-ob%CA%80%C9%AA%E1%B4%87%C9%B4). 
Taken from the question:
> 
> Your task is simple: given two integers a and b, output ∏[a,b]; that
>  is, the product of the range between a and b. You may take a and b in
>  any reasonable format, whether that be arguments to a function, a list
>  input, STDIN, et cetera. You may output in any reasonable format, such
>  as a return value (for functions) or STDOUT. a will always be less
>  than b.
> 
> 
> Note that the end may be exclusive or inclusive of b. I'm not picky.
>  ^\_^
> 
> 
> 
The difference for this challenge is we are going to be picky about the range type. Input is a string of the form `[a,b]`, `(a,b]`, `[a,b)`, or `(a,b)` where a `[]` is an inclusive boundary and `()` is an exclusive boundary. Given the explicit boundaries, provide the product of the range. Also the input range will always include at least 1 number, meaning ranges like `(3,4)` are invalid and need not be tested.
## Test cases
```
[a,b) => result
[2,5) => 24
[5,10) => 15120
[-4,3) => 0
[0,3) => 0
[-4,0) => 24
[a,b] => result
[2,5] => 120
[5,10] => 151200
[-4,3] => 0
[0,3] => 0
[-4,-1] => 24
(a,b] => result
(2,5] => 60
(5,10] => 30240
(-4,3] => 0
(0,3] => 6
(-4,-1] => -6
(a,b) => result
(2,5) => 12
(5,10) => 3024
(-4,3) => 0
(0,3) => 2
(-4,0) => -6
```
---
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest program in bytes wins.
---
## Leaderboard
The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
```
## Language Name, N bytes
```
where `N` is the size of your submission. If you improve your score, you *can* keep old scores in the headline, by striking them through. For instance:
```
## Ruby, <s>104</s> <s>101</s> 96 bytes
```
If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the *last* number in the header:
```
## Perl, 43 + 2 (-p flag) = 45 bytes
```
You can also make the language name a link which will then show up in the snippet:
```
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
```
```
var QUESTION_ID=66285,OVERRIDE_USER=44713;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
```
```
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
```
```
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
```
  
[Answer]
# LabVIEW, 38 [LabVIEW Primitives](http://meta.codegolf.stackexchange.com/a/7589/39490)
"slightly" modified, now sets the ranges by scanning for () and [] and adding the index to the numbers.
[![first](https://i.stack.imgur.com/L0Bmo.gif)](https://i.stack.imgur.com/L0Bmo.gif)
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), ~~24~~, 18 bytes
```
₌≬k+iE₍ht‛(]f=+÷rΠ
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyLhuaAiLCIiLCLigoziiaxrK2lF4oKNaHTigJsoXWY9K8O3cs6gIiwiIiwiKDIsIDVdIl0=)
I'm actually really proud of this answer, because it uses the new modifier parsing of 2.6.
With syntax highlighting:
[![syntax highlighted version](https://i.stack.imgur.com/PPx1y.png)](https://i.stack.imgur.com/PPx1y.png)
## Explained
```
₌≬k+iE₍ht‛(]f=+÷rΠ
₌                  # Apply the following to the same stack:
 ≬                 #   The next 3 elements as a single lambda, taking argument n:
  k+iE             #     eval(n[1:-1]) - the two numbers separated by a comma
₌                  #   and
      ₍ht          #   [n[0], n[-1]] - the range brackets
         ‛(]f=     # Does the first bracket equal "(" and does the last bracket equal "]" - this determines how much to offset the range; because the two numbers in the original input will be passed to Vyxal's range function which acts like python's range() function
              +    # add those offsets: an exclusive range start means the first number needs to be incremented because range() includes the first argument. an inclusive range start means the last number needs to be incremented because range() stops before the last argument.
               ÷r  # push the range between the two numbers + their offsets
                 Π # and take the product
```
[Answer]
## Minecraft 15w35a+, program size 638 total (see below)
Same as my answer [here](https://codegolf.stackexchange.com/a/66329/36670), but modified. Since Minecraft has no string input, I took the liberty of keeping scoreboard input. If that is a problem, consider this answer non-competitive.
[![enter image description here](https://i.stack.imgur.com/172CS.png)](https://i.stack.imgur.com/172CS.png)
This calculates `PI a,b` with inclusive / exclusive specified by the two levers. [![enter image description here](https://i.stack.imgur.com/XzAy3.png)](https://i.stack.imgur.com/XzAy3.png)Input is given by using these two commands: `/scoreboard players set A A {num}` and `/scoreboard players set B A {num}`. Remember to use `/scoreboard objectives add A dummy` before input.
Scored using: `{program size} + ( 2 * {input command} ) + {scoreboard command} = 538 + ( 2 * 33 ) + 34 = 638`.
This code corresponds to the following psuedocode:
```
R = 1
T = A
loop:
  R *= A
  A += 1
  if A == B:
    if A.exclusive:
      R /= T
    if B.exclusive:
      R /= B
    print R
    end program
```
Download the world [here](http://www.mediafire.com/download/3698b1mumrtmtzj/PPCG__Product_Inclusive_Exclusive.zip).
[Answer]
## Python 2, 72 bytes
```
lambda s:reduce(int.__mul__,range(*eval(s[1:-1]+'+'+`']'in s`))[s<'[':])
```
To extract the numbers we evaluate `s[1:-1]`, the input string with ends removed, which gives a tuple. The idea is to get the `range` of this tuple and take the product.
```
lambda s:reduce(int.__mul__,range(*eval(s[1:-1]))
```
The fudging happens to adjust the endpoints. The upper endpoint is easy, just cut off the first element if the input starts with `(`, done as `[s<'[':]`.
The other endpoint is trickier. Python doesn't have a clean way to conditionally remove the last element of a list because `l[:0]` removes the whole thing. So, we do something weird. We modify the tuple string before it is evaluated to tack on the string `"+True"` or `"+False"` depending on whether s ends in `]` or `)`. The result is that something like `3,7` becomes either `3,7+False` which is `3,7`, or `3,7+True` which is `3,8`.
Alternate, prettier 72:
```
lambda s:eval("reduce(int.__mul__,range((s<'[')+%s+(']'in s)))"%s[1:-1])
```
[Answer]
# Pyth, 20 bytes
```
*FPW}\)ztW}\(z}FvtPz
```
Try it online: [Demonstration](http://pyth.herokuapp.com/?code=%2AFPW%7D%5C%29ztW%7D%5C%28z%7DFvtPz&test_suite_input=%282%2C8%5D%0A%5B2%2C8%29%0A%5B2%2C8%5D%0A%282%2C8%29&test_suite=0&input=%282%2C8%5D) or [Test Suite](http://pyth.herokuapp.com/?code=%2AFPW%7D%5C%29ztW%7D%5C%28z%7DFvtPz&test_suite_input=%282%2C8%5D%0A%5B2%2C8%29%0A%5B2%2C8%5D%0A%282%2C8%29&test_suite=1&input=%282%2C8%5D)
### Explanation:
```
*FPW}\)ztW}\(z}FvtPz   implicit: z = input string
                 tPz   remove the first and last character of z
                v      evaluate, returns a tuple of numbers
              }F       inclusive range
        tW             remove the first number, if
          }\(z            "(" in z
  PW                   remove the last number, if
    }\)z                  ")" in z
*F                     compute the product of the remaining numbers
```
[Answer]
# Ruby, ~~79~~ 77 bytes
```
->s{a,b=s.scan /\-?\d+/;(a.to_i+(s[?[]?0:1)..b.to_i-(s[?]]?0:1)).reduce 1,:*}
```
**~~79 bytes~~**
```
->s{a,b=s.scan(/\-?\d+/).map &:to_i;((s[?[]?a:a+1)..(s[?]]?b:b-1)).reduce 1,:*}
```
**Ungolfed:**
```
-> s {
  a,b=s.scan /\-?\d+/    # Extracts integers from the input string, s
  (
    a.to_i+(s[?[]?0:1).. # Increase start of the range by 1 if s contains `(`
    b.to_i-(s[?]]?0:1)   # Decrease end of the range by 1 if s contains `)`
  ).reduce 1,:*
}
```
**Usage:**
```
->s{a,b=s.scan /\-?\d+/;(a.to_i+(s[?[]?0:1)..b.to_i-(s[?]]?0:1)).reduce 1,:*}["(2,5]"]
=> 60
```
[Answer]
## Seriously, 31 bytes
```
,#d@p@',@s`εj≈`Mi(@)']=+)'(=+xπ
```
Takes input as a string (wrapped in double quotes)
[Try it online](http://seriouslylang.herokuapp.com/link/code=2c2364407040272c407360ee6af7604d69284029275d3d2b2927283d2b78e3&input=) (input must be manually entered)
Explanation:
```
,#d@p@                             get input, take first and last character off and push them individually
      ',@s`εj≈`Mi                  split on commas, map: join on empty, cast to int; explode list
                 (@)']=+)'(=+      increment start and end if braces are ( and ] respectively (since range does [a,b))
                             xπ    make range, push product
      
```
[Answer]
# JavaScript (ES6), 68 bytes
```
s=>(f=_=>a>b||a++*f())([a,b,c]=s.match(/-?\d+|]/g),a-=-(s<'['),b-=!c)
```
[Answer]
# [Julia 0.4](http://julialang.org/), 75 bytes
```
s->prod((x=map(parse,split(s[2:end-1],",")))[1]+(s[1]<41):x[2]-(s[end]<42))
```
[Try it online!](https://tio.run/##Xc4xDsIwDIXhnVMgT7ZwhlhlqWjFPawMkdqKokKjGkRvHzJCxvfpH979vcwxT10216dtHRD37hETprjZyJaW@YWm0o7PwfnAwEBE6sOpqA@XxlO7qwRXZkkKCFG@2m39HCcEFT4T0OEPwi9gXWBdqBOWShouZ4DyFw "Julia 0.4 – Try It Online")
This is an anonymous function that accepts a string and returns an integer. To call it, give it a name, e.g. `f=s->...`.
Ungolfed:
```
function f(s::AbstractString)
    # Extract the numbers in the input
    x = map(parse, split(s[2:end-1], ","))
    # Construct a range, incrementing or decrementing the endpoints
    # based on the ASCII value of the surrounding bracket
    r = x[1]+(s[1] == 40):x[2]-(s[end] == 41)
    # Return the product over the range
    return prod(r)
end
```
[Answer]
# Python 3, 104
```
y,r=input().split(',')
t=int(y[1:])+(y[0]<')')
for x in range(t+1,int(r[:-1])+(r[-1]>'[')):t*=x
print(t)
```
Takes input from stdin.
[Answer]
# MATLAB, ~~86~~ 70 bytes
```
s=sscanf(input(''),'%c%d,%d%c');a=s<42;disp(prod(a(1)+s(2):s(3)-a(4)))
```
This also works with **Octave**. You can try [online here](http://octave-online.net/?s=QHPazBNGkfyhbhbdFrYAnJeGZmDvKMKYapOgHyikJRbmUTQP). I have added the code as a script to that workspace, so you can just enter `productRange` at the prompt, then enter your input, e.g. `'(2,5]'`.
---
So the code first scans the input to extract the brackets and the numbers together:
```
s=sscanf(input(''),'%c%d,%d%c');
```
This returns an array which is made of `[bracket, number, number, bracket]`.
The array is compared with `42`, actually any number between 42 and 90 inclusive will do. This determines which sort of bracket it was, giving a 1 if it is an exclusive bracket, and a 0 if an inclusive bracket.
```
a=s<42;
```
Finally, we display the product of the required range:
```
disp(prod(a(1)+s(2):s(3)-a(4)))
```
The product is of numbers staring with the first number `s(2)` plus the first bracket type `a(1)` (which is a 1 if an exclusive bracket), ranging up to and including the second number `s(3)` minus the second bracket type `a(4)`. This gives the correct inclusive/exclusive range.
[Answer]
# PowerShell, ~~146~~ 104 Bytes
```
param($i)$a,$b=$i.trim("[]()")-split',';($a,(1+$a))[$i[0]-eq'(']..($b,(+$b-1))[$i[-1]-eq')']-join'*'|iex
```
Golfed off 42 bytes by changing how the numbers are extracted from the input. Woo!
```
param($i)                          # Takes input string as $i
$a,$b=$i.trim("[]()")-split','     # Trims the []() off $i, splits on comma,
                                   # stores the left in $a and the right in $b
($a,(1+$a))[$i[0]-eq'(']..($b,(+$b-1))[$i[-1]-eq')']-join'*'|iex
# Index into a dynamic array of either $a or $a+1 depending upon if the first
# character of our input string is a ( or not
# .. ranges that together with
# The same thing applied to $b, depending if the last character is ) or not
# Then that's joined with asterisks before
# Being executed (i.e., eval'd)
```
[Answer]
# [Perl 6](http://perl6.org), 60 bytes
```
{s/\((\-?\d+)/[$0^/;s/(\-?\d+)\)/^$0]/;s/\,/../;[*] EVAL $_}
```
There is a bit of mis-match because the way you would write the `(2,5]` example in Perl 6 would be `2^..5` (`[2^..5]` also works).  
So I have to swap `(2` with `[2^`, and `,` with `..`, then I have to `EVAL` it into a Range.
---
usage:
```
# give it a name
my &code = {...}
# the `$ =` is so that it gets a scalar instead of a constant
say code $ = '(2,5)'; # 12
say code $ = '[2,5)'; # 24
say code $ = '(2,5]'; # 60
say code $ = '[2,5]'; # 120
say code $ = '(-4,0)' # -6
say code $ = '[-4,0)' # 24
say code $ = '(-4,0]' # 0
say code $ = '[-4,0]' # 0
say code $ = '(-4,-1)' # 6
say code $ = '[-4,-1)' # -24
say code $ = '(-4,-1]' # -6
say code $ = '[-4,-1]' # 24
# this is perfectly cromulent,
# as it returns the identity of `*`
say code $ = '(3,4)'; # 1
```
[Answer]
## Mathematica, 128 bytes
```
1##&@@Range[(t=ToExpression)[""<>Rest@#]+Boole[#[[1]]=="("],t[""<>Most@#2]-Boole[Last@#2==")"]]&@@Characters/@#~StringSplit~","&
```
This is too long... Currently thinking about a `StringReplace` + `RegularExpression` solution.
[Answer]
# JavaScript (ES6), 90 bytes
```
s=>eval(`for(n=s.match(/-*\\d+/g),i=n[0],c=s[0]<"["||i;++i<+n[1]+(s.slice(-1)>")");)c*=i`)
```
## Explanation
```
s=>
  eval(`                    // use eval to allow for loop without return or {}
    for(
      n=s.match(/-*\\d+/g), // n = array of input numbers [ a, b ]
      i=n[0],               // i = current number to multiply the result by
      c=s[0]<"["||i;        // c = result, initialise to a if inclusive else 1
      ++i<+n[1]             // iterate from a to b
        +(s.slice(-1)>")"); // if the end is inclusive, increment 1 more time
    )
      c*=i                  // multiply result
  `)                        // implicit: return c
```
## Test
```
var solution = s=>eval(`for(n=s.match(/-*\\d+/g),i=n[0],c=s[0]<"["||i;++i<+n[1]+(s.slice(-1)>")");)c*=i`)
```
```
<input type="text" id="input" value="(5,10]" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>
```
[Answer]
# TI-Basic, 69 bytes
```
Input Str1
expr("{"+sub(Str1,2,length(Str1)-2
prod(randIntNoRep(min(Ans)+(sub(Str1,1,1)="("),max(Ans)-(sub(Str1,length(Str1),1)=")
```
Output is stored in `Ans` and displayed. Replace `randIntNoRep(` with `seq(I,I,` (+3 bytes) if the calculator does not support it.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 57 bytes
```
1##&@@ToExpression["Range"<>(#/."("->"[1+"/.")"->"-1]")]&
```
[Try it online!](https://tio.run/##TY9Ba4MwFMfv@RQSR4ks2RKrXpwibD3sNtbdQg5BbBtYjWgGhdLP7mKitbf/e3m/33s5S3NqztKoWo6HYmRhuKmqH727dH0zDEq3HH7L9tjAtxKFry8QQVJCzp6hzdGUCRMwEptR6aAI9qZX7XF3Mb2sDX/a173qzGfb/Rn/giGwTJ5jGBRl4KIAH5qDq8L6VvyqtsnBl500XJHyUL2f5GRq@qFSlkEQa2zXCoCv0yxW@iZGHuM0mnxxAniKGXUFS1lMAScJ3rraZrpG26Z3xvLCIRMwCcRdMBvEahCrwX59VqBFkVGA7oYtjRNbPwjQIshcexaQzAn82bEXRIvA89HK@7Nd20@R7B8 "Wolfram Language (Mathematica) – Try It Online")
Input a list of characters.
Fairly straightforward. Mathematica uses `[` `]` to introduce arguments, and `Range` is inclusive on both ends.
---
### [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 69 bytes
```
1##&@@ToExpression["Range"<>#~StringReplace~{"("->"[1+",")"->"-1]"}]&
```
[Try it online!](https://tio.run/##TY9Pb4MgGIfvfAqDS6MZJGjVi9N4WA@7Le1uhAMxtCVpxViWNDH2qzsE/@z2e19@zwPcub6KO9ey5uO5GCPf31XVjzo82048HlI1FB55cxHwo/RfJ93J5nIU7Y3X4tXDAOIS0ugdIhhOEUcMDmw3SuUVnisfnrrjtaZvp7qTrf5q2l/tThAEhslzBL2i9Gxk4FNR0EukhuImG5GDb9PUVOLyXElTDCBS010MoH4qIKkGNtIYpeEkiRNAUxQRO0RpFBNAcYL2djaZbNGsycoYnllkAiYBWwWzgW0GthnMf2dFsCgyAoLVsCdxYuZ/gmARZHY9C3BmBe7ZsROEi8Dx4ca7Z9u1a@HsDw "Wolfram Language (Mathematica) – Try It Online")
Input a string.
[Answer]
# Japt, ~~43~~ 41 bytes
```
[VW]=Uf"\\d+";ÂV+Â('A>Ug¹oÂW+Â('A<UtJ¹r*1
```
[Try it online!](http://ethproductions.github.io/japt?v=master&code=W1ZXXT1VZiJcXGQrIjvCVivCKCdBPlVnuW/CVyvCKCdBPFV0SrlyKjE=&input=Ils1LDEwKSI=)
[Answer]
# CJam, 34 bytes
```
r)\(@+"[()]"2/\.#\',/:i.+~1$-,f+:*
```
[Try it online](http://cjam.aditsu.net/#code=r)%5C(%40%2B%22%5B()%5D%222%2F%5C.%23%5C'%2C%2F%3Ai.%2B~1%24-%2Cf%2B%3A*&input=(5%2C10%5D)
Explanation:
```
r       Read input.
)       Split off last character.
\       Swap rest of input to top.
(       Split off first character.
@       Rotate last character to top.
+       Concatenate first and last character, which are the two braces.
"[()]"  Push string with all possible braces.
2/      Split it into start and end braces.
\       Swap braces from input to top.
.#      Apply find operator to vector elements, getting the position of each brace
        from input in corresponding list of possible braces. The lists of braces
        are ordered so that the position of each can be used as an offset for the
        start/end value of the interval.
\       Swap remaining input, which is a string with two numbers separated by
        a comma, to top.
',/     Split it at comma.
:i      Convert the two values from string to integer.
.+      Element-wise addition to add the offsets based on the brace types.
~       Unwrap the final start/end values for the interval.
1$      Copy start value to top.
-       Subtract it from end value.
,       Build 0-based list of values with correct length.
f+      Add the start value to all values.
:*      Reduce with multiplication.
```
[Answer]
# R, ~~102~~ 104 bytes
```
f=function(s){x=scan(t=gsub('\\(|\\[|,|\\)|\\]',' ',s))+c(grepl('^\\(',s),-(grepl('\\)$',s)));prod(x[1]:x[2])}
```
Ungolfed
```
f=function(s){
    # remove delimiting punctuation from input string, parse and return an atomic vector
    x=scan(t=gsub('\\(|\\[|,|\\)|\\]',' ',s)) +
    # add /subtract from the range dependent on the `[)` pre/suf-fixes
    c(grepl('^\\(',s),-(grepl('\\)$',s)))
    # get the product of the appropriate range of numbers
    prod(x[1]:x[2])
}
```
edit to allow negative numbers [at the expense of 2 more characters
[Answer]
# JavaScript (ES6), 79
As an anonymous method
```
r=>eval("[a,b,e]=r.match(/-?\\d+|.$/g);c=a-=-(r<'@');for(b-=e<'@';a++<b;)c*=a")
```
Test snippet
```
F=r=>eval("[a,b,e]=r.match(/-?\\d+|.$/g);c=a-=-(r<'@');for(b-=e<'@';a++<b;)c*=a")
// TEST
console.log=x=>O.innerHTML+=x+'\n'
;[
 ['[2,5)',24],['[5,10)',15120],['[-4,3)',0],['[0,3)',0],['[-4,0)',24],
 ['[2,5]',120],['[5,10]',151200],['[-4,3]',0],['[0,3]',0],['[-4,-1]',24],
 ['(2,5]',60],['(5,10]',30240],['(-4,3]',0],['(0,3]',6],['(-4,-1]',-6],
 ['(2,5)',12],['(5,10)',3024],['(-4,3)',0],['(0,3)',2],['(-4,0)',-6]
].forEach(t=>{
  r=F(t[0]),k=t[1],console.log(t[0]+' -> '+r+' (check '+k+ (k==r?' ok)':' fail)'))
})
```
```
<pre id=O></pre>
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 25 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
Ugly as hell!
```
Å¯J q, rÈ°+Uø'()õY-Uø')Ã×
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=xa9KIHEsIHLIsCtV%2bCcoKfVZLVX4JynD1w&input=WwoiWzIsNSkiCiJbNSwxMCkiCiJbLTQsMykiCiJbMCwzKSIKIlstNCwwKSIKCiJbMiw1XSIKIls1LDEwXSIKIlstNCwzXSIKIlswLDNdIgoiWy00LC0xXSIKCiIoMiw1XSIKIig1LDEwXSIKIigtNCwzXSIKIigwLDNdIgoiKC00LC0xXSIKCiIoMiw1KSIKIig1LDEwKSIKIigtNCwzKSIKIigwLDMpIgoiKC00LDApIgpdLW1S) (includes all test cases)
[Answer]
# [Haskell](https://www.haskell.org/), 94 bytes
```
f=(\(h:a,_:b)->product[a!h..init b!last b]).span(','/=);c!')'=c!' '-1;c!'('=c!' '+1;c!_=read c
```
[Try it online!](https://tio.run/##LcfRCoMgFIDhVznCQGXmCHbVOHuRFnEyQ5lZqGOP7wp28/98jvLbhlDrguIlXEdq7CbZPPe0zR9TemJOax99gYkFyscGqfNOUXDFbygfhnHJ8Sjwpj0l/rqeGjFZmsHUlXwEBB@LTWQKXCC77Qsaltq36j78AA "Haskell – Try It Online")
[Answer]
# [Julia 0.4](http://julialang.org/), 64 bytes
```
s->prod((x=parse(s[2:end-1]).args)[]+(s[1]<41):x[2]-(s[end]<42))
```
[Try it online!](https://tio.run/##yyrNyUz8n2b7v1jXrqAoP0VDo8K2ILGoOFWjONrIKjUvRdcwVlMvsSi9WDM6VhsoaBhrY2KoaVURbRSrC@QCVQAFjDQ1/zsUZ@SXK6RpKEUb6ZhqKmlyoQjEIgtooKvQQFcRrWukY4QmYqIDdAumENCg/wA "Julia 0.4 – Try It Online")
Based on [Alex A's answer](https://codegolf.stackexchange.com/a/66312/98541)
# [Julia 1.0](http://julialang.org/), 69 bytes
```
s->prod((:)(Meta.parse(s[2:end-1]).args+[s[1]<'*',-(s[end]<'*')]...))
```
[Try it online!](https://tio.run/##yyrNyUw0rPifZvu/WNeuoCg/RUPDSlPDN7UkUa8gsag4VaM42sgqNS9F1zBWUy@xKL1YO7o42jDWRl1LXUcXKAmUAnM0Y/X09DQ1/zsUZ@SXK6RpKEUb6ZhqKmlyoQjEIgtooKvQQFcRrWukY4QmYqIDdAqmENCg/wA "Julia 1.0 – Try It Online")
[Answer]
# [Pip](https://github.com/dloscutoff/pip), 20 bytes
```
$*VaR^"(][)"['U"+1"]
```
[Replit!](https://replit.com/@dloscutoff/pip) Or, verify all test cases with this 22-byte version in Pip Classic: [Try it online!](https://tio.run/##Tc49DgIhEAXgfk9BiAW4kDAs0Gm8gI2FDZk1VsbEYrOWxrMjy6/dvMm8L7M8l/AJu/31fpkpQ8@ppzBSOgLF8CVncmK3@c3j8AheC8vJ4Ui0GbwVoFIAC1oNXhoxpRxn1ce4Vq0T@5gqW2EDsAFFwC5gFyRgIVglnBpYEyalTcx/AKuAS@sCSJeA/LbOAK9A7vPez2@ndb6SLsj19QM "Pip – Try It Online")
### Explanation
Conveniently, `,` is Pip's range operator; it is inclusive on the lower end and exclusive on the upper end. So if we turn the brackets into appropriate tweaks to the numbers, we can use eval to generate the range.
```
$*VaR^"(][)"['U"+1"]
   aR                 In the input, replace each string in
      "(][)"           This string
     ^                 Split into a list of characters
                      with the corresponding string in
            [      ]  this list:
             'U        ( becomes U (increment the following number)
               "+1"    ] becomes +1 (add 1 to the preceding number)
                       [ and ) don't have a corresponding replacement, so they are
                       simply deleted (leaving the numbers unchanged)
  V                   Evaluate the result as a Pip expression
$*                    Fold on multiplication
```
]