-=:: FBSL ::=-

(C)2001-2010 by Gerome GUILLEMIN, Mehdi BOUAZIZ and Mike LOBANOVSKY
It is currently Thu Sep 09, 2010 11:58 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Another Range() function
PostPosted: Sat Dec 12, 2009 7:25 pm 
Offline
FBSL geek
FBSL geek
User avatar

Joined: Sun Oct 29, 2006 3:22 pm
Posts: 284
Location: France (Nord)
I tried to improve my Range() function inspired by Killrami.

Killrami wrote:
Does FBSL have a range function similar to Pythons?


Code:
#AppType Console

Macro PrintItem(item) = Printf("%s ", $item)
Macro Array_Print(vector) = Map(PrintItem, vector)

Array_Print(Range(10))
Print
Array_Print(Range(3, 12))
Print
Array_Print(Range(5, 15, 3))
Print
Array_Print(Range(3, 12, 2.5))
Print
Array_Print(Range(8, 1))
Print
Array_Print(Range(4, 2, 0.25))
Print
Array_Print(Range())

Print: Pause

Function Range(ParamArray params)
   Dim %arg = Count(params)
   Dim rstart = 1, rend, rstep = 1
   Dim seq[] ={}
   Select Case arg
      Case 0
         Return rstart - 1
      Case 1
         rend = params[0] + 1
      Case 2
         rstart = params[0]
         rend = params[1] + 1
      Case 3
         rstart = params[0]
         rend = params[1] + 1
         rstep = params[2]
   End Select
   If rstart > rend Then
      While rstart >= rend - 1
         seq[Count(seq)] = rstart
         rstart = rstart - Abs(rstep)
      Wend
   Else
      While rstart < rend
         seq[Count(seq)] = rstart
         rstart = rstart + rstep
      Wend
   End If
   Return seq
End Function


I'm not very satisfied with my script. I think that it looks like a patched-up job. Without a doubt, one can do it better.
:wink:

_________________
> B e r t r a n d <


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 19, 2009 3:03 pm 
Offline
FBSL Administrator
FBSL Administrator
User avatar

Joined: Tue Apr 19, 2005 7:22 am
Posts: 890
Dear Bertrand,

I am afraid, the code which you propose here IS NOT directly inspired by Killrami's question. His question was about Python's version of the Range() function while your code behaves more like the PHP v4/5 version of Range().

IMO Python's function expects its parameters in the following generic order:

1. input: ascending order (start, stop, +step) whereby stop >= start. Also, the console printout of a special case of 1 parameter e.g. Range(10) will be "0,1,2,3,4,5,6,7,8,9" but not "1,2,3,4,5,6,7,8,9,10" as your function does;

2. input: descending order (start, stop, -step) whereby stop <= start.

In other words, the enumeration order (ascending or descending) is explicitly determined by the sign of the step parameter and if the magnitude of the start and stop parameters does not match the step sign used, the function will fail. This algo, of course, will have a simpler (perhaps also faster) implementation than you suggest.

Your function behaves like its PHP's counterpart: step is positive and its equivalent sign is determined by whether start is smaller or greater than stop. Clearly enough, this algo requires more checks and substitutions and is perhaps always slower than the Python-like implementation.

So which of the two implementations are we going to optimize? ;-)

Mike :D

_________________
Mike
(2.2GHz Intel Core2 Duo w/ 4GB RAM, GeForce 8600 w/ 1GB VRAM, Windows XP Pro Russian Sp3)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 19, 2009 4:37 pm 
Offline
FBSL geek
FBSL geek
User avatar

Joined: Sun Oct 29, 2006 3:22 pm
Posts: 284
Location: France (Nord)
Yes, I didn't really go further into the question. It was just a first draft :wink:
I didn't remember how works the Python's function Range(). In fact I hesitated over the decision to start with 0 or 1 (my Logo experience decided in favour of 1, probably wrongly).
I admit to having struggled to find a solution for the descending order and I lazily chose the easier one for me.
And what is more, I don't know anything about PHP.

Quote:
So which of the two implementations are we going to optimize?

Personaly, I would opt for the simpler and faster implementation or for a solution which satisfies Killrami's request in a better way (so, not my solution) ...
:)

_________________
> B e r t r a n d <


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 19, 2009 10:20 pm 
Offline
FBSL Administrator
FBSL Administrator
User avatar

Joined: Tue Apr 19, 2005 7:22 am
Posts: 890
taobert wrote:
Yes, I didn't really go further into the question. It was just a first draft :wink:
I didn't remember how works the Python's function Range(). In fact I hesitated over the decision to start with 0 or 1 (my Logo experience decided in favour of 1, probably wrongly).
I admit to having struggled to find a solution for the descending order and I lazily chose the easier one for me.
And what is more, I don't know anything about PHP.

Quote:
So which of the two implementations are we going to optimize?

Personaly, I would opt for the simpler and faster implementation or for a solution which satisfies Killrami's request in a better way (so, not my solution) ...
:)


OK, with all this in mind, first we'll work out the design rules for our more-or-less optimized Python-like implementation of Range() function:

1. Macros are generally handy but not here: PrintItem(item) would require an additional Print to go to a new line after the entire array contents are printed out while Array_Print(vector) would imply a call to an extra function which means additional time overhead for setting up Map() calls;

2. The implementation should provide for a special case with only 1 parameter given which is essentially the Range(end - start) parameter with a step = 1;

3. The generic parameter format is Range(start, end, (+/-)step) with start <= end for a positive step and start >= end for a negative step while any other parameter set (barring case 2 above) is illegal.

4. Array_Print is essentially an application-specific feature. Other tasks may require other ways to intercept/handle/respond to invalid parameter values or combinations so "If Count(params) = 0 Then" may need to be logically Or'ed accordingly with any other invalid conditions to produce the desired result for early error detection in the caller code.

Following these guidelines, I can suggest the following implementation:
Code:
#AppType Console

Array_Print(Range(10))
Array_Print(Range(3, 12))
Array_Print(Range(5, 15, 3))
Array_Print(Range(3, 12, 2.5))
Array_Print(Range(4, 2, -0.25))
Array_Print(Range(8, 1)) ' invalid params ignored => no console printout
Array_Print(Range(4, 2, 0.25)) ' invalid params ignored => no console printout
Array_Print(Range()) ' invalid params ignored => no console printout

Pause

Function Range(ParamArray params)
   Dim seq[] = {Nothing} ' initialization allows for early detection of invalid params
   ' volatile Count used below, and Count = 3
   ' is naturally expected in For/Next that follows
   If Count(params) = 0 /* Or any_other_invalid_case */ Then
      Return seq
   ElIf Count = 1 Then
      params[1] = params[0] - 1: params[0] = 0: params[2] = 1
   ElIf Count = 2 Then
      params[2] = 1
   End If
   For Dim i = 0 To %((params[1] - params[0]) / params[2])
      seq[i] = params[0] + i * params[2]
   Next
   Return seq
End Function

Sub Array_Print(vector)
   ForEach Dim o In vector
      If o Is Nothing Then Exit Sub ' early detection working else empty CRLF's printed
      Printf("%s ", $o)
   Next
   Print
End Sub


Does this implementation still produce a "patched-up job" feeling?

Mike :)

_________________
Mike
(2.2GHz Intel Core2 Duo w/ 4GB RAM, GeForce 8600 w/ 1GB VRAM, Windows XP Pro Russian Sp3)


Last edited by Mike Lobanovsky on Sat Dec 19, 2009 11:14 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 19, 2009 10:26 pm 
Offline
FBSL Administrator
FBSL Administrator
User avatar

Joined: Sat Mar 12, 2005 8:06 pm
Posts: 2877
Location: Paris -- France
Mike Lobanovsky wrote:

Does this implementation still produce a "patched-up job" feeling?

Mike :)


Hey Mike !!!
Simply A M A Z I N G !!!

_________________
Yours,

(¯`·._.·[Gerome GUILLEMIN]·._.·´¯)
:: Full SETUP w. HELP 07th of September 2010 ::
http://gedd123.free.fr/FBSLv3.exe [3.4.0.7]
http://gedd123.free.fr/FBSLv3bin.zip [minimal]
Laissons les jolies femmes aux hommes sans imagination. / Let us leave pretty women to men without imagination.(M.Proust)
The success is a defeat for the one who does not want to dance any more! (H.F. Thiefaine)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 20, 2009 12:54 pm 
Offline
FBSL geek
FBSL geek
User avatar

Joined: Sun Oct 29, 2006 3:22 pm
Posts: 284
Location: France (Nord)
Mike Lobanovsky wrote:

Does this implementation still produce a "patched-up job" feeling?

Mike :)

Absolutely not ! ... really clearer.
:D
Thanks for the lesson.
I like your 'Array_Print' better than mine. I was too much tempted to play with the Map function (one more conditionning by Logo or Lisp-like languages)
:wink:

_________________
> B e r t r a n d <


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 0 guests


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 post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group