| Author |
Message |
< Erlang ~ Simple loops |
| Jigar Gosar |
Posted: Wed Oct 24, 2007 4:02 pm |
|
|
|
Joined: 09 Oct 2007
Posts: 9
|
here is the code i came up with for printing numbers from 1 to Count.
using guards
Code:
print(Count) -> print(1,Count).
print(X,Count) when (X < Count) or (X == Count) ->
io:fwrite("~p~n",[X]),
print(X+1,Count);
print(X,Count) -> [].
using if
Code:
print2(Count) -> print(1,Count).
print2(X,Count) ->
if
(X < Count) or (X == Count) ->
io:fwrite("~p~n",[X]),
print2(X+1,Count)
end.
is there a better way or am I on the right track?
this is the smallest code I came up with, but this has problem of stack overflow, am I correct?
Code:
print3(0) -> [];
print3(Count) ->
print3(Count-1),
io:fwrite("~p~n",[Count]).
Please advise on any any other better alternative. and please comment on the merits of the solutions provided above.
I am new to erlang, and looking for better way of doing things. |
|
|
| Back to top |
|
| Adam |
Posted: Fri Oct 26, 2007 3:24 pm |
|
|
|
User
Joined: 23 Aug 2006
Posts: 71
Location: London
|
The last version is the most Erlang-like implementation, but you are correct that it will produce a large stack given high numbers. A better implementation requires a single change:
Code: print3(0) -> [];
print3(Count) ->
io:fwrite("~p~n",[Count]),
print3(Count-1).
This way, the last line will not be saved on the stack as the Erlang compiler recognizes and optimizes tail recursion.
The problem is that print3 counts backwards. If you must count starting from 1 your first implementation is the most correct one. It can be made a little prettier like this:
Code: print4(Count) ->
print4(1, Count).
print4(Count, Count) ->
ok;
print4(X, Count) ->
io:fwrite("~p~n", [X]),
print4(X + 1, Count). |
_________________ Adam
Erlang Training & Consulting |
|
| Back to top |
|
| Jigar Gosar |
Posted: Fri Oct 26, 2007 8:33 pm |
|
|
|
Joined: 09 Oct 2007
Posts: 9
|
thanks,
The problem with print4 is that it doesn't print count. i.e. if I pass 3, only 1 and 2 will be printed and not 3. Thats the reason I came up with such convoluted alternatives using guards and if.
But now looking at your solution, by just making a small change 3 can also be printed.
heres the mod.
Code:
print4(Count+1, Count) ->
ok;
But, its still more code than that of other imperative languages.
Functional languages take pride in conciseness of the code, and typical cases like quick sort are given to sell functional languages to imperative programmers.
I think this proves that there does exist a common case where functional code tends to become longer (although marginally) than the imperative counterpart.
I do acknowledge that there are many instances where functional code will beat the crap out of imperative languages in terms of LOC.
thanks for the reply. |
|
|
| Back to top |
|
| Adam |
Posted: Mon Oct 29, 2007 4:09 pm |
|
|
|
User
Joined: 23 Aug 2006
Posts: 71
Location: London
|
Well, compared to something imperative like:
Code: function print4(Count) {
int i;
for(i = 0; i > Count; i++)
print i;
return true;
}
It's five lines, about the same as print4 in Erlang (print4/1 is just syntactic sugar). Not such a big difference, yes?
Coding Erlang I don't even think about for-loops any more. Recursion becomes part of your mindset. Most problems people seem to have is when they haven't gotten used to a new mindset yet. |
_________________ Adam
Erlang Training & Consulting |
|
| Back to top |
|
| Jigar Gosar |
Posted: Wed Oct 31, 2007 4:17 pm |
|
|
|
Joined: 09 Oct 2007
Posts: 9
|
I agree its just 4 lines, but the syntactic sugar of print4/1 is necessary to make it as convenient to use as its imperative counterpart. As I have admitted before, the code is marginally longer in Erlang.
The point I was trying to make is that, code doesn't necessarily become smaller, in Erlang (and as such in functional programming languages), as some people claim.
I think it is easy to convert any for loop into its recursion counterpart, by following this print example.
But thinking in recursion is what take time, because I still think in imperative terms and then convert my code to functional.
The notion of recursion and syntax of Erlang is very overwhelming for new developers in general and my colleagues in particular. Its difficult for me to sell Erlang as a better programming languages to my peers. The only selling point that makes sense is the built in concurrency and distributed nature of Erlang, and the hence build massively scalable server.
Erlang doesn't seem suitable for general purpose programming, at least on its face. I would like to hear some comments on this. Specifically, for what other types of application is Erlang more suitable, besides distributed servers.
Also Lastly I would like to point a ruby example:
Code:
def count
count.times(){|x| puts x}
end
Its intuitive, readable, concise and beautiful all at the same time  |
|
|
| Back to top |
|
| Mazen |
Posted: Thu Nov 01, 2007 5:12 pm |
|
|
|
User
Joined: 20 Jul 2006
Posts: 164
Location: London
|
Jigar Gosar wrote:
The point I was trying to make is that, code doesn't necessarily become smaller, in Erlang (and as such in functional programming languages), as some people claim.
IMHO The difference in such a small example is marginal and doesn't really show anything sensible.
If you would compare bigger commercial applications I think the difference would be more obvious (for or against).
Further more; syntetic sugar is not needed except for when you use the function as an API towards other applications. In all other cases you don't really create 2 functions with different number arities just for looks even if it would make sense in some situations where you want to provide a nicer environment for real time tracing.
/M |
|
|
| Back to top |
|
| zambal |
Posted: Thu Nov 01, 2007 8:29 pm |
|
|
|
User
Joined: 03 Jul 2007
Posts: 11
|
Hi,
Hereby another solution, by using the lists library:
Code:
print6(N) ->
lists:foreach(
fun(X)-> io:fwrite("~p~n",[X]) end,
lists:seq(1, N)).
It's still recursive, but hided by the library functions. If you'd import the used functions in your module, it could be as short as:
Code:
print6(N) ->
foreach(
fun(X)-> fwrite("~p~n",[X]) end,
seq(1, N)).
I'm not sure what solution is more idiomatic, but I think this one's pretty readable.
-zambal |
|
|
| Back to top |
|
| gbulmer |
Posted: Thu Nov 01, 2007 11:37 pm |
|
|
|
Joined: 01 Nov 2007
Posts: 1
|
Jigar Gosar wrote: I agree its just 4 lines, but the syntactic sugar of print4/1 is necessary to make it as convenient to use as its imperative counterpart. As I have admitted before, the code is marginally longer in Erlang.
The point I was trying to make is that, code doesn't necessarily become smaller, in Erlang (and as such in functional programming languages), as some people claim.
I really believe there is much more to comparing programming languages than counting lines of code, but if that is your dominant criteria, how about something like:
Code: count(N) -> [io:format("~w~n",[X]) || X <- lists:seq(1,N)], ok.
Quote: But thinking in recursion is what take time, because I still think in imperative terms and then convert my code to functional.
The notion of recursion and syntax of Erlang is very overwhelming for new developers in general and my colleagues in particular.
I have learned and used more than a dozen programming languages commercially (and many more for fun); the syntax stops being a problem after a day or two (except for Perl ).
IMHO, You will need to unlearn habits that have been successful for you in an imperative, iterative language, to 'get' Functional Programming Languages, rather than try to translate. Did you learn about proof by induction in math at school? You may be able to use thinking about those proofs as a path.
Quote: Its difficult for me to sell Erlang as a better programming languages to my peers. The only selling point that makes sense is the built in concurrency and distributed nature of Erlang, and the hence build massively scalable server.
I strongly believe you should not try to sell Erlang to developers unless it is clearly superior to their current technology. There is a significant cost and risk associated with learning and deploying a new technology. It is much better to wait until you have a project where those costs and risks are dwarfed by Erlangs benefits instead of trying to sell Erlang into unsuitable contexts. You do Erlang, your colleagues and yourself no favours otherwise.
Sorry for the harsh position, but the industry statistics are still that more than 75% of money spent on software never yields any results, and I believe inappropriate use of technology is a significant factor in that level of failure.
Quote:
Erlang doesn't seem suitable for general purpose programming, at least on its face. I would like to hear some comments on this. Specifically, for what other types of application is Erlang more suitable, besides distributed servers.
Maybe you could outline the sort of systems you and your colleagues build, and maybe someone can help you see where Erlang may be relevant.
Quote:
Also Lastly I would like to point a ruby example:
Code:
def count
count.times(){|x| puts x}
end
Its intuitive, readable, concise and beautiful all at the same time 
It may have those properties, but I doubt it because it is incorrect. Maybe you were aiming for:
Code:
def count(n)
n.times(){|x| puts x+1}
end
Which prints a sequence of integers, one per line, starting at 1.
I accept the Ruby is shorter than the Erlang, but maybe we can agree that printing a finite sequence of integers isn't a very good fit with Erlang, and leave it at that. |
|
|
| Back to top |
|
|
|
All times are GMT
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|
|