Reputation: 610
I've found block scope {
and }
in JavaSciprt after ES6 is useful in development, and frequently use for testing small code blocks including the same variable names in different versions side by side.
How do you do in Haskell? What's the best prctice?
Upvotes: 1
Views: 197
Reputation: 152682
There's a few choices, depending on what context you're looking for. I think the thing most likely to be useful to you is that each binding can be associated with a where
block, and the variables in each block are independent. So, for example:
foo = component1 * component2 where
component1 = x + y where
x = 32
y = sqrt (magnitude velocity)
component2 = x + y where
x = magnitude acceleration
y = 5.5
In each case, the x
and y
are in scope only for the component that's currently being defined.
One place that doesn't always work well is in do blocks. There's two reasons for this: first, the associated where
block's scope doesn't include any of the variables bound by statements in the do
block, and second, because sometimes the thing you want is differing scopes for differing parts of the do
block. For those cases, let
/in
works better. For example:
foo = do
let x = print "hi"
y = putStrLn "hi"
in do
x
y
-- x and y are no longer in scope here
v <- readLn :: IO Int
let x = print [v] -- v is in scope, unlike a where block
y = print v
in do
x
y
Again, in each case, the x
and y
are in scope for the body of the nested do
block, but not in scope in the outer do
block. It is also possible to add something to the outer do
block's scope, though of course the syntax has to be different (or how would the compiler know which one you wanted?). The difference is that you leave off the in
, so:
foo = do
v <- readLn :: IO Int
let w = v + v
print w
Upvotes: 2
Reputation: 10645
If you have some code like this:
foo x y = do
print x
print y
And you want to temporarily test changing the value of x
then you can just write:
foo x y = let x = 2 in do
print x
print y
This let
syntax creates a new scope and "overwrites" (shadows) any variables with the same name that were previously bound. You can use this let almost everywhere, e.g.:
foo x y = do
let x = 2 in print x
print y
Or even:
foo x y = do
print (let x = 2 in x)
print y
It is really flexible.
Upvotes: 4