4 ms·
I think the main difficulty in converting your example to a functional style is how to express the idea of a for loop which builds up a result as it goes along,
by voyou 12y ago
I think the main difficulty in converting your example to a functional style is how to express the idea of a for loop which builds up a result as it goes along, without using a mutable variable to store this result. Here's an attempt to explain how that the ideas in the parent are helpful in solving that problem.
You can think of the body of a for loop in python as the body of a function. In that case, a for loop is like the built-in map function, which applies that function to every element of the list. So convert your for loop into:
def body(email):
domain = email.split("@")[1]
if domain not in domains:
domains.append(domain)
And instead of a for loop we can use the standard function, 'map'.
domains = []
map(body, emails)
Now, obviously the data here isn't immutable. But what if, instead of changing 'domains' every time the function is called, we passed in the current value of 'domains', and returned a changed value, like so:
def body(domains, email):
domain = email.split("@")[1]
if domain not in domains:
return domains + [domain]
else:
return domains
Then, we could apply this function to each element of the list in turn, passing the current list of domains at each stage to the body. This is the standard function 'reduce' in Python (which the parent calls by its other common name, 'fold'):
domains = reduce(body, emails, [])
You could think of 'reduce' in python being implemented like:
def reduce(func, l, currentResult):
for item in list:
currentResult = func(currentResult, item)
return currentResult
Or, it could also be implemented recursively, which means it wouldn't need to use mutation internally:
def reduce(func, l, currentValue):
if len(l) == 0:
return currentValue
else:
return reduce(func, l[1:], func(currentValue, l[0]))
Many for loops that build up a result can be expressed instead using 'reduce', so reduce is one of the most important building blocks of functional programming.
- stevesimmons 12y agoExcept you'd never write it like that in idiomatic Python. Your reduce's repeated list copying/appending/searching kills performance. Instead you would do something like this: domains = set( email.split('@')[-1] for email in open(path) )
- innguest 12y agoHe's pretending python compiles to something sane. FP spoils you with great compilers.
- sanderjd 12y agoThis is a great explanation and I hope it will help your parent commenter realize that, while different and not trivial, this stuff really isn't dark magic and really doesn't require a master's degree level of study to grok.
- chris_mahan 12y agoI think my comment is going to be that, from reading the parent, I understand that functional programming moves the code to the data and not the data through the code. I can't do the mental gymnastics to think about the code that way. When I think about the purpose of the code, the result of the code, before the code has been written, I do this by "compiling and running" in my head. Of course, there's no actual compiling. There's just thinking. When I reason about the code, either code I'm going to write, code I wrote, or code other people wrote, I execute the code in my head. I'm currently building a web-scraping system, to look information on partner web site. I'm using python 3, selenium, pyodbc to sql server. I'm also developing the same in C# (3.5) using the webbrowser component in systems.forms. It's got a lot of moving parts, lots of languages involved. I read the documentation for the tools, then I assemble in my head, essentially "running the code" in my head, and then, once all the edge cases are dealt with (are there iframes, popups, ajax async calls, flash and pdfs) then I design on paper, with boxes, and then, later, later, if it all works in my head, then I code it. Can't do that if I can't reason in my head about what the program is going to do, exactly. Functional Programming, for me, does not fit in my mental model, so I can't use it, regardless of actual implementation.
- SotallyTober 12y agoThis is partially because you're shoe horning functional ideas into an imperative language. When you have no choice but to use maps and folds you quickly build up mental models of how to do what you normally do with for loops: accumulate (fold), transform (map), or generate (zipWith).
- innguest 12y agoThe problem with your approach is it produces this mess: http://qt-project.org/doc/qt-4.8/widgets-analogclock.html http://qt-project.org/doc/qt-4.8/widgets-analogclock.html When you could instead say just what you mean in functional programming: http://elm-lang.org/edit/examples/Intermediate/Clock.elm http://elm-lang.org/edit/examples/Intermediate/Clock.elm The most important skill for a programmer is to be able to learn new things. Especially when they're there to help you.