Changeset 8723 in project


Ignore:
Timestamp:
02/23/08 22:31:38 (12 years ago)
Author:
mfredrickson
Message:

Adding info for (let ...) binding and blocks.

File:
1 edited

Legend:

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

    r8716 r8723  
    2323procedural fashion (like you would in Pascal, for example) or in a
    2424functional style (a bit like Haskell or ML) and you can even
    25 experiment with message-passing like in Erlang or logic programming
    26 like you would with Prolog.
     25experiment with message-passing like in Erlang, logic programming
     26like you would with Prolog, or stack languages like Forth and Factor.
    2727
    2828=== Origins
     
    216216artifact of an imperative programming style and in clean code you
    217217want to avoid using it.
     218
     219Scheme also allows the ''binding'' of local variables. Bound variables
     220behave like the defined variables above, however, they are only valid
     221within a local scope. The top-level variables we've seen are the equivalent
     222of a global in Ruby.
     223
     224The most common binding constructs are {{let}} and {{let*}}.
     225{{let}} allows for any number of bindings, none of which are related.
     226
     227<enscript highlight=scheme>
     228  (let ((a 5)
     229        (b 10))
     230    (+ a b))
     231</enscript>
     232
     233{{let*}} is like let, except that the bindings are evaluated in order,
     234so subsequent bindings can reference earlier bindings.
     235
     236<enscript highlight=scheme>
     237  (let* ((a 5)
     238         (b (* 2 a)))
     239    (+ a b))
     240</enscript>
     241
     242There are other binding forms, such as {{letrec}} and the so-called
     243''named let''. More information about these forms can be found in
     244the [[http://schemers.org/Documents/Standards/R5RS/|Scheme specification]].
    218245
    219246=== Procedures
     
    332359allocate any more.  In the second example it will stay constant and
    333360simply loop forever.
     361
     362=== Blocks
     363
     364Ruby programmers will be familiar with ''blocks.'' Classic example in
     365Ruby is the {{map}} method used to iterate over a collection, executing
     366a ''block'' of code for each item in the collection.
     367
     368Ruby:
     369  >> [1, 2, 3, 4, 5].map { |x| x * x }
     370  => [1, 4, 9, 16, 25]
     371
     372Scheme also contains blocks, though we call them anonymous functions
     373usually. Functions are created using the {{(lambda args body...)}} body
     374form. This syntax is a little more verbose than Ruby's, but the trade off
     375is that more than one function can be passed as an argument, whereas Ruby
     376generally only allows one.
     377
     378Scheme:
     379  #;1> (map (lambda (x) (* x x)) '(1 2 3 4 5))
     380  (1 4 9 16 25)
     381
     382A more complicated example involves opening and closing files. Say we
     383wanted to create a utility like {{wc -l}} that counts the number of
     384lines in a file. In Ruby, it might look something like:
     385
     386<enscript highlight=ruby>
     387  count = 0
     388  File.open("myfile", 'r') { |fh|
     389      count += 1 while fh.gets
     390  }
     391  puts count
     392</enscript>
     393
     394Similarly, Scheme uses anonymous functions to create the same behavior:
     395
     396<enscript highlight=scheme>
     397  (with-input-from-file "filename"
     398    (lambda () (port-fold (lambda (line lines-so-far) (+ 1 lines-so-farc)) 0 read-line)))
     399</enscript>
     400
     401This Scheme code also showcases some typical functional style, using
     402a ''fold'' operation instead of incrementing the value of a variable.
     403
    334404
    335405== Data types
Note: See TracChangeset for help on using the changeset viewer.