Changeset 8711 in project


Ignore:
Timestamp:
02/23/08 21:24:25 (12 years ago)
Author:
sjamaan
Message:

Document regexes and some other stuff

File:
1 edited

Legend:

Unmodified
Added
Removed
  • wiki/chicken-for-ruby-programmers

    r8709 r8711  
    254254</enscript>
    255255
     256In Scheme, recursion is a very important tool.  In fact, it is so
     257important that the Scheme standard ''demands'' tail call optimization
     258(TCO), which basically means that you can have infinite recursion as
     259long as the recursive procedure does not need to do anything after it
     260returns.  That sounds a bit strange, so here's an example:
     261
     262Ruby:
     263
     264  irb(main):010:0> def add_up_to(num)
     265  irb(main):011:1>   if num.zero?
     266  irb(main):012:2>     0
     267  irb(main):013:2>   else
     268  irb(main):014:2*     add_up_to(num - 1) + num
     269  irb(main):015:2>   end
     270  irb(main):016:1> end
     271  => nil
     272  irb(main):017:0> add_up_to(4)
     273  => 10
     274  irb(main):018:0> add_up_to(9999)
     275  SystemStackError: stack level too deep
     276
     277Chicken:
     278
     279  #;2> (define (add-up-to x)
     280         (if (zero? x)
     281             0
     282             (+ (add-up-to (sub1 x)) x)))
     283  #;3> (add-up-to 4)
     284  10
     285  #;4> (add-up-to 9999)
     286  49995000
     287
     288In most other Schemes, however, this will break just like in Ruby,
     289because when the {{(+ (add-up-to (sub1 x)) x)}} expression is
     290evaluated, the recursive call to {{add-up-to}} creates a new stack
     291frame so that when it returns the x can be added to the result.
     292All Schemes know that when there is nothing that needs to be done
     293after a procedure returns, there is no point in returning to the
     294procedure that called it at all, instead it can just return directly
     295to the procedure that called the current procedure, so the call can
     296be optimized to become a ''goto'', replacing the current stack frame:
     297
     298Ruby still can't handle it:
     299
     300  irb(main):027:0> def add_up_to(x)
     301  irb(main):028:1>   def inner(x, y)
     302  irb(main):029:2>     if x.zero?
     303  irb(main):030:3>       y
     304  irb(main):031:3>     else
     305  irb(main):032:3*       inner(x, x+y)
     306  irb(main):033:3>     end
     307  irb(main):034:2>   end
     308  irb(main):035:1>   inner(x, 0)
     309  irb(main):036:1> end
     310  => nil
     311  irb(main):037:0> add_up_to(9999)
     312  SystemStackError: stack level too deep
     313
     314Scheme (this works in all Schemes):
     315
     316  #;2> (define (add-up-to x)
     317         (define (inner x y)
     318           (if (zero? x)
     319               y
     320               (inner (sub1 x) (+ y x))))
     321         (inner x 0))
     322  #;3> (add-up-to 4)
     323  10
     324  #;4> (add-up-to 9999)
     325  49995000
     326
     327As you'll notice, this version is a lot faster in Chicken too because
     328it does not have to travel back through all those empty "stack
     329frames".  You can also notice the difference when you remove the stop
     330condition and you look at your OS's process list.  Then Chicken's
     331memory usage just keeps going up until it breaks because it can't
     332allocate any more.  In the second example it will stay constant and
     333simply loop forever.
    256334
    257335== Data types
     
    500578Ruby:
    501579
    502   //
     580   m = /(.)(.)(\d+)(\d)/.match("THX1138.")
     581   m[0]       #=> "HX1138"
     582   m[1, 2]    #=> ["H", "X"]
     583   m[1..3]    #=> ["H", "X", "113"]
     584   m[-3, 2]   #=> ["X", "113"]
    503585
    504586Chicken:
     587
     588  #;1> (use regex)
     589  ; loading library regex ...
     590  #;2> (string-search "(.)(.)(\\d+)(\\d)" "THX1138.")
     591  ("HX1138" "H" "X" "113" "8")
     592
     593The {{string-search}} procedure automatically transforms
     594the first string to a regexp.  You can also do that yourself:
     595
     596  #;3> (string-search (regexp "(.)(.)(\\d+)(\\d)") "THX1138.")
     597  ("HX1138" "H" "X" "113" "8")
     598
     599The advantage of doing this is that when you need to match several
     600strings you can use the same regexp so it doesn't have to precompile
     601the regexp every time you call {{string-search}}.
    505602
    506603=== Hashes
Note: See TracChangeset for help on using the changeset viewer.