In functional programming, are local mutable variables with no side effects still considered “bad practice”?

Is having mutable local variables in a function that are only used internally, (e.g. the function has no side effects, at least not intentionally) still considered “non functional”?

e.g. in the “Functional programming with Scala” course style check considers any var usage as bad

My question, if the function has no side effects, is writing imperative style code still discouraged?

e.g. instead of using tail recursion with the accumulator pattern, what’s wrong with doing a local for loop and creating a local mutable ListBuffer and adding to it, as long as the input is not changed?

If the answer is “yes, they are always discouraged, even if there is no side effects” then what is the reason?

3

The one thing that is unequivocally bad practice here is claiming that something is a pure function when it isn’t.

If mutable variables are used in a way that is truly and completely self-contained, the function is externally pure and everyone is happy. Haskell in fact supports this explicitly, with the type system even ensuring that mutable references can’t be used outside the function that creates them.

That said, I think talking about “side effects” is not the best way to look at it (and is why I said “pure” above). Anything that creates a dependency between the function and external state makes things harder to reason about, and that includes things like knowing the current time or using concealed mutable state in a non-thread-safe way.

The problem isn’t mutability per se, it’s a lack of referential transparency.

A referentially transparent thing and a reference to it always have to be equal, so a referentially transparent function will always return the same results for a given set of inputs and a referentially transparent “variable” is really a value rather than a variable, since it can’t change. You can make a referentially transparent function that has a mutable variable inside; that isn’t a problem. It might be harder to guarantee the function is referentially transparent, though, depending on what you’re doing.

There’s one instance I can think of where mutability has to be used to do something that is very functional: memoization. Memoization is caching values from a function, so they don’t have to be recomputed; it’s referentially transparent, but it does use mutation.

But in general referential transparency and immutability go together, other than a local mutable variable in a referentially transparent function and memoization, I’m not sure there are any other examples where this is not the case.

5

It’s not really good to boil this down to “good practice” vs “bad practice”. Scala supports mutable values because they solve certain problems much better than immutable values, namely those that are iterative in nature.

For perspective, I’m fairly sure that via CanBuildFrom almost all immutable structures provided by scala do some sort of mutation internally. The point is that what they expose is immutable. Keeping as many values immutable as possible helps make the program easier to reason about and less error prone.

This doesn’t mean that you necessarily need to avoid mutable structures and values internally when you have a problem that is better suited to mutability.

With that in mind, a lot of problems that typically require mutable variables (such as looping) can be solved better with a lot of the higher order functions that languages like Scala provide (map/filter/fold). Be aware of those.

1

Aside from potential issues with thread safety, you also typically lose a lot of type safety. Imperative loops have a return type of Unit and can take pretty much any expression for inputs. Higher-order functions and even recursion have much more precise semantics and types.

You also have many more options for functional container processing than with imperative loops. With imperative, you basically have for, while, and minor variations on those two like do...while and foreach.

In functional, you have aggregate, count, filter, find, flatMap, fold, groupBy, lastIndexWhere, map, maxBy, minBy, partition, scan, sortBy, sortWith, span, and takeWhile, just to name a few more common ones from Scala’s standard library. When you become accustomed to having those available, imperative for loops seem too basic in comparison.

The only real reason to use local mutability is very occasionally for performance.

0

I would say it is mostly ok. What’s more, generating structures this way might be a good way to improve performances in some cases. Clojure has takled this problem by providing Transient data structures.

The basic idea is to allow local mutations in a limited scope, and then to freeze the structure before returning it. This way, your user can still reason about your code as if it were pure, but you are able to perform in place transformations when you need to.

As the link says:

If a tree falls in the woods, does it make a sound? If a pure function
mutates some local data in order to produce an immutable return value,
is that ok?

Having no local mutable variables does have one advantage–it makes the function more friendly towards threads.

I got burned by such a local variable (not in my code, nor did I have the source) causing a low-probability data corruption. Thread safety wasn’t mentioned one way or another, there was no state that persisted across calls and there were no side effects. It didn’t occur to me that it might not be thread safe, chasing a 1 in 100,000 random data corruption is a royal pain.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật