Can I destructive rebind a local variable in haskell?

Dear haskeller,
Can I destructive rebind a local variable like this
import System.Directory
test filename = do
is_dir <- doesDirectoryExist filename
let filename = if not is_dir then filename else filename
putStrLn $ " filename " ++ filename
main = test "."
in GHCi 6.10.1 on WinXP, the ghci aborts silencely when I executes
"main"
after compile it into a executable file.
c:\USERS\home\learning_haskell\>testDirectory
testDirectory
C stack overflow in generated code
I have some code in scheme which works very well
(define (func x)
(let ((x x))
x))
By rebinding a formal variable, we can save naming some varaibles. I
am not good at naming a variable.
Thank you in advance
Best Regards
Chunye Wang

2009/1/6 Wang, Chunye (NSN - CN/Beijing)
Can I destructive rebind a local variable like this
import System.Directory test filename = do is_dir <- doesDirectoryExist filename let filename = if not is_dir then filename else filename
Nope. The "filename" on the right side of the = is the same as the "filename" on the left, so you're making an infinite loop, the same way: let x = x in x is an infinite loop. However you can make a new name as you are trying, you just can't reference the old one. e.g.: let filename = 42 Here would be just fine. However, for cases like this, it is useful that single quote is a valid identifier, so you can say: let filename' = if not is_dir then filename else filename (read "filename prime") Luke

Hi Luke
Thank you ! I got it :)
Best Regards
Chunye Wang

2009/1/6 Luke Palmer
2009/1/6 Wang, Chunye (NSN - CN/Beijing)
Dear haskeller, Can I destructive rebind a local variable like this
import System.Directory test filename = do is_dir <- doesDirectoryExist filename let filename = if not is_dir then filename else filename
Nope. The "filename" on the right side of the = is the same as the "filename" on the left, so you're making an infinite loop, the same way: let x = x in x is an infinite loop. However you can make a new name as you are trying, you just can't reference the old one. e.g.: let filename = 42
You can also reuse the name exactly by using bind+return instead of let: test filename = do is_dir <- doesDirectoryExist filename filename <- return $ if not is_dir then filename else filename I'm not a huge fan of the prime thing because it's tiny and easy to miss and if you forget it you probably won't get a type error, you'll just get a bug, possibly a subtle one. Besides, what's the next step? filename''? filename'''?

Hi Evan,
You can also reuse the name exactly by using bind+return instead of let: test filename = do is_dir <- doesDirectoryExist filename filename <- return $ if not is_dir then filename else filename
I'm not a huge fan of the prime thing because it's tiny and easy to miss and if you forget it you probably won't get a type error, you'll just get a bug, possibly a subtle one. Besides, what's the next step? filename''? filename'''?
Nice. Good solution. ``imperative style'' is not a bad idea when I'm
not used to the ``pure functional style''
E.g.
filename <- return $ combine filename "Makefile"
Similar to the other imperative language
filename = joinPath(filename,"Makefile")
and I often write similar code in EmacsLisp also.
It is not so buggy, because we live in "imperitive programming" for
long time
Best Regards
Chunye Wang

Nice. Good solution. ``imperative style'' is not a bad idea when I'm not used to the ``pure functional style''
E.g.
filename <- return $ combine filename "Makefile"
Similar to the other imperative language
filename = joinPath(filename,"Makefile")
I wouldn't consider it particularly imperative, it's just variable shadowing. It desugars to calling a function with a parameter that shadows the old variable. Of course, you could say a more functional way would be to use pointfree style or just nested calls to avoid naming the intermediate values. Then you can't intersperse IO actions... but it's good to avoid doing that anyway.
participants (3)
-
Evan Laforge
-
Luke Palmer
-
Wang, Chunye (NSN - CN/Beijing)